@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,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useActiveOrganization, useAuth, useAuthenticate, useAuthPlugin } from "@better-auth-ui/react";
3
+ import { Gear, Person } from "@gravity-ui/icons";
4
+ import { cn, Tabs } from "@heroui/react";
5
+ import { useEffect, useMemo } from "react";
6
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
7
+ import { OrganizationPeople } from "./organization-people";
8
+ import { OrganizationSettings } from "./organization-settings";
9
+ /**
10
+ * Organization management shell: tabs for profile / danger zone and for
11
+ * people (members / invitations). Path segments come from
12
+ * `useAuthPlugin(organizationPlugin).viewPaths.organization`.
13
+ */
14
+ export function Organization({ className, hideNav, path, variant, view, ...props }) {
15
+ if (!view && !path) {
16
+ throw new Error("[Better Auth UI] Either `view` or `path` must be provided");
17
+ }
18
+ const { authClient, basePaths, localization, navigate } = useAuth();
19
+ useAuthenticate(authClient);
20
+ const { localization: organizationLocalization, viewPaths: organizationViewPaths, slug } = useAuthPlugin(organizationPlugin);
21
+ const { data: activeOrganization, isPending } = useActiveOrganization(authClient);
22
+ useEffect(() => {
23
+ if (!isPending && !activeOrganization) {
24
+ navigate({
25
+ to: `${basePaths.settings}/${organizationViewPaths.settings?.organizations}`,
26
+ replace: true
27
+ });
28
+ }
29
+ }, [
30
+ basePaths.settings,
31
+ isPending,
32
+ navigate,
33
+ organizationViewPaths.settings?.organizations,
34
+ activeOrganization
35
+ ]);
36
+ const currentView = useMemo(() => {
37
+ if (view)
38
+ return view;
39
+ const match = Object.entries(organizationViewPaths.organization).find(([, segment]) => segment === path);
40
+ return match?.[0];
41
+ }, [view, path, organizationViewPaths.organization]);
42
+ if (!currentView) {
43
+ const validPaths = Object.values(organizationViewPaths.organization).join(", ");
44
+ throw new Error(`[Better Auth UI] Unknown organization path "${path}". Valid paths are: ${validPaths}`);
45
+ }
46
+ if (!isPending && !activeOrganization) {
47
+ return null;
48
+ }
49
+ return (_jsxs(Tabs, { className: cn(className), orientation: "horizontal", selectedKey: currentView, ...props, children: [!hideNav && (_jsx(Tabs.ListContainer, { children: _jsxs(Tabs.List, { "aria-label": localization.settings.settings, className: "max-w-fit overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden", children: [_jsxs(Tabs.Tab, { id: "settings", href: slug
50
+ ? `${basePaths.organization}/${slug}/${organizationViewPaths.organization.settings}`
51
+ : `${basePaths.organization}/${organizationViewPaths.organization.settings}`, className: "gap-2", onPress: (e) => e.target.scrollIntoView({
52
+ behavior: "smooth",
53
+ inline: "center"
54
+ }), children: [_jsx(Gear, { className: "text-muted" }), localization.settings.settings, _jsx(Tabs.Indicator, {})] }), _jsxs(Tabs.Tab, { id: "people", href: slug
55
+ ? `${basePaths.organization}/${slug}/${organizationViewPaths.organization.people}`
56
+ : `${basePaths.organization}/${organizationViewPaths.organization.people}`, className: "gap-2", onPress: (e) => e.target.scrollIntoView({
57
+ behavior: "smooth",
58
+ inline: "center"
59
+ }), children: [_jsx(Person, { className: "text-muted" }), organizationLocalization.people, _jsx(Tabs.Indicator, {})] })] }) })), _jsx(Tabs.Panel, { id: "settings", className: "px-0", children: _jsx(OrganizationSettings, { variant: variant }) }), _jsx(Tabs.Panel, { id: "people", className: "px-0", children: _jsx(OrganizationPeople, {}) })] }));
60
+ }
@@ -0,0 +1,4 @@
1
+ export type OrganizationsEmptyProps = {
2
+ onCreatePress: () => void;
3
+ };
4
+ export declare function OrganizationsEmpty({ onCreatePress }: OrganizationsEmptyProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuthPlugin } from "@better-auth-ui/react";
3
+ import { Briefcase } from "@gravity-ui/icons";
4
+ import { Button, EmptyState } from "@heroui/react";
5
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
6
+ export function OrganizationsEmpty({ onCreatePress }) {
7
+ const { localization: organizationLocalization } = useAuthPlugin(organizationPlugin);
8
+ return (_jsxs(EmptyState, { className: "flex flex-col items-center gap-4 text-center", children: [_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-surface-secondary", children: _jsx(Briefcase, { className: "size-5" }) }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: organizationLocalization.noOrganizations }), _jsx("span", { className: "text-sm text-muted", children: organizationLocalization.organizationsDescription })] }), _jsx(Button, { size: "sm", onPress: onCreatePress, children: organizationLocalization.createOrganization })] }));
9
+ }
@@ -0,0 +1,17 @@
1
+ import { type CardProps } from "@heroui/react";
2
+ import type { ComponentProps } from "react";
3
+ export type OrganizationsSettingsProps = {
4
+ className?: string;
5
+ variant?: CardProps["variant"];
6
+ };
7
+ /**
8
+ * Renders the organizations settings panel.
9
+ *
10
+ * Displays all organizations the user belongs to with an empty state and
11
+ * create button, followed by a card for invitations to the user.
12
+ *
13
+ * @param className - Optional additional CSS class names for the outer container.
14
+ * @param variant - Card variant forwarded to each card.
15
+ * @returns The organizations settings UI as a JSX element.
16
+ */
17
+ export declare function OrganizationsSettings({ className, variant, ...props }: OrganizationsSettingsProps & ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "@heroui/react";
3
+ import { Organizations } from "./organizations";
4
+ import { UserInvitations } from "./user-invitations";
5
+ /**
6
+ * Renders the organizations settings panel.
7
+ *
8
+ * Displays all organizations the user belongs to with an empty state and
9
+ * create button, followed by a card for invitations to the user.
10
+ *
11
+ * @param className - Optional additional CSS class names for the outer container.
12
+ * @param variant - Card variant forwarded to each card.
13
+ * @returns The organizations settings UI as a JSX element.
14
+ */
15
+ export function OrganizationsSettings({ className, variant, ...props }) {
16
+ return (_jsxs("div", { className: cn("flex w-full flex-col gap-4 md:gap-6", className), ...props, children: [_jsx(Organizations, { variant: variant }), _jsx(UserInvitations, { variant: variant })] }));
17
+ }
@@ -0,0 +1,10 @@
1
+ import { type CardProps } from "@heroui/react";
2
+ export type OrganizationsProps = {
3
+ variant?: CardProps["variant"];
4
+ };
5
+ /**
6
+ * Lists organizations the user belongs to (via {@link useListOrganizations}): loading skeleton,
7
+ * empty state with create, or a card of rows with a Manage control per organization.
8
+ * Owns {@link CreateOrganizationDialog} open state and the create actions.
9
+ */
10
+ export declare function Organizations({ variant }: OrganizationsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin, useListOrganizations } from "@better-auth-ui/react";
3
+ import { Button, Card } from "@heroui/react";
4
+ import { useState } from "react";
5
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
6
+ import { CreateOrganizationDialog } from "./create-organization-dialog";
7
+ import { OrganizationRow } from "./organization-row";
8
+ import { OrganizationViewSkeleton } from "./organization-view-skeleton";
9
+ import { OrganizationsEmpty } from "./organizations-empty";
10
+ /**
11
+ * Lists organizations the user belongs to (via {@link useListOrganizations}): loading skeleton,
12
+ * empty state with create, or a card of rows with a Manage control per organization.
13
+ * Owns {@link CreateOrganizationDialog} open state and the create actions.
14
+ */
15
+ export function Organizations({ variant }) {
16
+ const { authClient } = useAuth();
17
+ const { localization: organizationLocalization } = useAuthPlugin(organizationPlugin);
18
+ const [createOpen, setCreateOpen] = useState(false);
19
+ const { data: organizations, isPending: organizationsPending } = useListOrganizations(authClient);
20
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-end justify-between gap-3", children: [_jsx("h2", { className: "truncate text-sm font-semibold", children: organizationLocalization.organizations }), _jsx(Button, { className: "shrink-0", size: "sm", isDisabled: organizationsPending, onPress: () => setCreateOpen(true), children: organizationLocalization.createOrganization })] }), _jsx(Card, { variant: variant, children: _jsx(Card.Content, { className: "gap-0", children: organizationsPending ? (_jsx(OrganizationViewSkeleton, {})) : !organizations?.length ? (_jsx(OrganizationsEmpty, { onCreatePress: () => setCreateOpen(true) })) : (organizations.map((organization, index) => (_jsxs("div", { children: [index > 0 && (_jsx("div", { className: "-mx-4 my-4 border-b border-dashed" })), _jsx(OrganizationRow, { organization: organization })] }, organization.id)))) }) })] }), _jsx(CreateOrganizationDialog, { isOpen: createOpen, onOpenChange: setCreateOpen })] }));
21
+ }
@@ -0,0 +1,9 @@
1
+ import type { Member, User } from "better-auth/client";
2
+ export type RemoveMemberDialogProps = {
3
+ isOpen: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ member: Member & {
6
+ user: Partial<User>;
7
+ };
8
+ };
9
+ export declare function RemoveMemberDialog({ isOpen, onOpenChange, member }: RemoveMemberDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin, useRemoveMember } from "@better-auth-ui/react";
3
+ import { TrashBin } from "@gravity-ui/icons";
4
+ import { AlertDialog, Button, Card, Chip, Spinner, toast } from "@heroui/react";
5
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
6
+ import { UserView } from "../user/user-view";
7
+ export function RemoveMemberDialog({ isOpen, onOpenChange, member }) {
8
+ const { authClient, localization } = useAuth();
9
+ const { localization: organizationLocalization, roles } = useAuthPlugin(organizationPlugin);
10
+ const { mutate: removeMember, isPending } = useRemoveMember(authClient, {
11
+ onSuccess: () => {
12
+ onOpenChange(false);
13
+ toast.success(organizationLocalization.memberRemoved);
14
+ }
15
+ });
16
+ return (_jsx(AlertDialog.Backdrop, { isOpen: isOpen, onOpenChange: onOpenChange, children: _jsx(AlertDialog.Container, { children: _jsxs(AlertDialog.Dialog, { children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger", children: _jsx(TrashBin, {}) }), _jsx(AlertDialog.Heading, { children: organizationLocalization.removeMember })] }), _jsxs(AlertDialog.Body, { className: "flex flex-col gap-4 overflow-visible", children: [_jsx("p", { className: "text-muted text-sm", children: organizationLocalization.removeMemberWarning }), _jsx(Card, { variant: "secondary", children: _jsxs(Card.Content, { className: "justify-between flex-row items-center gap-2", children: [_jsx(UserView, { user: member.user }), _jsx(Chip, { size: "sm", variant: "tertiary", children: _jsx(Chip.Label, { children: roles?.[member.role] ?? member.role }) })] }) })] }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "tertiary", isDisabled: isPending, children: localization.settings.cancel }), _jsxs(Button, { variant: "danger", isPending: isPending, onPress: () => removeMember({
17
+ memberIdOrEmail: member.id,
18
+ organizationId: member.organizationId
19
+ }), children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), organizationLocalization.removeMember] })] })] }) }) }));
20
+ }
@@ -0,0 +1,19 @@
1
+ import { type InputProps, type TextFieldProps } from "@heroui/react";
2
+ /** Props for the {@link SlugField} component. */
3
+ export type SlugFieldProps = {
4
+ value: string;
5
+ onChange: (value: string) => void;
6
+ currentSlug?: string;
7
+ isDisabled?: boolean;
8
+ variant?: InputProps["variant"];
9
+ };
10
+ /**
11
+ * Sanitize a slug value so it only contains lowercase alphanumeric characters
12
+ * and dashes. Runs of disallowed characters are collapsed to a single dash, but
13
+ * leading/trailing dashes are preserved while the user is still typing.
14
+ */
15
+ export declare function sanitizeSlug(value: string): string;
16
+ /**
17
+ * Organization slug field with debounced availability checking.
18
+ */
19
+ export declare function SlugField({ value, onChange, currentSlug, variant, ...props }: SlugFieldProps & TextFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin, useCheckSlug } from "@better-auth-ui/react";
3
+ import { Check, Xmark } from "@gravity-ui/icons";
4
+ import { FieldError, InputGroup, Label, Spinner, TextField } from "@heroui/react";
5
+ import { useDebouncer } from "@tanstack/react-pacer";
6
+ import { useEffect } from "react";
7
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
8
+ /**
9
+ * Sanitize a slug value so it only contains lowercase alphanumeric characters
10
+ * and dashes. Runs of disallowed characters are collapsed to a single dash, but
11
+ * leading/trailing dashes are preserved while the user is still typing.
12
+ */
13
+ export function sanitizeSlug(value) {
14
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-");
15
+ }
16
+ /**
17
+ * Organization slug field with debounced availability checking.
18
+ */
19
+ export function SlugField({ value, onChange, currentSlug, variant, ...props }) {
20
+ const { authClient } = useAuth();
21
+ const { localization, checkSlug: checkSlugEnabled } = useAuthPlugin(organizationPlugin);
22
+ const { mutate: checkSlug, data: checkSlugData, error: checkSlugError, reset: resetCheckSlug } = useCheckSlug(authClient);
23
+ const debouncer = useDebouncer((value) => {
24
+ if (!checkSlugEnabled || !value.trim() || value.trim() === currentSlug)
25
+ return;
26
+ checkSlug({ slug: value.trim() });
27
+ }, { wait: 500 });
28
+ useEffect(() => {
29
+ if (!checkSlugEnabled)
30
+ return;
31
+ resetCheckSlug();
32
+ debouncer.maybeExecute(value);
33
+ }, [checkSlugEnabled, value, debouncer.maybeExecute, resetCheckSlug]);
34
+ const handleChange = (next) => {
35
+ onChange(sanitizeSlug(next));
36
+ };
37
+ return (_jsxs(TextField, { id: "slug", name: "slug", ...props, value: value, onChange: handleChange, children: [_jsx(Label, { children: localization.slug }), _jsxs(InputGroup, { variant: variant, children: [_jsx(InputGroup.Input, { placeholder: localization.slugPlaceholder, required: true }), checkSlugEnabled && !!value.trim() && value.trim() !== currentSlug && (_jsx(InputGroup.Suffix, { className: "px-2", children: checkSlugData?.status ? (_jsx(Check, { className: "text-success" })) : checkSlugError ? (_jsx(Xmark, { className: "text-danger" })) : (_jsx(Spinner, { size: "sm", color: "current" })) }))] }), _jsx(FieldError, {})] }));
38
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Placeholder row matching {@link UserInvitationRow} while invitations load.
3
+ */
4
+ export declare function UserInvitationRowSkeleton(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Skeleton } from "@heroui/react";
3
+ /**
4
+ * Placeholder row matching {@link UserInvitationRow} while invitations load.
5
+ */
6
+ export function UserInvitationRowSkeleton() {
7
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "size-10 shrink-0 rounded-xl" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-40 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-28 rounded-lg" })] })] }));
8
+ }
@@ -0,0 +1,10 @@
1
+ import type { Invitation } from "better-auth/client";
2
+ export type UserInvitationRowProps = {
3
+ invitation: Invitation & {
4
+ organizationName?: string;
5
+ };
6
+ };
7
+ /**
8
+ * Single invitation row with accept/reject actions for the current user.
9
+ */
10
+ export declare function UserInvitationRow({ invitation }: UserInvitationRowProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAcceptInvitation, useAuth, useAuthPlugin, useRejectInvitation } from "@better-auth-ui/react";
3
+ import { Check, Clock, Xmark } from "@gravity-ui/icons";
4
+ import { Button, Chip, Spinner } from "@heroui/react";
5
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
6
+ /**
7
+ * Single invitation row with accept/reject actions for the current user.
8
+ */
9
+ export function UserInvitationRow({ invitation }) {
10
+ const { authClient } = useAuth();
11
+ const { localization: organizationLocalization, roles } = useAuthPlugin(organizationPlugin);
12
+ const { mutate: acceptInvitation, isPending: isAccepting } = useAcceptInvitation(authClient);
13
+ const { mutate: rejectInvitation, isPending: isRejecting } = useRejectInvitation(authClient);
14
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary", children: _jsx(Clock, { className: "size-4.5" }) }), _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "truncate text-sm font-medium leading-tight", children: invitation.organizationName }), _jsx(Chip, { size: "sm", children: roles?.[invitation.role] ?? invitation.role })] }), _jsx("span", { className: "truncate text-muted text-xs", children: new Date(invitation.createdAt).toLocaleString(undefined, {
15
+ dateStyle: "medium",
16
+ timeStyle: "short"
17
+ }) })] }), _jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", isPending: isAccepting, isDisabled: isRejecting, onPress: () => acceptInvitation({
18
+ invitationId: invitation.id
19
+ }), children: [isAccepting ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(Check, {}), organizationLocalization.accept] }), _jsx(Button, { variant: "danger-soft", size: "sm", isIconOnly: true, isPending: isRejecting, isDisabled: isAccepting, onPress: () => rejectInvitation({
20
+ invitationId: invitation.id
21
+ }), "aria-label": organizationLocalization.rejectInvitation, children: isRejecting ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(Xmark, {}) })] })] }));
22
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Empty state for `UserInvitations`
3
+ */
4
+ export declare function UserInvitationsEmpty(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuthPlugin } from "@better-auth-ui/react";
3
+ import { PaperPlane } from "@gravity-ui/icons";
4
+ import { EmptyState } from "@heroui/react";
5
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
6
+ /**
7
+ * Empty state for `UserInvitations`
8
+ */
9
+ export function UserInvitationsEmpty() {
10
+ const { localization: organizationLocalization } = useAuthPlugin(organizationPlugin);
11
+ return (_jsxs(EmptyState, { className: "flex flex-col items-center gap-4 text-center", children: [_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-surface-secondary", children: _jsx(PaperPlane, { className: "size-5" }) }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: organizationLocalization.noInvitations }), _jsx("span", { className: "text-sm text-muted", children: organizationLocalization.userInvitationsEmptyDescription })] })] }));
12
+ }
@@ -0,0 +1,10 @@
1
+ import { type CardProps } from "@heroui/react";
2
+ export type UserInvitationsProps = {
3
+ variant?: CardProps["variant"];
4
+ };
5
+ /**
6
+ * Organization invitations for the signed-in user (from
7
+ * {@link useListUserInvitations}). Always renders the section card; uses
8
+ * {@link UserInvitationsEmpty} when there are no pending invitations.
9
+ */
10
+ export declare function UserInvitations({ variant }: UserInvitationsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin, useListUserInvitations } from "@better-auth-ui/react";
3
+ import { Card } from "@heroui/react";
4
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin";
5
+ import { UserInvitationRow } from "./user-invitation-row";
6
+ import { UserInvitationRowSkeleton } from "./user-invitation-row-skeleton";
7
+ import { UserInvitationsEmpty } from "./user-invitations-empty";
8
+ /**
9
+ * Organization invitations for the signed-in user (from
10
+ * {@link useListUserInvitations}). Always renders the section card; uses
11
+ * {@link UserInvitationsEmpty} when there are no pending invitations.
12
+ */
13
+ export function UserInvitations({ variant }) {
14
+ const { authClient } = useAuth();
15
+ const { localization: organizationLocalization } = useAuthPlugin(organizationPlugin);
16
+ const { data: invitations, isPending } = useListUserInvitations(authClient);
17
+ return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsx("h2", { className: "truncate text-sm font-semibold", children: organizationLocalization.invitations }), _jsx(Card, { variant: variant, children: _jsx(Card.Content, { children: isPending ? (_jsx(UserInvitationRowSkeleton, {})) : !invitations?.length ? (_jsx(UserInvitationsEmpty, {})) : (invitations?.map((invitation, index) => (_jsxs("div", { children: [index > 0 && (_jsx("div", { className: "border-b border-dashed -mx-4 my-4" })), _jsx(UserInvitationRow, { invitation: invitation })] }, invitation.id)))) }) })] }));
18
+ }
@@ -0,0 +1,5 @@
1
+ export type AddPasskeyDialogProps = {
2
+ isOpen: boolean;
3
+ onOpenChange: (open: boolean) => void;
4
+ };
5
+ export declare function AddPasskeyDialog({ isOpen, onOpenChange }: AddPasskeyDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAddPasskey, useAuth, useAuthPlugin } from "@better-auth-ui/react";
3
+ import { Fingerprint } from "@gravity-ui/icons";
4
+ import { AlertDialog, Button, FieldError, Form, Input, Label, Spinner, TextField } from "@heroui/react";
5
+ import { passkeyPlugin } from "../../../lib/auth/passkey-plugin";
6
+ export function AddPasskeyDialog({ isOpen, onOpenChange }) {
7
+ const { authClient, localization } = useAuth();
8
+ const { localization: passkeyLocalization } = useAuthPlugin(passkeyPlugin);
9
+ const { mutate: addPasskey, isPending: isAdding } = useAddPasskey(authClient);
10
+ const handleOpenChange = (open) => {
11
+ onOpenChange(open);
12
+ };
13
+ const handleSubmit = (e) => {
14
+ e.preventDefault();
15
+ const formData = new FormData(e.target);
16
+ const name = formData.get("name")?.trim();
17
+ addPasskey(name ? { name } : undefined, {
18
+ onSuccess: () => handleOpenChange(false)
19
+ });
20
+ };
21
+ return (_jsx(AlertDialog.Backdrop, { isOpen: isOpen, onOpenChange: handleOpenChange, children: _jsx(AlertDialog.Container, { children: _jsx(AlertDialog.Dialog, { children: _jsxs(Form, { onSubmit: handleSubmit, children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "default", children: _jsx(Fingerprint, {}) }), _jsx(AlertDialog.Heading, { children: passkeyLocalization.addPasskey })] }), _jsxs(AlertDialog.Body, { className: "overflow-visible", children: [_jsx("p", { className: "text-muted text-sm", children: passkeyLocalization.passkeysDescription }), _jsxs(TextField, { className: "mt-4", id: "name", name: "name", isDisabled: isAdding, children: [_jsx(Label, { children: passkeyLocalization.name }), _jsx(Input, { autoFocus: true, placeholder: localization.settings.optional, variant: "secondary" }), _jsx(FieldError, {})] })] }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "tertiary", isDisabled: isAdding, children: localization.settings.cancel }), _jsxs(Button, { type: "submit", isPending: isAdding, children: [isAdding && _jsx(Spinner, { color: "current", size: "sm" }), passkeyLocalization.addPasskey] })] })] }) }) }) }));
22
+ }
@@ -0,0 +1,11 @@
1
+ export type ListedPasskey = {
2
+ id: string;
3
+ name?: string | null;
4
+ createdAt: Date;
5
+ };
6
+ export type DeletePasskeyDialogProps = {
7
+ isOpen: boolean;
8
+ onOpenChange: (open: boolean) => void;
9
+ passkey: ListedPasskey;
10
+ };
11
+ export declare function DeletePasskeyDialog({ isOpen, onOpenChange, passkey }: DeletePasskeyDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin, useDeletePasskey } from "@better-auth-ui/react";
3
+ import { Fingerprint } from "@gravity-ui/icons";
4
+ import { AlertDialog, Button, Input, Label, Spinner, TextField } from "@heroui/react";
5
+ import { passkeyPlugin } from "../../../lib/auth/passkey-plugin";
6
+ export function DeletePasskeyDialog({ isOpen, onOpenChange, passkey }) {
7
+ const { authClient, localization } = useAuth();
8
+ const { localization: passkeyLocalization } = useAuthPlugin(passkeyPlugin);
9
+ const passkeyName = passkey.name || passkeyLocalization.passkey;
10
+ const { mutate: deletePasskey, isPending: isDeleting } = useDeletePasskey(authClient, {
11
+ onSuccess: () => onOpenChange(false)
12
+ });
13
+ return (_jsx(AlertDialog.Backdrop, { isOpen: isOpen, onOpenChange: onOpenChange, children: _jsx(AlertDialog.Container, { children: _jsxs(AlertDialog.Dialog, { children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger", children: _jsx(Fingerprint, {}) }), _jsx(AlertDialog.Heading, { children: passkeyLocalization.deletePasskeyTitle })] }), _jsxs(AlertDialog.Body, { className: "flex flex-col gap-4 overflow-visible", children: [_jsx("p", { className: "text-muted text-sm", children: passkeyLocalization.deletePasskeyWarning }), _jsxs(TextField, { value: passkeyName, variant: "secondary", children: [_jsx(Label, { children: passkey.name || passkeyLocalization.passkey }), _jsx(Input, { readOnly: true })] })] }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "tertiary", isDisabled: isDeleting, children: localization.settings.cancel }), _jsxs(Button, { variant: "danger", onPress: () => deletePasskey({ id: passkey.id }), isPending: isDeleting, children: [isDeleting && _jsx(Spinner, { color: "current", size: "sm" }), passkeyLocalization.deletePasskeyTitle] })] })] }) }) }));
14
+ }
@@ -1,4 +1,4 @@
1
- import { AuthView } from '@better-auth-ui/core';
1
+ import { type AuthView } from "@better-auth-ui/core";
2
2
  export type PasskeyButtonProps = {
3
3
  /** @remarks `AuthView` */
4
4
  view?: AuthView;
@@ -1,24 +1,25 @@
1
- import { passkeyPlugin as e } from "../../../lib/auth/passkey-plugin.js";
2
- import { authMutationKeys as t } from "@better-auth-ui/core";
3
- import { useAuth as n, useAuthPlugin as r, useSignInPasskey as i } from "@better-auth-ui/react";
4
- import { Fingerprint as a } from "@gravity-ui/icons";
5
- import { Button as o, Spinner as s } from "@heroui/react";
6
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
- import { useIsMutating as u } from "@tanstack/react-query";
8
- //#region src/components/auth/passkey/passkey-button.tsx
9
- function d({ view: d }) {
10
- let { authClient: f, localization: p, redirectTo: m, navigate: h } = n(), { localization: g } = r(e), { mutate: _, isPending: v } = i(f, { onSuccess: () => h({ to: m }) }), y = u({ mutationKey: t.signIn.all }) + u({ mutationKey: t.signUp.all }) > 0;
11
- return d === "signUp" ? null : /* @__PURE__ */ l(o, {
12
- className: "w-full",
13
- variant: "tertiary",
14
- isDisabled: y,
15
- isPending: v,
16
- onPress: () => _(),
17
- children: [v ? /* @__PURE__ */ c(s, {
18
- color: "current",
19
- size: "sm"
20
- }) : /* @__PURE__ */ c(a, {}), p.auth.continueWith.replace("{{provider}}", g.passkey)]
21
- });
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { authMutationKeys } from "@better-auth-ui/core";
3
+ import { useAuth, useAuthPlugin, useSignInPasskey } from "@better-auth-ui/react";
4
+ import { Fingerprint } from "@gravity-ui/icons";
5
+ import { Button, Spinner } from "@heroui/react";
6
+ import { useIsMutating } from "@tanstack/react-query";
7
+ import { passkeyPlugin } from "../../../lib/auth/passkey-plugin";
8
+ export function PasskeyButton({ view }) {
9
+ const { authClient, localization, redirectTo, navigate } = useAuth();
10
+ const { localization: passkeyLocalization } = useAuthPlugin(passkeyPlugin);
11
+ const { mutate: signInPasskey, isPending: passkeyPending } = useSignInPasskey(authClient, {
12
+ onSuccess: () => navigate({ to: redirectTo })
13
+ });
14
+ const signInMutating = useIsMutating({
15
+ mutationKey: authMutationKeys.signIn.all
16
+ });
17
+ const signUpMutating = useIsMutating({
18
+ mutationKey: authMutationKeys.signUp.all
19
+ });
20
+ const isPending = signInMutating + signUpMutating > 0;
21
+ // Passkey sign-in isn't relevant on the sign-up flow.
22
+ if (view === "signUp")
23
+ return null;
24
+ return (_jsxs(Button, { className: "w-full", variant: "tertiary", isDisabled: isPending, isPending: passkeyPending, onPress: () => signInPasskey(), children: [passkeyPending ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(Fingerprint, {}), localization.auth.continueWith.replace("{{provider}}", passkeyLocalization.passkey)] }));
22
25
  }
23
- //#endregion
24
- export { d as PasskeyButton };
@@ -0,0 +1 @@
1
+ export declare function PasskeySkeleton(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Skeleton } from "@heroui/react";
3
+ export function PasskeySkeleton() {
4
+ return (_jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "size-10 rounded-xl" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-28 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-32 rounded-lg" })] })] }) }));
5
+ }
@@ -1,8 +1,5 @@
1
+ import { type ListedPasskey } from "./delete-passkey-dialog";
1
2
  export type PasskeyProps = {
2
- passkey: {
3
- id: string;
4
- name?: string | null;
5
- createdAt: Date;
6
- };
3
+ passkey: ListedPasskey;
7
4
  };
8
5
  export declare function Passkey({ passkey }: PasskeyProps): import("react/jsx-runtime").JSX.Element;
@@ -1,45 +1,17 @@
1
- import { passkeyPlugin as e } from "../../../lib/auth/passkey-plugin.js";
2
- import { useAuth as t, useAuthPlugin as n, useDeletePasskey as r } from "@better-auth-ui/react";
3
- import { Fingerprint as i, Xmark as a } from "@gravity-ui/icons";
4
- import { Button as o, Spinner as s } from "@heroui/react";
5
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
- //#region src/components/auth/passkey/passkey.tsx
7
- function u({ passkey: u }) {
8
- let { authClient: d, localization: f } = t(), { localization: p } = n(e), { mutate: m, isPending: h } = r(d), g = u.name || p.passkey;
9
- return /* @__PURE__ */ l("div", {
10
- className: "flex items-center gap-3",
11
- children: [
12
- /* @__PURE__ */ c("div", {
13
- className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary",
14
- children: /* @__PURE__ */ c(i, { className: "size-4.5" })
15
- }),
16
- /* @__PURE__ */ l("div", {
17
- className: "flex flex-col min-w-0",
18
- children: [/* @__PURE__ */ c("span", {
19
- className: "text-sm font-medium leading-tight",
20
- children: g
21
- }), /* @__PURE__ */ c("span", {
22
- className: "text-xs text-muted",
23
- children: new Date(u.createdAt).toLocaleString(void 0, {
24
- dateStyle: "medium",
25
- timeStyle: "short"
26
- })
27
- })]
28
- }),
29
- /* @__PURE__ */ l(o, {
30
- className: "ml-auto shrink-0",
31
- variant: "outline",
32
- size: "sm",
33
- isPending: h,
34
- onPress: () => m({ id: u.id }),
35
- "aria-label": p.deletePasskey.replace("{{name}}", g),
36
- children: [h ? /* @__PURE__ */ c(s, {
37
- color: "current",
38
- size: "sm"
39
- }) : /* @__PURE__ */ c(a, {}), f.settings.delete]
40
- })
41
- ]
42
- });
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useAuthPlugin } from "@better-auth-ui/react";
3
+ import { Fingerprint, Xmark } from "@gravity-ui/icons";
4
+ import { Button } from "@heroui/react";
5
+ import { useState } from "react";
6
+ import { passkeyPlugin } from "../../../lib/auth/passkey-plugin";
7
+ import { DeletePasskeyDialog } from "./delete-passkey-dialog";
8
+ export function Passkey({ passkey }) {
9
+ const { localization } = useAuth();
10
+ const { localization: passkeyLocalization } = useAuthPlugin(passkeyPlugin);
11
+ const [deleteOpen, setDeleteOpen] = useState(false);
12
+ const passkeyName = passkey.name || passkeyLocalization.passkey;
13
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary", children: _jsx(Fingerprint, { className: "size-4.5" }) }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate text-sm font-medium leading-tight", children: passkeyName }), _jsx("span", { className: "text-xs text-muted", children: new Date(passkey.createdAt).toLocaleString(undefined, {
14
+ dateStyle: "medium",
15
+ timeStyle: "short"
16
+ }) })] }), _jsxs(Button, { className: "ml-auto shrink-0", variant: "outline", size: "sm", onPress: () => setDeleteOpen(true), "aria-label": passkeyLocalization.deletePasskey.replace("{{name}}", passkeyName), children: [_jsx(Xmark, {}), localization.settings.delete] }), _jsx(DeletePasskeyDialog, { isOpen: deleteOpen, onOpenChange: setDeleteOpen, passkey: passkey })] }));
43
17
  }
44
- //#endregion
45
- export { u as Passkey };
@@ -0,0 +1,4 @@
1
+ export type PasskeysEmptyProps = {
2
+ onAddPress: () => void;
3
+ };
4
+ export declare function PasskeysEmpty({ onAddPress }: PasskeysEmptyProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuthPlugin } from "@better-auth-ui/react";
3
+ import { Fingerprint } from "@gravity-ui/icons";
4
+ import { Button } from "@heroui/react";
5
+ import { passkeyPlugin } from "../../../lib/auth/passkey-plugin";
6
+ export function PasskeysEmpty({ onAddPress }) {
7
+ const { localization: passkeyLocalization } = useAuthPlugin(passkeyPlugin);
8
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4", children: [_jsx("div", { className: "flex size-10 items-center justify-center rounded-xl bg-surface-secondary", children: _jsx(Fingerprint, { className: "size-4.5" }) }), _jsxs("div", { className: "flex flex-col items-center justify-center gap-1 text-center", children: [_jsx("p", { className: "text-sm font-semibold", children: passkeyLocalization.noPasskeys }), _jsx("p", { className: "text-muted text-xs", children: passkeyLocalization.passkeysDescription })] }), _jsx(Button, { size: "sm", onPress: onAddPress, children: passkeyLocalization.addPasskey })] }));
9
+ }
@@ -1,4 +1,4 @@
1
- import { CardProps } from '@heroui/react';
1
+ import { type CardProps } from "@heroui/react";
2
2
  export type PasskeysProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];