@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.2.30 → 0.2.32
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/CHANGELOG.md +1 -1
- package/dist/components/ui/navigation/index.d.ts +4 -1
- package/dist/components/ui/navigation/index.d.ts.map +1 -1
- package/dist/components/ui/navigation/index.esm.js +4 -0
- package/dist/components/ui/navigation/index.js +4 -0
- package/dist/components/ui/navigation/subscription-badge.d.ts +9 -0
- package/dist/components/ui/navigation/subscription-badge.d.ts.map +1 -0
- package/dist/components/ui/navigation/subscription-badge.esm.js +58 -0
- package/dist/components/ui/navigation/subscription-badge.js +58 -0
- package/dist/components/ui/navigation/types.d.ts +1 -0
- package/dist/components/ui/navigation/types.d.ts.map +1 -1
- package/dist/components/ui/navigation/user-avatar.d.ts +9 -0
- package/dist/components/ui/navigation/user-avatar.d.ts.map +1 -0
- package/dist/components/ui/navigation/user-avatar.esm.js +55 -0
- package/dist/components/ui/navigation/user-avatar.js +55 -0
- package/dist/components/ui/navigation/user-menu-examples.d.ts +8 -0
- package/dist/components/ui/navigation/user-menu-examples.d.ts.map +1 -0
- package/dist/components/ui/navigation/user-menu-examples.esm.js +125 -0
- package/dist/components/ui/navigation/user-menu-examples.js +125 -0
- package/dist/components/ui/navigation/user-menu-types.d.ts +218 -0
- package/dist/components/ui/navigation/user-menu-types.d.ts.map +1 -0
- package/dist/components/ui/navigation/user-menu-types.esm.js +5 -0
- package/dist/components/ui/navigation/user-menu-types.js +5 -0
- package/dist/components/ui/navigation/user-menu.d.ts +9 -0
- package/dist/components/ui/navigation/user-menu.d.ts.map +1 -0
- package/dist/components/ui/navigation/user-menu.esm.js +154 -0
- package/dist/components/ui/navigation/user-menu.js +154 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +5 -1
- package/dist/index.js +5 -1
- package/dist/styles.css +2 -2
- package/package.json +1 -1
- package/src/components/ui/navigation/index.ts +13 -0
- package/src/components/ui/navigation/subscription-badge.tsx +110 -0
- package/src/components/ui/navigation/types.ts +14 -0
- package/src/components/ui/navigation/user-avatar.tsx +111 -0
- package/src/components/ui/navigation/user-menu-examples.tsx +551 -0
- package/src/components/ui/navigation/user-menu-types.ts +308 -0
- package/src/components/ui/navigation/user-menu.tsx +354 -0
- package/src/index.ts +5 -1
- package/src/styles/components/navigation/user-menu.css +525 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubscriptionBadge Component
|
|
3
|
+
* Displays subscription tier with appropriate styling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use client'
|
|
7
|
+
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
import { SubscriptionBadgeProps } from './user-menu-types.js';
|
|
10
|
+
import { Badge } from '../badge.js';
|
|
11
|
+
|
|
12
|
+
// Default icons for subscription tiers
|
|
13
|
+
const StarIcon = () => (
|
|
14
|
+
<svg
|
|
15
|
+
width="12"
|
|
16
|
+
height="12"
|
|
17
|
+
viewBox="0 0 24 24"
|
|
18
|
+
fill="currentColor"
|
|
19
|
+
strokeWidth="0"
|
|
20
|
+
>
|
|
21
|
+
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// const CrownIcon = () => (
|
|
26
|
+
// <svg
|
|
27
|
+
// width="12"
|
|
28
|
+
// height="12"
|
|
29
|
+
// viewBox="0 0 24 24"
|
|
30
|
+
// fill="currentColor"
|
|
31
|
+
// strokeWidth="0"
|
|
32
|
+
// >
|
|
33
|
+
// <path d="M3 18h18l-2-12-4 6-3-6-3 6-4-6-2 12z"/>
|
|
34
|
+
// </svg>
|
|
35
|
+
// );
|
|
36
|
+
|
|
37
|
+
const DiamondIcon = () => (
|
|
38
|
+
<svg
|
|
39
|
+
width="12"
|
|
40
|
+
height="12"
|
|
41
|
+
viewBox="0 0 24 24"
|
|
42
|
+
fill="currentColor"
|
|
43
|
+
strokeWidth="0"
|
|
44
|
+
>
|
|
45
|
+
<path d="M6 3h12l4 6-10 12L2 9l4-6z"/>
|
|
46
|
+
</svg>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const SubscriptionBadge: React.FC<SubscriptionBadgeProps> = ({
|
|
50
|
+
subscription,
|
|
51
|
+
size = 'sm',
|
|
52
|
+
variant = 'default',
|
|
53
|
+
showIcon = true,
|
|
54
|
+
className = ''
|
|
55
|
+
}) => {
|
|
56
|
+
const getDefaultIcon = () => {
|
|
57
|
+
switch (subscription.tier) {
|
|
58
|
+
case 'pro':
|
|
59
|
+
return <StarIcon />;
|
|
60
|
+
case 'enterprise':
|
|
61
|
+
return <DiamondIcon />;
|
|
62
|
+
case 'free':
|
|
63
|
+
default:
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const getBadgeVariant = () => {
|
|
69
|
+
switch (subscription.tier) {
|
|
70
|
+
case 'pro':
|
|
71
|
+
return 'default' as const;
|
|
72
|
+
case 'enterprise':
|
|
73
|
+
return 'secondary' as const;
|
|
74
|
+
case 'free':
|
|
75
|
+
default:
|
|
76
|
+
return 'outline' as const;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getSizeClass = () => {
|
|
81
|
+
switch (size) {
|
|
82
|
+
case 'sm':
|
|
83
|
+
return 'subscription-badge--sm';
|
|
84
|
+
case 'lg':
|
|
85
|
+
return 'subscription-badge--lg';
|
|
86
|
+
default: // md
|
|
87
|
+
return 'subscription-badge--md';
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const icon = subscription.icon || (showIcon ? getDefaultIcon() : null);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Badge
|
|
95
|
+
variant={variant === 'default' ? getBadgeVariant() : variant}
|
|
96
|
+
className={`subscription-badge ${getSizeClass()} ${className}`}
|
|
97
|
+
>
|
|
98
|
+
{icon && (
|
|
99
|
+
<span className="subscription-badge__icon">
|
|
100
|
+
{icon}
|
|
101
|
+
</span>
|
|
102
|
+
)}
|
|
103
|
+
<span className="subscription-badge__label">
|
|
104
|
+
{subscription.label}
|
|
105
|
+
</span>
|
|
106
|
+
</Badge>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default SubscriptionBadge;
|
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
import { ReactNode } from 'react';
|
|
7
7
|
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// USER MENU EXPORTS
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
UserMenuProps,
|
|
14
|
+
UserMenuUser,
|
|
15
|
+
UserMenuSubscription,
|
|
16
|
+
UserMenuItem,
|
|
17
|
+
UserMenuGroup,
|
|
18
|
+
UserAvatarProps,
|
|
19
|
+
SubscriptionBadgeProps
|
|
20
|
+
} from './user-menu-types.js';
|
|
21
|
+
|
|
8
22
|
// ============================================================================
|
|
9
23
|
// COMMON NAVIGATION TYPES
|
|
10
24
|
// ============================================================================
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserAvatar Component
|
|
3
|
+
* Displays user avatar with fallback to initials
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use client'
|
|
7
|
+
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
import { UserAvatarProps } from './user-menu-types.js';
|
|
10
|
+
|
|
11
|
+
const UserIcon = () => (
|
|
12
|
+
<svg
|
|
13
|
+
width="24"
|
|
14
|
+
height="24"
|
|
15
|
+
viewBox="0 0 24 24"
|
|
16
|
+
fill="none"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
strokeWidth="2"
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
strokeLinejoin="round"
|
|
21
|
+
>
|
|
22
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
|
|
23
|
+
<circle cx="12" cy="7" r="4"/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export const UserAvatar: React.FC<UserAvatarProps> = ({
|
|
28
|
+
user,
|
|
29
|
+
size = 'md',
|
|
30
|
+
className = '',
|
|
31
|
+
fallbackClassName = ''
|
|
32
|
+
}) => {
|
|
33
|
+
const [imageError, setImageError] = React.useState(false);
|
|
34
|
+
const [imageLoading, setImageLoading] = React.useState(true);
|
|
35
|
+
|
|
36
|
+
const handleImageError = () => {
|
|
37
|
+
setImageError(true);
|
|
38
|
+
setImageLoading(false);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleImageLoad = () => {
|
|
42
|
+
setImageLoading(false);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const getSizeClasses = () => {
|
|
46
|
+
switch (size) {
|
|
47
|
+
case 'xs':
|
|
48
|
+
return 'user-avatar--xs';
|
|
49
|
+
case 'sm':
|
|
50
|
+
return 'user-avatar--sm';
|
|
51
|
+
case 'lg':
|
|
52
|
+
return 'user-avatar--lg';
|
|
53
|
+
case 'xl':
|
|
54
|
+
return 'user-avatar--xl';
|
|
55
|
+
default: // md
|
|
56
|
+
return 'user-avatar--md';
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const getInitials = () => {
|
|
61
|
+
if (user.fullName) {
|
|
62
|
+
return user.fullName
|
|
63
|
+
.split(' ')
|
|
64
|
+
.map(name => name.charAt(0))
|
|
65
|
+
.join('')
|
|
66
|
+
.toUpperCase()
|
|
67
|
+
.slice(0, 2);
|
|
68
|
+
}
|
|
69
|
+
if (user.firstName) {
|
|
70
|
+
return user.firstName.charAt(0).toUpperCase();
|
|
71
|
+
}
|
|
72
|
+
if (user.email) {
|
|
73
|
+
return user.email.charAt(0).toUpperCase();
|
|
74
|
+
}
|
|
75
|
+
return '?';
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const hasValidImage = user.avatar && !imageError;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div className={`user-avatar ${getSizeClasses()} ${className}`}>
|
|
82
|
+
{hasValidImage ? (
|
|
83
|
+
<>
|
|
84
|
+
<img
|
|
85
|
+
src={user.avatar}
|
|
86
|
+
alt={user.fullName || user.firstName || 'User avatar'}
|
|
87
|
+
className="user-avatar__image"
|
|
88
|
+
onError={handleImageError}
|
|
89
|
+
onLoad={handleImageLoad}
|
|
90
|
+
style={{
|
|
91
|
+
display: imageLoading ? 'none' : 'block'
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
{imageLoading && (
|
|
95
|
+
<div className={`user-avatar__fallback ${fallbackClassName}`}>
|
|
96
|
+
<UserIcon />
|
|
97
|
+
</div>
|
|
98
|
+
)}
|
|
99
|
+
</>
|
|
100
|
+
) : (
|
|
101
|
+
<div className={`user-avatar__fallback ${fallbackClassName}`}>
|
|
102
|
+
<span className="user-avatar__initials">
|
|
103
|
+
{getInitials()}
|
|
104
|
+
</span>
|
|
105
|
+
</div>
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default UserAvatar;
|