import React, { useCallback, useMemo } from 'react';
import { StyleSheet, View } from 'react-native';
import { UserResponse } from 'stream-chat';
import { Avatar, AvatarProps } from './Avatar';
import { iconSizes } from './constants';
import { UserAvatar, UserAvatarProps } from './UserAvatar';
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
import { PeopleIcon } from '../../../icons/users';
import { primitives } from '../../../theme';
import { BadgeCount, BadgeCountProps, OnlineIndicator, OnlineIndicatorProps } from '../Badge';
export type AvatarGroupProps = {
/**
* The size of the avatar group.
*/
size: 'lg' | 'xl' | '2xl';
/**
* The items to display in the avatar group.
*/
items: React.ReactNode[];
};
// Sizes accounts for the border width as well
const sizes = {
'2xl': {
width: 64,
height: 64,
},
xl: {
width: 48,
height: 48,
},
lg: {
width: 44,
height: 44,
},
};
const buildForTwo = (items: React.ReactNode[]) => {
return (
<>
{items[0]}
{items[1]}
>
);
};
const buildForThree = (items: React.ReactNode[]) => {
return (
<>
{items[0]}
{items[1]}
{items[2]}
>
);
};
const buildForFour = (items: React.ReactNode[]) => {
return (
<>
{items[0]}
{items[1]}
{items[2]}
{items[3]}
>
);
};
const avatarSize: Record = {
'2xl': 'lg',
xl: 'md',
lg: 'sm',
};
const badgeCountSize: Record = {
'2xl': 'lg',
xl: 'md',
lg: 'sm',
};
export const AvatarGroup = (props: AvatarGroupProps) => {
const { size, items = [] } = props;
const {
theme: { semantics },
} = useTheme();
const avatarGroupStyles = useUserAvatarGroupStyles();
const buildForOne = useCallback(
(item: React.ReactNode) => {
return buildForTwo([
item,
}
size={avatarSize[size]}
/>,
]);
},
[avatarGroupStyles.userAvatarWrapper, semantics, size],
);
const buildForMore = useCallback(
(items: React.ReactNode[]) => {
const remainingItems = items.length - 2;
return (
<>
{items[0]}
{items[1]}
>
);
},
[size],
);
const renderItems = useMemo(() => {
const length = items.length;
if (length === 1) {
return buildForOne(items[0]);
}
if (length === 2) {
return buildForTwo(items);
}
if (length === 3) {
return buildForThree(items);
}
if (length === 4) {
return buildForFour(items);
}
return buildForMore(items);
}, [buildForMore, buildForOne, items]);
return (
{renderItems}
);
};
export type UserAvatarGroupProps = Pick & {
/**
* The users to display in the avatar group.
*/
users: UserResponse[];
/**
* Whether to show the online indicator.
*/
showOnlineIndicator?: boolean;
};
const userAvatarSize: Record = {
'2xl': 'lg',
xl: 'md',
lg: 'sm',
};
const onlineIndicatorSize: Record = {
'2xl': 'xl',
xl: 'xl',
lg: 'lg',
};
export const UserAvatarGroup = ({
users,
showOnlineIndicator = true,
size,
}: UserAvatarGroupProps) => {
const styles = useUserAvatarGroupStyles();
return (
(
))}
/>
{showOnlineIndicator ? (
) : null}
);
};
const useUserAvatarGroupStyles = () => {
const {
theme: { semantics },
} = useTheme();
return useMemo(
() =>
StyleSheet.create({
userAvatarWrapper: {
borderWidth: 2,
borderColor: semantics.borderCoreInverse,
borderRadius: primitives.radiusMax,
},
onlineIndicatorWrapper: {
position: 'absolute',
right: 0,
top: 0,
},
}),
[semantics],
);
};
const styles = StyleSheet.create({
container: {},
topStart: {
position: 'absolute',
top: 0,
left: 0,
},
bottomEnd: {
position: 'absolute',
bottom: 0,
right: 0,
},
topEnd: {
position: 'absolute',
top: 0,
right: 0,
},
bottomStart: {
position: 'absolute',
bottom: 0,
left: 0,
},
topCenter: {
alignItems: 'center',
},
bottomCenter: {
position: 'absolute',
bottom: 0,
alignSelf: 'center',
},
});