66 lines
1.5 KiB
TypeScript
66 lines
1.5 KiB
TypeScript
|
|
import { Avatar, AvatarFallback } from "@repo/shadcn-ui/components";
|
||
|
|
import { cn } from "@repo/shadcn-ui/lib/utils";
|
||
|
|
import type * as React from "react";
|
||
|
|
|
||
|
|
type InitialsProps = {
|
||
|
|
name?: string | null;
|
||
|
|
maxParts?: number;
|
||
|
|
fallback?: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const getInitials = ({ name, maxParts = 2, fallback = "?" }: InitialsProps): string => {
|
||
|
|
if (!name?.trim()) return fallback;
|
||
|
|
|
||
|
|
return (
|
||
|
|
name
|
||
|
|
.trim()
|
||
|
|
.split(/\s+/)
|
||
|
|
.filter(Boolean)
|
||
|
|
.slice(0, maxParts)
|
||
|
|
.map((p) => p[0]?.toUpperCase() ?? "")
|
||
|
|
.join("") || fallback
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export const Initials = (props: InitialsProps) => {
|
||
|
|
return <>{getInitials(props)}</>;
|
||
|
|
};
|
||
|
|
|
||
|
|
const VARIANT_CLASSES: Record<string, string> = {
|
||
|
|
primary: "bg-primary/10 text-primary",
|
||
|
|
muted: "bg-muted text-muted-foreground",
|
||
|
|
};
|
||
|
|
|
||
|
|
type InitialsAvatarProps = React.ComponentProps<typeof Avatar> & {
|
||
|
|
name?: string | null;
|
||
|
|
variant?: "primary" | "muted";
|
||
|
|
maxParts?: number;
|
||
|
|
fallback?: string;
|
||
|
|
fallbackClassName?: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const InitialsAvatar = ({
|
||
|
|
name,
|
||
|
|
variant = "muted",
|
||
|
|
maxParts = 2,
|
||
|
|
fallback = "?",
|
||
|
|
className,
|
||
|
|
fallbackClassName,
|
||
|
|
...props
|
||
|
|
}: InitialsAvatarProps) => {
|
||
|
|
return (
|
||
|
|
<Avatar
|
||
|
|
className={cn(
|
||
|
|
"size-10 border-2 shadow-sm",
|
||
|
|
variant === "primary" && "border-primary",
|
||
|
|
className
|
||
|
|
)}
|
||
|
|
{...props}
|
||
|
|
>
|
||
|
|
<AvatarFallback className={cn(VARIANT_CLASSES[variant], fallbackClassName)}>
|
||
|
|
<Initials fallback={fallback} maxParts={maxParts} name={name} />
|
||
|
|
</AvatarFallback>
|
||
|
|
</Avatar>
|
||
|
|
);
|
||
|
|
};
|