@slyxup/ui 0.2.15 → 0.3.1

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.
@@ -1,101 +0,0 @@
1
- import { useAuth, useUser } from '@slyxup/react';
2
- import { useEffect, useRef, useState } from 'react';
3
- import { injectStyles } from '../../styles';
4
-
5
- function initials(name: string | null | undefined, email: string): string {
6
- if (name?.trim()) return name.trim().slice(0, 1).toUpperCase();
7
- return email.slice(0, 1).toUpperCase();
8
- }
9
-
10
- export interface UserButtonProps {
11
- /** Called when "Profile settings" is clicked. Use to open <UserProfile />. */
12
- onProfileClick?: () => void;
13
- }
14
-
15
- /** Avatar + dropdown with profile actions and sign out. */
16
- export function UserButton({ onProfileClick }: UserButtonProps) {
17
- injectStyles();
18
- const { isLoaded, user } = useUser();
19
- const { signOut } = useAuth();
20
- const [open, setOpen] = useState(false);
21
- const wrapRef = useRef<HTMLDivElement>(null);
22
-
23
- useEffect(() => {
24
- function onDocClick(e: MouseEvent) {
25
- if (wrapRef.current && !wrapRef.current.contains(e.target as Node))
26
- setOpen(false);
27
- }
28
- function onKey(e: KeyboardEvent) {
29
- if (e.key === 'Escape') setOpen(false);
30
- }
31
- document.addEventListener('mousedown', onDocClick);
32
- document.addEventListener('keydown', onKey);
33
- return () => {
34
- document.removeEventListener('mousedown', onDocClick);
35
- document.removeEventListener('keydown', onKey);
36
- };
37
- }, []);
38
-
39
- if (!isLoaded)
40
- return <div className="slx-userbtn-avatar" aria-hidden="true" />;
41
- const email = user?.email ?? '';
42
- const name = user?.firstName;
43
-
44
- function handleProfileClick() {
45
- setOpen(false);
46
- onProfileClick?.();
47
- }
48
-
49
- async function onSignOut() {
50
- await signOut();
51
- setOpen(false);
52
- }
53
-
54
- return (
55
- <div className="slx-userbtn-wrap" ref={wrapRef}>
56
- <button
57
- type="button"
58
- className="slx-userbtn-avatar"
59
- onClick={() => setOpen((o) => !o)}
60
- aria-haspopup="menu"
61
- aria-expanded={open}
62
- aria-label="Account menu"
63
- >
64
- {user?.avatarUrl ? (
65
- <img src={user.avatarUrl} alt="" />
66
- ) : (
67
- initials(name, email || '?')
68
- )}
69
- </button>
70
-
71
- {open && (
72
- <div className="slx-menu" role="menu">
73
- <div className="slx-menu-header">
74
- <p className="slx-menu-name">
75
- {name
76
- ? `${name}${user?.lastName ? ` ${user.lastName}` : ''}`
77
- : email.split('@')[0]}
78
- </p>
79
- <p className="slx-menu-email">{email}</p>
80
- </div>
81
- <button
82
- type="button"
83
- className="slx-menu-item"
84
- role="menuitem"
85
- onClick={handleProfileClick}
86
- >
87
- Profile settings
88
- </button>
89
- <button
90
- type="button"
91
- className="slx-menu-item slx-menu-item-danger"
92
- role="menuitem"
93
- onClick={onSignOut}
94
- >
95
- Sign out
96
- </button>
97
- </div>
98
- )}
99
- </div>
100
- );
101
- }