@dudousxd/adonis-authkit-react 0.1.2 → 0.3.0
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/README.md +26 -0
- package/build/index.d.ts +47 -0
- package/build/index.js +24 -0
- package/build/src/authkit_provider.d.ts +13 -0
- package/build/src/authkit_provider.js +11 -0
- package/build/src/components/authorized_apps.d.ts +8 -0
- package/build/src/components/authorized_apps.js +26 -0
- package/build/src/components/avatar.d.ts +22 -0
- package/build/src/components/avatar.js +15 -0
- package/build/src/components/organization_profile.d.ts +8 -0
- package/build/src/components/organization_profile.js +87 -0
- package/build/src/components/organization_switcher.d.ts +7 -0
- package/build/src/components/organization_switcher.js +57 -0
- package/build/src/components/password_strength_meter.d.ts +11 -0
- package/build/src/components/password_strength_meter.js +39 -0
- package/build/src/components/sign_in_button.d.ts +297 -0
- package/build/src/components/sign_in_button.js +16 -0
- package/build/src/components/sign_out_button.d.ts +296 -0
- package/build/src/components/sign_out_button.js +16 -0
- package/build/src/components/user_button.d.ts +8 -0
- package/build/src/components/user_button.js +31 -0
- package/build/src/components/user_profile.d.ts +6 -0
- package/build/src/components/user_profile.js +27 -0
- package/build/src/config.d.ts +27 -0
- package/build/src/config.js +40 -0
- package/build/src/hooks/use_authorized_apps.d.ts +16 -0
- package/build/src/hooks/use_authorized_apps.js +15 -0
- package/build/src/hooks/use_org_invitations.d.ts +19 -0
- package/build/src/hooks/use_org_invitations.js +20 -0
- package/build/src/hooks/use_organization.d.ts +23 -0
- package/build/src/hooks/use_organization.js +8 -0
- package/build/src/hooks/use_organizations.d.ts +18 -0
- package/build/src/hooks/use_organizations.js +14 -0
- package/build/src/hooks/use_password_strength.d.ts +11 -0
- package/build/src/hooks/use_password_strength.js +34 -0
- package/build/src/hooks/use_profile.d.ts +13 -0
- package/build/src/hooks/use_profile.js +28 -0
- package/build/src/hooks/use_resource.d.ts +11 -0
- package/build/src/hooks/use_resource.js +48 -0
- package/build/src/hooks/use_sessions.d.ts +16 -0
- package/build/src/hooks/use_sessions.js +15 -0
- package/build/src/hooks/use_sign_in.d.ts +6 -0
- package/build/src/hooks/use_sign_in.js +13 -0
- package/build/src/hooks/use_sign_out.d.ts +6 -0
- package/build/src/hooks/use_sign_out.js +11 -0
- package/build/src/hooks/use_switch_organization.d.ts +7 -0
- package/build/src/hooks/use_switch_organization.js +42 -0
- package/build/src/hooks/use_user.d.ts +6 -0
- package/build/src/hooks/use_user.js +5 -0
- package/build/src/use_auth.js +1 -1
- package/build/src/utils.d.ts +2 -0
- package/build/src/utils.js +18 -0
- package/package.json +9 -7
- package/styles.css +294 -0
package/README.md
CHANGED
|
@@ -108,6 +108,32 @@ import { AuthProvider } from '@dudousxd/adonis-authkit-react'
|
|
|
108
108
|
</AuthProvider>
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
## 5. Config + componentes prontos
|
|
112
|
+
|
|
113
|
+
Envolva a app com `<AuthkitProvider>` para configurar URLs/endpoints e use os
|
|
114
|
+
hooks headless e componentes prontos:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import '@dudousxd/adonis-authkit-react/styles.css'
|
|
118
|
+
import {
|
|
119
|
+
AuthkitProvider,
|
|
120
|
+
useSignIn, useSignOut, useUser, useProfile, useSessions, useAuthorizedApps,
|
|
121
|
+
SignInButton, SignOutButton, UserButton, UserProfile, AuthorizedApps,
|
|
122
|
+
} from '@dudousxd/adonis-authkit-react'
|
|
123
|
+
|
|
124
|
+
<AuthkitProvider config={{ csrfToken: page.props.csrfToken }}>
|
|
125
|
+
<UserButton />
|
|
126
|
+
<UserProfile />
|
|
127
|
+
<AuthorizedApps />
|
|
128
|
+
</AuthkitProvider>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Defaults dos endpoints apontam para as rotas reais do host-kit
|
|
132
|
+
(`/auth/login`, `/account/logout`, `/account/security`, `/account/security/profile`,
|
|
133
|
+
`/account/apps`, …). Numa topologia de *client app*, aponte-os para rotas locais que
|
|
134
|
+
redirecionam para o IdP. Temável via CSS vars `--authkit-*`. Veja a
|
|
135
|
+
[doc de React](https://...) para detalhes.
|
|
136
|
+
|
|
111
137
|
## Helpers puros
|
|
112
138
|
|
|
113
139
|
Para uso fora de componentes, as funções de papéis são exportadas e livres de React:
|
package/build/index.d.ts
CHANGED
|
@@ -1,9 +1,56 @@
|
|
|
1
1
|
export { useAuth } from './src/use_auth.js';
|
|
2
2
|
export { AuthProvider, AuthContext } from './src/provider.js';
|
|
3
3
|
export type { AuthProviderProps } from './src/provider.js';
|
|
4
|
+
export { AuthkitProvider } from './src/authkit_provider.js';
|
|
5
|
+
export type { AuthkitProviderProps } from './src/authkit_provider.js';
|
|
6
|
+
export { AuthkitConfigContext, useAuthkitConfig, resolveConfig, buildAuthUrl, DEFAULT_CONFIG, } from './src/config.js';
|
|
7
|
+
export type { AuthkitConfig, ResolvedAuthkitConfig, AuthkitEndpoints, } from './src/config.js';
|
|
8
|
+
export { useSignIn } from './src/hooks/use_sign_in.js';
|
|
9
|
+
export type { SignInOptions } from './src/hooks/use_sign_in.js';
|
|
10
|
+
export { useSignOut } from './src/hooks/use_sign_out.js';
|
|
11
|
+
export type { SignOutOptions } from './src/hooks/use_sign_out.js';
|
|
12
|
+
export { useUser } from './src/hooks/use_user.js';
|
|
13
|
+
export type { UseUserResult } from './src/hooks/use_user.js';
|
|
14
|
+
export { useProfile } from './src/hooks/use_profile.js';
|
|
15
|
+
export type { UseProfileResult, ProfileUpdate } from './src/hooks/use_profile.js';
|
|
16
|
+
export { useSessions } from './src/hooks/use_sessions.js';
|
|
17
|
+
export type { UseSessionsResult, AuthSession } from './src/hooks/use_sessions.js';
|
|
18
|
+
export { useAuthorizedApps } from './src/hooks/use_authorized_apps.js';
|
|
19
|
+
export type { UseAuthorizedAppsResult, AuthorizedApp } from './src/hooks/use_authorized_apps.js';
|
|
20
|
+
export { useOrganizations } from './src/hooks/use_organizations.js';
|
|
21
|
+
export type { UseOrganizationsResult, OrgEntry } from './src/hooks/use_organizations.js';
|
|
22
|
+
export { useOrganization } from './src/hooks/use_organization.js';
|
|
23
|
+
export type { UseOrganizationResult, ActiveOrgDetail, OrgMemberEntry } from './src/hooks/use_organization.js';
|
|
24
|
+
export { useSwitchOrganization } from './src/hooks/use_switch_organization.js';
|
|
25
|
+
export type { UseSwitchOrganizationResult } from './src/hooks/use_switch_organization.js';
|
|
26
|
+
export { useOrgInvitations } from './src/hooks/use_org_invitations.js';
|
|
27
|
+
export type { UseOrgInvitationsResult, OrgInvitationEntry } from './src/hooks/use_org_invitations.js';
|
|
28
|
+
export { jsonRequest, useResource } from './src/hooks/use_resource.js';
|
|
29
|
+
export type { ResourceState } from './src/hooks/use_resource.js';
|
|
30
|
+
export { usePasswordStrength, heuristicScorer, } from './src/hooks/use_password_strength.js';
|
|
31
|
+
export type { PasswordStrengthScore, PasswordStrengthResult, PasswordScorer, UsePasswordStrengthOptions, } from './src/hooks/use_password_strength.js';
|
|
32
|
+
export { deriveInitials, currentUrl } from './src/utils.js';
|
|
4
33
|
export { Authenticated, Guest } from './src/components/authenticated.js';
|
|
5
34
|
export type { AuthenticatedProps, GuestProps } from './src/components/authenticated.js';
|
|
6
35
|
export { Can } from './src/components/can.js';
|
|
7
36
|
export type { CanProps } from './src/components/can.js';
|
|
37
|
+
export { SignInButton } from './src/components/sign_in_button.js';
|
|
38
|
+
export type { SignInButtonProps } from './src/components/sign_in_button.js';
|
|
39
|
+
export { SignOutButton } from './src/components/sign_out_button.js';
|
|
40
|
+
export type { SignOutButtonProps } from './src/components/sign_out_button.js';
|
|
41
|
+
export { Avatar } from './src/components/avatar.js';
|
|
42
|
+
export type { AvatarProps } from './src/components/avatar.js';
|
|
43
|
+
export { UserButton } from './src/components/user_button.js';
|
|
44
|
+
export type { UserButtonProps } from './src/components/user_button.js';
|
|
45
|
+
export { UserProfile } from './src/components/user_profile.js';
|
|
46
|
+
export type { UserProfileProps } from './src/components/user_profile.js';
|
|
47
|
+
export { AuthorizedApps } from './src/components/authorized_apps.js';
|
|
48
|
+
export type { AuthorizedAppsProps } from './src/components/authorized_apps.js';
|
|
49
|
+
export { PasswordStrengthMeter } from './src/components/password_strength_meter.js';
|
|
50
|
+
export type { PasswordStrengthMeterProps } from './src/components/password_strength_meter.js';
|
|
51
|
+
export { OrganizationSwitcher } from './src/components/organization_switcher.js';
|
|
52
|
+
export type { OrganizationSwitcherProps } from './src/components/organization_switcher.js';
|
|
53
|
+
export { OrganizationProfile } from './src/components/organization_profile.js';
|
|
54
|
+
export type { OrganizationProfileProps } from './src/components/organization_profile.js';
|
|
8
55
|
export { hasGlobalRole, hasAnyGlobalRole, hasAllGlobalRoles, hasAppRole, hasAnyAppRole, hasAllAppRoles, } from './src/roles.js';
|
|
9
56
|
export type { AuthUser, AuthSharedProps, AuthState } from './src/types.js';
|
package/build/index.js
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
export { useAuth } from './src/use_auth.js';
|
|
2
2
|
export { AuthProvider, AuthContext } from './src/provider.js';
|
|
3
|
+
export { AuthkitProvider } from './src/authkit_provider.js';
|
|
4
|
+
export { AuthkitConfigContext, useAuthkitConfig, resolveConfig, buildAuthUrl, DEFAULT_CONFIG, } from './src/config.js';
|
|
5
|
+
export { useSignIn } from './src/hooks/use_sign_in.js';
|
|
6
|
+
export { useSignOut } from './src/hooks/use_sign_out.js';
|
|
7
|
+
export { useUser } from './src/hooks/use_user.js';
|
|
8
|
+
export { useProfile } from './src/hooks/use_profile.js';
|
|
9
|
+
export { useSessions } from './src/hooks/use_sessions.js';
|
|
10
|
+
export { useAuthorizedApps } from './src/hooks/use_authorized_apps.js';
|
|
11
|
+
export { useOrganizations } from './src/hooks/use_organizations.js';
|
|
12
|
+
export { useOrganization } from './src/hooks/use_organization.js';
|
|
13
|
+
export { useSwitchOrganization } from './src/hooks/use_switch_organization.js';
|
|
14
|
+
export { useOrgInvitations } from './src/hooks/use_org_invitations.js';
|
|
15
|
+
export { jsonRequest, useResource } from './src/hooks/use_resource.js';
|
|
16
|
+
export { usePasswordStrength, heuristicScorer, } from './src/hooks/use_password_strength.js';
|
|
17
|
+
export { deriveInitials, currentUrl } from './src/utils.js';
|
|
3
18
|
export { Authenticated, Guest } from './src/components/authenticated.js';
|
|
4
19
|
export { Can } from './src/components/can.js';
|
|
20
|
+
export { SignInButton } from './src/components/sign_in_button.js';
|
|
21
|
+
export { SignOutButton } from './src/components/sign_out_button.js';
|
|
22
|
+
export { Avatar } from './src/components/avatar.js';
|
|
23
|
+
export { UserButton } from './src/components/user_button.js';
|
|
24
|
+
export { UserProfile } from './src/components/user_profile.js';
|
|
25
|
+
export { AuthorizedApps } from './src/components/authorized_apps.js';
|
|
26
|
+
export { PasswordStrengthMeter } from './src/components/password_strength_meter.js';
|
|
27
|
+
export { OrganizationSwitcher } from './src/components/organization_switcher.js';
|
|
28
|
+
export { OrganizationProfile } from './src/components/organization_profile.js';
|
|
5
29
|
export { hasGlobalRole, hasAnyGlobalRole, hasAllGlobalRoles, hasAppRole, hasAnyAppRole, hasAllAppRoles, } from './src/roles.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AuthkitConfig } from './config.js';
|
|
3
|
+
import type { AuthSharedProps } from './types.js';
|
|
4
|
+
export interface AuthkitProviderProps {
|
|
5
|
+
config?: AuthkitConfig;
|
|
6
|
+
value?: AuthSharedProps['authkit'];
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function AuthkitProvider({ config, value, children }: AuthkitProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<{
|
|
10
|
+
user: import("./types.js").AuthUser | null;
|
|
11
|
+
globalRoles: string[];
|
|
12
|
+
appRoles?: string[];
|
|
13
|
+
} | undefined>> | import("react").FunctionComponentElement<import("react").ProviderProps<import("./config.js").ResolvedAuthkitConfig>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { AuthContext } from './provider.js';
|
|
3
|
+
import { AuthkitConfigContext, resolveConfig } from './config.js';
|
|
4
|
+
export function AuthkitProvider({ config, value, children }) {
|
|
5
|
+
const resolved = resolveConfig(config);
|
|
6
|
+
const tree = createElement(AuthkitConfigContext.Provider, { value: resolved }, children);
|
|
7
|
+
if (value !== undefined) {
|
|
8
|
+
return createElement(AuthContext.Provider, { value }, tree);
|
|
9
|
+
}
|
|
10
|
+
return tree;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AuthorizedAppsProps {
|
|
2
|
+
className?: string;
|
|
3
|
+
revokeLabel?: string;
|
|
4
|
+
emptyLabel?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function AuthorizedApps({ className, revokeLabel, emptyLabel, }: AuthorizedAppsProps): import("react").DetailedReactHTMLElement<{
|
|
7
|
+
className: string;
|
|
8
|
+
}, HTMLElement>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { useAuthorizedApps } from '../hooks/use_authorized_apps.js';
|
|
3
|
+
export function AuthorizedApps({ className, revokeLabel = 'Revogar', emptyLabel = 'Nenhum app autorizado.', }) {
|
|
4
|
+
const { data, loading, error, actions } = useAuthorizedApps();
|
|
5
|
+
if (loading && !data) {
|
|
6
|
+
return createElement('div', { className: 'authkit-apps__loading' }, 'Carregando…');
|
|
7
|
+
}
|
|
8
|
+
if (error) {
|
|
9
|
+
return createElement('p', { className: 'authkit-error', role: 'alert' }, error.message);
|
|
10
|
+
}
|
|
11
|
+
const apps = data ?? [];
|
|
12
|
+
if (apps.length === 0) {
|
|
13
|
+
return createElement('p', { className: 'authkit-apps__empty' }, emptyLabel);
|
|
14
|
+
}
|
|
15
|
+
return createElement('ul', { className: ['authkit-apps', className].filter(Boolean).join(' ') }, ...apps.map((app) => createElement('li', { key: app.clientId, className: 'authkit-apps__item' }, createElement('div', { className: 'authkit-apps__info' }, app.logoUrl
|
|
16
|
+
? createElement('img', {
|
|
17
|
+
className: 'authkit-apps__logo',
|
|
18
|
+
src: app.logoUrl,
|
|
19
|
+
alt: '',
|
|
20
|
+
})
|
|
21
|
+
: null, createElement('span', { className: 'authkit-apps__name' }, app.name ?? app.clientId)), createElement('button', {
|
|
22
|
+
type: 'button',
|
|
23
|
+
className: 'authkit-button authkit-button--danger',
|
|
24
|
+
onClick: () => void actions.revoke(app.clientId),
|
|
25
|
+
}, revokeLabel))));
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AuthUser } from '../types.js';
|
|
2
|
+
export interface AvatarProps {
|
|
3
|
+
user: Pick<AuthUser, 'name' | 'email' | 'avatarUrl'>;
|
|
4
|
+
size?: number;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function Avatar({ user, size, className }: AvatarProps): import("react").DetailedReactHTMLElement<{
|
|
8
|
+
className: string;
|
|
9
|
+
src: string;
|
|
10
|
+
alt: string;
|
|
11
|
+
style: {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
}, HTMLElement> | import("react").DetailedReactHTMLElement<{
|
|
16
|
+
className: string;
|
|
17
|
+
style: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
'aria-hidden': true;
|
|
22
|
+
}, HTMLElement>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { deriveInitials } from '../utils.js';
|
|
3
|
+
export function Avatar({ user, size = 36, className }) {
|
|
4
|
+
const cls = ['authkit-avatar', className].filter(Boolean).join(' ');
|
|
5
|
+
const style = { width: size, height: size };
|
|
6
|
+
if (user.avatarUrl) {
|
|
7
|
+
return createElement('img', {
|
|
8
|
+
className: cls,
|
|
9
|
+
src: user.avatarUrl,
|
|
10
|
+
alt: user.name ?? user.email ?? '',
|
|
11
|
+
style,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return createElement('span', { className: cls, style, 'aria-hidden': true }, deriveInitials(user.name, user.email));
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface OrganizationProfileProps {
|
|
2
|
+
inviteLabel?: string;
|
|
3
|
+
leaveLabel?: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function OrganizationProfile({ inviteLabel, leaveLabel, className, }: OrganizationProfileProps): import("react").DetailedReactHTMLElement<{
|
|
7
|
+
className: string;
|
|
8
|
+
}, HTMLElement> | null;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createElement, useState } from 'react';
|
|
2
|
+
import { useOrganizations } from '../hooks/use_organizations.js';
|
|
3
|
+
import { useOrganization } from '../hooks/use_organization.js';
|
|
4
|
+
import { useAuth } from '../use_auth.js';
|
|
5
|
+
import { useAuthkitConfig } from '../config.js';
|
|
6
|
+
import { jsonRequest } from '../hooks/use_resource.js';
|
|
7
|
+
export function OrganizationProfile({ inviteLabel = 'Convidar membro', leaveLabel = 'Sair da organização', className, }) {
|
|
8
|
+
const { isAuthenticated } = useAuth();
|
|
9
|
+
const config = useAuthkitConfig();
|
|
10
|
+
const { activeOrgId, actions: orgListActions } = useOrganizations();
|
|
11
|
+
const { data: org, loading, error, actions } = useOrganization(activeOrgId);
|
|
12
|
+
const [inviteEmail, setInviteEmail] = useState('');
|
|
13
|
+
const [inviteRole, setInviteRole] = useState('member');
|
|
14
|
+
const [inviteLoading, setInviteLoading] = useState(false);
|
|
15
|
+
const [inviteError, setInviteError] = useState(null);
|
|
16
|
+
if (!isAuthenticated || !activeOrgId)
|
|
17
|
+
return null;
|
|
18
|
+
if (loading)
|
|
19
|
+
return createElement('div', { className: 'authkit-org-profile__loading' }, 'Carregando…');
|
|
20
|
+
if (error)
|
|
21
|
+
return createElement('div', { className: 'authkit-error' }, error.message);
|
|
22
|
+
if (!org)
|
|
23
|
+
return null;
|
|
24
|
+
const base = config.endpoints.orgs.replace('/json', '');
|
|
25
|
+
const handleInvite = async (e) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
if (!inviteEmail.trim())
|
|
28
|
+
return;
|
|
29
|
+
setInviteLoading(true);
|
|
30
|
+
setInviteError(null);
|
|
31
|
+
try {
|
|
32
|
+
await jsonRequest(`${base}/${encodeURIComponent(activeOrgId)}/invite`, {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
body: JSON.stringify({ email: inviteEmail.trim(), role: inviteRole }),
|
|
35
|
+
csrfToken: config.csrfToken,
|
|
36
|
+
});
|
|
37
|
+
setInviteEmail('');
|
|
38
|
+
await actions.refetch();
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
setInviteError(err);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
setInviteLoading(false);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const handleLeave = async () => {
|
|
48
|
+
try {
|
|
49
|
+
await jsonRequest(`${base}/${encodeURIComponent(activeOrgId)}/leave`, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
csrfToken: config.csrfToken,
|
|
52
|
+
});
|
|
53
|
+
await orgListActions.refetch();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const memberList = createElement('div', { className: 'authkit-org-profile__members' }, createElement('h3', { className: 'authkit-org-profile__section-title' }, 'Membros'), ...(org.members.length === 0
|
|
59
|
+
? [createElement('p', { className: 'authkit-org-profile__empty' }, 'Nenhum membro.')]
|
|
60
|
+
: org.members.map((m) => createElement('div', { key: m.accountId, className: 'authkit-org-profile__member' }, createElement('div', { className: 'authkit-org-profile__member-info' }, createElement('span', { className: 'authkit-org-profile__member-email' }, m.email ?? m.accountId), createElement('span', { className: 'authkit-org-profile__member-role' }, m.role))))));
|
|
61
|
+
const inviteForm = org.canManage
|
|
62
|
+
? createElement('form', { className: 'authkit-org-profile__invite-form', onSubmit: handleInvite }, createElement('h3', { className: 'authkit-org-profile__section-title' }, inviteLabel), createElement('input', {
|
|
63
|
+
className: 'authkit-input',
|
|
64
|
+
type: 'email',
|
|
65
|
+
placeholder: 'Email',
|
|
66
|
+
value: inviteEmail,
|
|
67
|
+
onChange: (e) => setInviteEmail(e.target.value),
|
|
68
|
+
}), createElement('input', {
|
|
69
|
+
className: 'authkit-input',
|
|
70
|
+
placeholder: 'Papel (ex: member)',
|
|
71
|
+
value: inviteRole,
|
|
72
|
+
onChange: (e) => setInviteRole(e.target.value),
|
|
73
|
+
}), inviteError
|
|
74
|
+
? createElement('p', { className: 'authkit-error', role: 'alert' }, inviteError.message)
|
|
75
|
+
: null, createElement('button', {
|
|
76
|
+
type: 'submit',
|
|
77
|
+
className: 'authkit-button authkit-button--primary',
|
|
78
|
+
disabled: inviteLoading,
|
|
79
|
+
}, inviteLoading ? 'Enviando…' : inviteLabel))
|
|
80
|
+
: null;
|
|
81
|
+
const leaveButton = createElement('button', {
|
|
82
|
+
type: 'button',
|
|
83
|
+
className: 'authkit-button authkit-button--danger',
|
|
84
|
+
onClick: handleLeave,
|
|
85
|
+
}, leaveLabel);
|
|
86
|
+
return createElement('div', { className: ['authkit-card', 'authkit-org-profile', className].filter(Boolean).join(' ') }, createElement('div', { className: 'authkit-org-profile__header' }, createElement('div', { className: 'authkit-org-profile__name' }, org.name), createElement('div', { className: 'authkit-org-profile__slug' }, org.slug)), memberList, inviteForm, leaveButton);
|
|
87
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface OrganizationSwitcherProps {
|
|
2
|
+
personalAccountLabel?: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function OrganizationSwitcher({ personalAccountLabel, className, }: OrganizationSwitcherProps): import("react").DetailedReactHTMLElement<{
|
|
6
|
+
className: string;
|
|
7
|
+
}, HTMLElement> | null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createElement, useState } from 'react';
|
|
2
|
+
import { useOrganizations } from '../hooks/use_organizations.js';
|
|
3
|
+
import { useSwitchOrganization } from '../hooks/use_switch_organization.js';
|
|
4
|
+
import { useAuth } from '../use_auth.js';
|
|
5
|
+
export function OrganizationSwitcher({ personalAccountLabel = 'Conta pessoal', className, }) {
|
|
6
|
+
const { isAuthenticated } = useAuth();
|
|
7
|
+
const { data: orgs, activeOrgId, supported } = useOrganizations();
|
|
8
|
+
const { activate, deactivate, loading: switching } = useSwitchOrganization();
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
if (!isAuthenticated || !supported)
|
|
11
|
+
return null;
|
|
12
|
+
const activeOrg = orgs?.find((o) => o.id === activeOrgId) ?? null;
|
|
13
|
+
const label = activeOrg ? activeOrg.name : personalAccountLabel;
|
|
14
|
+
const trigger = createElement('button', {
|
|
15
|
+
type: 'button',
|
|
16
|
+
className: 'authkit-orgswitcher__trigger',
|
|
17
|
+
'aria-haspopup': 'listbox',
|
|
18
|
+
'aria-expanded': open,
|
|
19
|
+
disabled: switching,
|
|
20
|
+
onClick: () => setOpen((v) => !v),
|
|
21
|
+
}, createElement('span', { className: 'authkit-orgswitcher__label' }, label), createElement('span', { className: 'authkit-orgswitcher__chevron', 'aria-hidden': 'true' }, '▾'));
|
|
22
|
+
const menu = open
|
|
23
|
+
? createElement('div', { className: 'authkit-orgswitcher__menu', role: 'listbox' }, createElement('button', {
|
|
24
|
+
type: 'button',
|
|
25
|
+
className: [
|
|
26
|
+
'authkit-orgswitcher__item',
|
|
27
|
+
!activeOrgId ? 'authkit-orgswitcher__item--active' : '',
|
|
28
|
+
]
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
.join(' '),
|
|
31
|
+
role: 'option',
|
|
32
|
+
'aria-selected': !activeOrgId,
|
|
33
|
+
onClick: async () => {
|
|
34
|
+
setOpen(false);
|
|
35
|
+
if (activeOrgId)
|
|
36
|
+
await deactivate();
|
|
37
|
+
},
|
|
38
|
+
}, createElement('span', { className: 'authkit-orgswitcher__item-name' }, personalAccountLabel)), ...(orgs ?? []).map((org) => createElement('button', {
|
|
39
|
+
key: org.id,
|
|
40
|
+
type: 'button',
|
|
41
|
+
className: [
|
|
42
|
+
'authkit-orgswitcher__item',
|
|
43
|
+
org.isActive ? 'authkit-orgswitcher__item--active' : '',
|
|
44
|
+
]
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.join(' '),
|
|
47
|
+
role: 'option',
|
|
48
|
+
'aria-selected': org.isActive,
|
|
49
|
+
onClick: async () => {
|
|
50
|
+
setOpen(false);
|
|
51
|
+
if (!org.isActive)
|
|
52
|
+
await activate(org.id);
|
|
53
|
+
},
|
|
54
|
+
}, createElement('span', { className: 'authkit-orgswitcher__item-name' }, org.name), createElement('span', { className: 'authkit-orgswitcher__item-role' }, org.role))))
|
|
55
|
+
: null;
|
|
56
|
+
return createElement('div', { className: ['authkit-orgswitcher', className].filter(Boolean).join(' ') }, trigger, menu);
|
|
57
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type PasswordScorer } from '../hooks/use_password_strength.js';
|
|
2
|
+
export interface PasswordStrengthMeterProps {
|
|
3
|
+
password: string;
|
|
4
|
+
scorer?: PasswordScorer;
|
|
5
|
+
showFeedback?: boolean;
|
|
6
|
+
labels?: [string, string, string, string, string];
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function PasswordStrengthMeter({ password, scorer, showFeedback, labels, className, }: PasswordStrengthMeterProps): import("react").DetailedReactHTMLElement<{
|
|
10
|
+
className: string;
|
|
11
|
+
}, HTMLElement>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { usePasswordStrength, } from '../hooks/use_password_strength.js';
|
|
3
|
+
const DEFAULT_LABELS = [
|
|
4
|
+
'Very weak',
|
|
5
|
+
'Weak',
|
|
6
|
+
'Fair',
|
|
7
|
+
'Good',
|
|
8
|
+
'Strong',
|
|
9
|
+
];
|
|
10
|
+
export function PasswordStrengthMeter({ password, scorer, showFeedback = true, labels = DEFAULT_LABELS, className, }) {
|
|
11
|
+
const { score, feedback } = usePasswordStrength(password, { scorer });
|
|
12
|
+
const cls = ['authkit-strength', className].filter(Boolean).join(' ');
|
|
13
|
+
const segments = [0, 1, 2, 3].map((i) => createElement('span', {
|
|
14
|
+
key: i,
|
|
15
|
+
className: [
|
|
16
|
+
'authkit-strength__segment',
|
|
17
|
+
i < score ? 'authkit-strength__segment--filled' : '',
|
|
18
|
+
]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(' '),
|
|
21
|
+
}));
|
|
22
|
+
const children = [
|
|
23
|
+
createElement('div', {
|
|
24
|
+
key: 'bar',
|
|
25
|
+
className: 'authkit-strength__bar',
|
|
26
|
+
role: 'meter',
|
|
27
|
+
'aria-valuemin': 0,
|
|
28
|
+
'aria-valuemax': 4,
|
|
29
|
+
'aria-valuenow': score,
|
|
30
|
+
'aria-label': labels[score],
|
|
31
|
+
'data-score': score,
|
|
32
|
+
}, segments),
|
|
33
|
+
createElement('span', { key: 'label', className: 'authkit-strength__label' }, labels[score]),
|
|
34
|
+
];
|
|
35
|
+
if (showFeedback && feedback && feedback.length > 0) {
|
|
36
|
+
children.push(createElement('ul', { key: 'feedback', className: 'authkit-strength__feedback' }, feedback.map((tip, i) => createElement('li', { key: i }, tip))));
|
|
37
|
+
}
|
|
38
|
+
return createElement('div', { className: cls }, children);
|
|
39
|
+
}
|