import type { FC } from 'react' import type { AvatarSize } from '@/app/components/base/avatar' import { memo } from 'react' import { AvatarFallback, AvatarImage, AvatarRoot } from '@/app/components/base/avatar' import { getUserColor } from '@/app/components/workflow/collaboration/utils/user-color' import { useAppContext } from '@/context/app-context' type User = { id: string name: string avatar_url?: string | null } function numericPxToAvatarSize(px: number): AvatarSize { const candidates: { px: number, size: AvatarSize }[] = [ { px: 16, size: 'xxs' }, { px: 20, size: 'xs' }, { px: 24, size: 'sm' }, { px: 32, size: 'md' }, { px: 36, size: 'lg' }, { px: 40, size: 'xl' }, { px: 48, size: '2xl' }, { px: 64, size: '3xl' }, ] let best = candidates[0]! let bestDist = Math.abs(px - best.px) for (const c of candidates) { const d = Math.abs(px - c.px) if (d < bestDist || (d === bestDist && c.px < best.px)) { best = c bestDist = d } } return best.size } type UserAvatarListProps = { users: User[] maxVisible?: number size?: number className?: string showCount?: boolean } export const UserAvatarList: FC = memo(({ users, maxVisible = 3, size = 24, className = '', showCount = true, }) => { const { userProfile } = useAppContext() if (!users.length) return null const shouldShowCount = showCount && users.length > maxVisible const actualMaxVisible = shouldShowCount ? Math.max(1, maxVisible - 1) : maxVisible const visibleUsers = users.slice(0, actualMaxVisible) const remainingCount = users.length - actualMaxVisible const currentUserId = userProfile?.id const avatarSize = numericPxToAvatarSize(size) return (
{visibleUsers.map((user, index) => { const isCurrentUser = user.id === currentUserId const userColor = isCurrentUser ? undefined : getUserColor(user.id) return (
{user.avatar_url && ( )} {user.name?.[0]?.toLocaleUpperCase()}
) }, )} {shouldShowCount && remainingCount > 0 && (
+ {remainingCount}
)}
) }) UserAvatarList.displayName = 'UserAvatarList'