@better-auth-ui/heroui 1.6.8 → 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.
- package/dist/components/auth/additional-field.d.ts +2 -2
- package/dist/components/auth/additional-field.js +133 -266
- package/dist/components/auth/api-key/api-key-skeleton.js +4 -20
- package/dist/components/auth/api-key/api-key.d.ts +6 -2
- package/dist/components/auth/api-key/api-key.js +16 -54
- package/dist/components/auth/api-key/api-keys-empty.d.ts +3 -1
- package/dist/components/auth/api-key/api-keys-empty.js +8 -34
- package/dist/components/auth/api-key/api-keys.d.ts +10 -2
- package/dist/components/auth/api-key/api-keys.js +21 -40
- package/dist/components/auth/api-key/create-api-key-dialog.d.ts +3 -1
- package/dist/components/auth/api-key/create-api-key-dialog.js +43 -73
- package/dist/components/auth/api-key/delete-api-key-dialog.d.ts +4 -2
- package/dist/components/auth/api-key/delete-api-key-dialog.js +16 -50
- package/dist/components/auth/api-key/new-api-key-dialog.js +23 -59
- package/dist/components/auth/api-key/organization-api-keys.d.ts +14 -0
- package/dist/components/auth/api-key/organization-api-keys.js +22 -0
- package/dist/components/auth/auth-provider.d.ts +1 -1
- package/dist/components/auth/auth-provider.js +10 -16
- package/dist/components/auth/auth.d.ts +3 -3
- package/dist/components/auth/auth.js +86 -61
- package/dist/components/auth/delete-user/danger-zone.d.ts +3 -3
- package/dist/components/auth/delete-user/danger-zone.js +11 -17
- package/dist/components/auth/delete-user/delete-account.d.ts +9 -0
- package/dist/components/auth/delete-user/delete-account.js +50 -0
- package/dist/components/auth/email/email-changed-email.d.ts +2 -2
- package/dist/components/auth/email/email-changed-email.js +22 -29
- package/dist/components/auth/email/email-verification-email.d.ts +2 -2
- package/dist/components/auth/email/email-verification-email.js +22 -29
- package/dist/components/auth/email/magic-link-email.d.ts +2 -2
- package/dist/components/auth/email/magic-link-email.js +22 -29
- package/dist/components/auth/email/new-device-email.d.ts +2 -2
- package/dist/components/auth/email/new-device-email.js +22 -29
- package/dist/components/auth/email/organization-invitation-email.d.ts +3 -0
- package/dist/components/auth/email/organization-invitation-email.js +23 -0
- package/dist/components/auth/email/otp-email.d.ts +2 -2
- package/dist/components/auth/email/otp-email.js +21 -28
- package/dist/components/auth/email/password-changed-email.d.ts +2 -2
- package/dist/components/auth/email/password-changed-email.js +22 -29
- package/dist/components/auth/email/reset-password-email.d.ts +2 -2
- package/dist/components/auth/email/reset-password-email.js +22 -29
- package/dist/components/auth/error-toaster.js +32 -16
- package/dist/components/auth/field-separator.d.ts +1 -1
- package/dist/components/auth/field-separator.js +4 -17
- package/dist/components/auth/forgot-password.d.ts +1 -1
- package/dist/components/auth/forgot-password.js +36 -88
- package/dist/components/auth/magic-link/magic-link-button.d.ts +1 -1
- package/dist/components/auth/magic-link/magic-link-button.js +33 -19
- package/dist/components/auth/magic-link/magic-link.d.ts +2 -2
- package/dist/components/auth/magic-link/magic-link.js +39 -86
- package/dist/components/auth/multi-session/manage-account.d.ts +1 -1
- package/dist/components/auth/multi-session/manage-account.js +32 -48
- package/dist/components/auth/multi-session/manage-accounts.d.ts +1 -1
- package/dist/components/auth/multi-session/manage-accounts.js +32 -33
- package/dist/components/auth/multi-session/switch-account-submenu-content.d.ts +3 -1
- package/dist/components/auth/multi-session/switch-account-submenu-content.js +24 -27
- package/dist/components/auth/multi-session/switch-account-submenu-item.d.ts +3 -2
- package/dist/components/auth/multi-session/switch-account-submenu-item.js +16 -19
- package/dist/components/auth/multi-session/switch-account-submenu.d.ts +2 -1
- package/dist/components/auth/multi-session/switch-account-submenu.js +23 -23
- package/dist/components/auth/organization/change-organization-logo.d.ts +4 -0
- package/dist/components/auth/organization/change-organization-logo.js +69 -0
- package/dist/components/auth/organization/create-organization-dialog.d.ts +13 -0
- package/dist/components/auth/organization/create-organization-dialog.js +37 -0
- package/dist/components/auth/organization/delete-organization-dialog.d.ts +7 -0
- package/dist/components/auth/organization/delete-organization-dialog.js +25 -0
- package/dist/components/auth/organization/delete-organization-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/delete-organization-skeleton.js +8 -0
- package/dist/components/auth/organization/delete-organization.d.ts +5 -0
- package/dist/components/auth/organization/delete-organization.js +27 -0
- package/dist/components/auth/organization/invite-member-dialog.d.ts +13 -0
- package/dist/components/auth/organization/invite-member-dialog.js +47 -0
- package/dist/components/auth/organization/leave-organization-dialog.d.ts +7 -0
- package/dist/components/auth/organization/leave-organization-dialog.js +21 -0
- package/dist/components/auth/organization/leave-organization.d.ts +4 -0
- package/dist/components/auth/organization/leave-organization.js +16 -0
- package/dist/components/auth/organization/organization-danger-zone.d.ts +16 -0
- package/dist/components/auth/organization/organization-danger-zone.js +23 -0
- package/dist/components/auth/organization/organization-invitation-row-skeleton.d.ts +5 -0
- package/dist/components/auth/organization/organization-invitation-row-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-invitation-row.d.ts +5 -0
- package/dist/components/auth/organization/organization-invitation-row.js +31 -0
- package/dist/components/auth/organization/organization-invitations-empty.d.ts +8 -0
- package/dist/components/auth/organization/organization-invitations-empty.js +13 -0
- package/dist/components/auth/organization/organization-invitations.d.ts +9 -0
- package/dist/components/auth/organization/organization-invitations.js +66 -0
- package/dist/components/auth/organization/organization-logo.d.ts +15 -0
- package/dist/components/auth/organization/organization-logo.js +14 -0
- package/dist/components/auth/organization/organization-member-row-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/organization-member-row-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-member-row.d.ts +9 -0
- package/dist/components/auth/organization/organization-member-row.js +34 -0
- package/dist/components/auth/organization/organization-members.d.ts +9 -0
- package/dist/components/auth/organization/organization-members.js +67 -0
- package/dist/components/auth/organization/organization-people.d.ts +10 -0
- package/dist/components/auth/organization/organization-people.js +11 -0
- package/dist/components/auth/organization/organization-profile.d.ts +9 -0
- package/dist/components/auth/organization/organization-profile.js +34 -0
- package/dist/components/auth/organization/organization-row.d.ts +8 -0
- package/dist/components/auth/organization/organization-row.js +31 -0
- package/dist/components/auth/organization/organization-settings.d.ts +12 -0
- package/dist/components/auth/organization/organization-settings.js +13 -0
- package/dist/components/auth/organization/organization-switcher.d.ts +20 -0
- package/dist/components/auth/organization/organization-switcher.js +48 -0
- package/dist/components/auth/organization/organization-view-skeleton.d.ts +6 -0
- package/dist/components/auth/organization/organization-view-skeleton.js +9 -0
- package/dist/components/auth/organization/organization-view.d.ts +15 -0
- package/dist/components/auth/organization/organization-view.js +31 -0
- package/dist/components/auth/organization/organization.d.ts +17 -0
- package/dist/components/auth/organization/organization.js +60 -0
- package/dist/components/auth/organization/organizations-empty.d.ts +4 -0
- package/dist/components/auth/organization/organizations-empty.js +9 -0
- package/dist/components/auth/organization/organizations-settings.d.ts +17 -0
- package/dist/components/auth/organization/organizations-settings.js +17 -0
- package/dist/components/auth/organization/organizations.d.ts +10 -0
- package/dist/components/auth/organization/organizations.js +21 -0
- package/dist/components/auth/organization/remove-member-dialog.d.ts +9 -0
- package/dist/components/auth/organization/remove-member-dialog.js +20 -0
- package/dist/components/auth/organization/slug-field.d.ts +19 -0
- package/dist/components/auth/organization/slug-field.js +38 -0
- package/dist/components/auth/organization/user-invitation-row-skeleton.d.ts +4 -0
- package/dist/components/auth/organization/user-invitation-row-skeleton.js +8 -0
- package/dist/components/auth/organization/user-invitation-row.d.ts +10 -0
- package/dist/components/auth/organization/user-invitation-row.js +22 -0
- package/dist/components/auth/organization/user-invitations-empty.d.ts +4 -0
- package/dist/components/auth/organization/user-invitations-empty.js +12 -0
- package/dist/components/auth/organization/user-invitations.d.ts +10 -0
- package/dist/components/auth/organization/user-invitations.js +18 -0
- package/dist/components/auth/passkey/add-passkey-dialog.js +21 -64
- package/dist/components/auth/passkey/delete-passkey-dialog.js +13 -46
- package/dist/components/auth/passkey/passkey-button.d.ts +1 -1
- package/dist/components/auth/passkey/passkey-button.js +24 -23
- package/dist/components/auth/passkey/passkey-skeleton.js +4 -16
- package/dist/components/auth/passkey/passkey.d.ts +1 -1
- package/dist/components/auth/passkey/passkey.js +16 -47
- package/dist/components/auth/passkey/passkeys-empty.js +8 -34
- package/dist/components/auth/passkey/passkeys.d.ts +1 -1
- package/dist/components/auth/passkey/passkeys.js +15 -41
- package/dist/components/auth/provider-button.d.ts +2 -2
- package/dist/components/auth/provider-button.js +28 -24
- package/dist/components/auth/provider-buttons.js +28 -18
- package/dist/components/auth/reset-password.d.ts +1 -1
- package/dist/components/auth/reset-password.js +56 -146
- package/dist/components/auth/settings/account/account-settings.d.ts +2 -2
- package/dist/components/auth/settings/account/account-settings.js +21 -19
- package/dist/components/auth/settings/account/change-avatar.js +53 -88
- package/dist/components/auth/settings/account/change-email.d.ts +1 -1
- package/dist/components/auth/settings/account/change-email.js +27 -53
- package/dist/components/auth/settings/account/user-profile.d.ts +1 -1
- package/dist/components/auth/settings/account/user-profile.js +64 -85
- package/dist/components/auth/settings/security/active-session.d.ts +1 -1
- package/dist/components/auth/settings/security/active-session.js +50 -57
- package/dist/components/auth/settings/security/active-sessions.d.ts +1 -1
- package/dist/components/auth/settings/security/active-sessions.js +21 -32
- package/dist/components/auth/settings/security/change-password.d.ts +1 -1
- package/dist/components/auth/settings/security/change-password.js +76 -186
- package/dist/components/auth/settings/security/linked-account.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-account.js +37 -55
- package/dist/components/auth/settings/security/linked-accounts.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-accounts.js +34 -43
- package/dist/components/auth/settings/security/security-settings.d.ts +2 -2
- package/dist/components/auth/settings/security/security-settings.js +19 -21
- package/dist/components/auth/settings/settings.d.ts +4 -4
- package/dist/components/auth/settings/settings.js +52 -44
- package/dist/components/auth/sign-in.d.ts +2 -2
- package/dist/components/auth/sign-in.js +63 -132
- package/dist/components/auth/sign-out.js +32 -26
- package/dist/components/auth/sign-up.d.ts +2 -2
- package/dist/components/auth/sign-up.js +97 -211
- package/dist/components/auth/theme/appearance.d.ts +1 -1
- package/dist/components/auth/theme/appearance.js +23 -71
- package/dist/components/auth/theme/theme-toggle-item.js +56 -61
- package/dist/components/auth/user/user-avatar.d.ts +4 -4
- package/dist/components/auth/user/user-avatar.js +31 -28
- package/dist/components/auth/user/user-button.d.ts +6 -7
- package/dist/components/auth/user/user-button.js +38 -72
- package/dist/components/auth/user/user-view.d.ts +13 -7
- package/dist/components/auth/user/user-view.js +26 -36
- package/dist/components/auth/username/sign-in-username.d.ts +2 -2
- package/dist/components/auth/username/sign-in-username.js +87 -147
- package/dist/components/auth/username/username-field.d.ts +1 -1
- package/dist/components/auth/username/username-field.js +44 -52
- package/dist/email.d.ts +8 -7
- package/dist/email.js +8 -8
- package/dist/index.d.ts +21 -21
- package/dist/index.js +21 -22
- package/dist/lib/auth/api-key-plugin.d.ts +7 -4
- package/dist/lib/auth/api-key-plugin.js +12 -10
- package/dist/lib/auth/auth-plugin.d.ts +10 -6
- package/dist/lib/auth/auth-plugin.js +1 -0
- package/dist/lib/auth/delete-user-plugin.d.ts +6 -6
- package/dist/lib/auth/delete-user-plugin.js +6 -9
- package/dist/lib/auth/magic-link-plugin.d.ts +5 -5
- package/dist/lib/auth/magic-link-plugin.js +17 -12
- package/dist/lib/auth/multi-session-plugin.d.ts +5 -5
- package/dist/lib/auth/multi-session-plugin.js +8 -11
- package/dist/lib/auth/organization-plugin.d.ts +37 -0
- package/dist/lib/auth/organization-plugin.js +19 -0
- package/dist/lib/auth/passkey-plugin.d.ts +5 -5
- package/dist/lib/auth/passkey-plugin.js +8 -11
- package/dist/lib/auth/theme-plugin.d.ts +6 -6
- package/dist/lib/auth/theme-plugin.js +25 -22
- package/dist/lib/auth/username-plugin.d.ts +11 -11
- package/dist/lib/auth/username-plugin.js +18 -17
- package/dist/plugins.d.ts +46 -22
- package/dist/plugins.js +47 -22
- package/package.json +25 -19
- package/src/components/auth/api-key/api-key.tsx +25 -16
- package/src/components/auth/api-key/api-keys-empty.tsx +8 -4
- package/src/components/auth/api-key/api-keys.tsx +52 -14
- package/src/components/auth/api-key/create-api-key-dialog.tsx +15 -2
- package/src/components/auth/api-key/delete-api-key-dialog.tsx +10 -2
- package/src/components/auth/api-key/organization-api-keys.tsx +55 -0
- package/src/components/auth/delete-user/danger-zone.tsx +3 -3
- package/src/components/auth/delete-user/{delete-user.tsx → delete-account.tsx} +9 -9
- package/src/components/auth/email/organization-invitation-email.tsx +38 -0
- package/src/components/auth/error-toaster.tsx +28 -10
- package/src/components/auth/forgot-password.tsx +10 -2
- package/src/components/auth/multi-session/manage-accounts.tsx +1 -1
- package/src/components/auth/multi-session/switch-account-submenu-content.tsx +7 -2
- package/src/components/auth/multi-session/switch-account-submenu-item.tsx +4 -2
- package/src/components/auth/multi-session/switch-account-submenu.tsx +8 -4
- package/src/components/auth/organization/change-organization-logo.tsx +171 -0
- package/src/components/auth/organization/create-organization-dialog.tsx +133 -0
- package/src/components/auth/organization/delete-organization-dialog.tsx +97 -0
- package/src/components/auth/organization/delete-organization-skeleton.tsx +17 -0
- package/src/components/auth/organization/delete-organization.tsx +77 -0
- package/src/components/auth/organization/invite-member-dialog.tsx +177 -0
- package/src/components/auth/organization/leave-organization-dialog.tsx +95 -0
- package/src/components/auth/organization/leave-organization.tsx +59 -0
- package/src/components/auth/organization/organization-danger-zone.tsx +68 -0
- package/src/components/auth/organization/organization-invitation-row-skeleton.tsx +29 -0
- package/src/components/auth/organization/organization-invitation-row.tsx +97 -0
- package/src/components/auth/organization/organization-invitations-empty.tsx +39 -0
- package/src/components/auth/organization/organization-invitations.tsx +351 -0
- package/src/components/auth/organization/organization-logo.tsx +64 -0
- package/src/components/auth/organization/organization-member-row-skeleton.tsx +24 -0
- package/src/components/auth/organization/organization-member-row.tsx +157 -0
- package/src/components/auth/organization/organization-members.tsx +284 -0
- package/src/components/auth/organization/organization-people.tsx +26 -0
- package/src/components/auth/organization/organization-profile.tsx +141 -0
- package/src/components/auth/organization/organization-row.tsx +66 -0
- package/src/components/auth/organization/organization-settings.tsx +38 -0
- package/src/components/auth/organization/organization-switcher.tsx +233 -0
- package/src/components/auth/organization/organization-view-skeleton.tsx +36 -0
- package/src/components/auth/organization/organization-view.tsx +109 -0
- package/src/components/auth/organization/organization.tsx +162 -0
- package/src/components/auth/organization/organizations-empty.tsx +35 -0
- package/src/components/auth/organization/organizations-settings.tsx +36 -0
- package/src/components/auth/organization/organizations.tsx +80 -0
- package/src/components/auth/organization/remove-member-dialog.tsx +95 -0
- package/src/components/auth/organization/slug-field.tsx +111 -0
- package/src/components/auth/organization/user-invitation-row-skeleton.tsx +17 -0
- package/src/components/auth/organization/user-invitation-row.tsx +90 -0
- package/src/components/auth/organization/user-invitations-empty.tsx +30 -0
- package/src/components/auth/organization/user-invitations.tsx +59 -0
- package/src/components/auth/settings/account/change-email.tsx +1 -1
- package/src/components/auth/settings/account/user-profile.tsx +5 -5
- package/src/components/auth/settings/security/active-sessions.tsx +6 -4
- package/src/components/auth/settings/security/linked-accounts.tsx +2 -2
- package/src/components/auth/settings/settings.tsx +77 -14
- package/src/components/auth/user/user-avatar.tsx +4 -1
- package/src/components/auth/user/user-button.tsx +14 -11
- package/src/components/auth/user/user-view.tsx +32 -12
- package/src/email.ts +1 -0
- package/src/lib/auth/api-key-plugin.ts +10 -4
- package/src/lib/auth/auth-plugin.ts +6 -1
- package/src/lib/auth/organization-plugin.tsx +32 -0
- package/src/plugins.ts +25 -1
- package/dist/components/auth/delete-user/delete-user.d.ts +0 -9
- 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,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,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,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
|
+
}
|
|
@@ -1,65 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAddPasskey
|
|
3
|
-
import { Fingerprint
|
|
4
|
-
import { AlertDialog
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/* @__PURE__ */ m(a.Header, { children: [/* @__PURE__ */ p(a.Icon, {
|
|
23
|
-
status: "default",
|
|
24
|
-
children: /* @__PURE__ */ p(i, {})
|
|
25
|
-
}), /* @__PURE__ */ p(a.Heading, { children: y.addPasskey })] }),
|
|
26
|
-
/* @__PURE__ */ m(a.Body, {
|
|
27
|
-
className: "overflow-visible",
|
|
28
|
-
children: [/* @__PURE__ */ p("p", {
|
|
29
|
-
className: "text-muted text-sm",
|
|
30
|
-
children: y.passkeysDescription
|
|
31
|
-
}), /* @__PURE__ */ m(f, {
|
|
32
|
-
className: "mt-4",
|
|
33
|
-
id: "name",
|
|
34
|
-
name: "name",
|
|
35
|
-
isDisabled: x,
|
|
36
|
-
children: [
|
|
37
|
-
/* @__PURE__ */ p(u, { children: y.name }),
|
|
38
|
-
/* @__PURE__ */ p(l, {
|
|
39
|
-
autoFocus: !0,
|
|
40
|
-
placeholder: v.settings.optional,
|
|
41
|
-
variant: "secondary"
|
|
42
|
-
}),
|
|
43
|
-
/* @__PURE__ */ p(s, {})
|
|
44
|
-
]
|
|
45
|
-
})]
|
|
46
|
-
}),
|
|
47
|
-
/* @__PURE__ */ m(a.Footer, { children: [/* @__PURE__ */ p(o, {
|
|
48
|
-
slot: "close",
|
|
49
|
-
variant: "tertiary",
|
|
50
|
-
isDisabled: x,
|
|
51
|
-
children: v.settings.cancel
|
|
52
|
-
}), /* @__PURE__ */ m(o, {
|
|
53
|
-
type: "submit",
|
|
54
|
-
isPending: x,
|
|
55
|
-
children: [x && /* @__PURE__ */ p(d, {
|
|
56
|
-
color: "current",
|
|
57
|
-
size: "sm"
|
|
58
|
-
}), y.addPasskey]
|
|
59
|
-
})] })
|
|
60
|
-
]
|
|
61
|
-
}) }) })
|
|
62
|
-
});
|
|
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] })] })] }) }) }) }));
|
|
63
22
|
}
|
|
64
|
-
//#endregion
|
|
65
|
-
export { h as AddPasskeyDialog };
|
|
@@ -1,47 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAuth
|
|
3
|
-
import { Fingerprint
|
|
4
|
-
import { AlertDialog
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/* @__PURE__ */ f(a.Header, { children: [/* @__PURE__ */ d(a.Icon, {
|
|
15
|
-
status: "danger",
|
|
16
|
-
children: /* @__PURE__ */ d(i, {})
|
|
17
|
-
}), /* @__PURE__ */ d(a.Heading, { children: v.deletePasskeyTitle })] }),
|
|
18
|
-
/* @__PURE__ */ f(a.Body, {
|
|
19
|
-
className: "flex flex-col gap-4 overflow-visible",
|
|
20
|
-
children: [/* @__PURE__ */ d("p", {
|
|
21
|
-
className: "text-muted text-sm",
|
|
22
|
-
children: v.deletePasskeyWarning
|
|
23
|
-
}), /* @__PURE__ */ f(u, {
|
|
24
|
-
value: y,
|
|
25
|
-
variant: "secondary",
|
|
26
|
-
children: [/* @__PURE__ */ d(c, { children: h.name || v.passkey }), /* @__PURE__ */ d(s, { readOnly: !0 })]
|
|
27
|
-
})]
|
|
28
|
-
}),
|
|
29
|
-
/* @__PURE__ */ f(a.Footer, { children: [/* @__PURE__ */ d(o, {
|
|
30
|
-
slot: "close",
|
|
31
|
-
variant: "tertiary",
|
|
32
|
-
isDisabled: x,
|
|
33
|
-
children: _.settings.cancel
|
|
34
|
-
}), /* @__PURE__ */ f(o, {
|
|
35
|
-
variant: "danger",
|
|
36
|
-
onPress: () => b({ id: h.id }),
|
|
37
|
-
isPending: x,
|
|
38
|
-
children: [x && /* @__PURE__ */ d(l, {
|
|
39
|
-
color: "current",
|
|
40
|
-
size: "sm"
|
|
41
|
-
}), v.deletePasskeyTitle]
|
|
42
|
-
})] })
|
|
43
|
-
] }) })
|
|
44
|
-
});
|
|
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] })] })] }) }) }));
|
|
45
14
|
}
|
|
46
|
-
//#endregion
|
|
47
|
-
export { p as DeletePasskeyDialog };
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { authMutationKeys
|
|
3
|
-
import { useAuth
|
|
4
|
-
import { Fingerprint
|
|
5
|
-
import { Button
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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 };
|
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return /* @__PURE__ */ t("div", {
|
|
6
|
-
className: "flex items-center justify-between",
|
|
7
|
-
children: /* @__PURE__ */ n("div", {
|
|
8
|
-
className: "flex items-center gap-3",
|
|
9
|
-
children: [/* @__PURE__ */ t(e, { className: "size-10 rounded-xl" }), /* @__PURE__ */ n("div", {
|
|
10
|
-
className: "flex flex-col gap-1",
|
|
11
|
-
children: [/* @__PURE__ */ t(e, { className: "h-4 w-28 rounded-lg" }), /* @__PURE__ */ t(e, { className: "h-3 w-32 rounded-lg" })]
|
|
12
|
-
})]
|
|
13
|
-
})
|
|
14
|
-
});
|
|
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" })] })] }) }));
|
|
15
5
|
}
|
|
16
|
-
//#endregion
|
|
17
|
-
export { r as PasskeySkeleton };
|