// @flow strict import * as React from 'react'; import {colorBackgroundTertiary} from '../../styles/variables/_color'; import { spaceSmall, spaceXSmall, spaceXXSmall, } from '../../styles/variables/_space'; import classify from '../../utils/classify'; import type {AvatarSize} from '../Avatar'; import {BaseAvatar} from '../Avatar'; import type {ElevationType, PlacementType} from '../Tooltip'; import {Tooltip} from '../Tooltip'; import css from './AvatarGroup.module.css'; const COLOR_SEQUENCE = ['blue', 'green', 'orange', 'red', 'gray']; export type AvatarGroupProps = { children?: React.Node, size?: AvatarSize, borderColor?: string, maxTooltipLines?: number, placement?: PlacementType, maxAvatars?: number, tooltipElevation?: ElevationType, }; export const AvatarGroup: React$AbstractComponent< AvatarGroupProps, HTMLDivElement, > = React.forwardRef( ( { children, size = 'medium', borderColor = colorBackgroundTertiary, maxTooltipLines = 7, placement = 'top', maxAvatars = 5, tooltipElevation, }: AvatarGroupProps, ref, ): React.Node => { const childAvatarCount = React.Children.count(children); const leftOverlap = { small: spaceXXSmall, medium: `${parseInt(spaceSmall) / 2}px`, large: spaceXSmall, extraLarge: spaceSmall, }; let colorIndex = -1; const avatarInGroup = (child, index, color) => { const {classNames, text} = child.props; const {wrapper, ...restClassNames} = classNames || {}; const avatar = React.cloneElement(child, { size, classNames: { wrapper: classify(css.avatarInGroup, wrapper), ...restClassNames, }, style: { borderColor, marginLeft: `-${index !== 0 ? leftOverlap[size] : 0}`, }, color, }); return text ? ( {avatar} ) : ( avatar ); }; const childrenArray = React.Children.toArray(children); const totalAvatarCount = childrenArray.length; const plusAvatar = () => { const nameList = []; for (let i = maxAvatars - 1; i < totalAvatarCount; i++) { const child = childrenArray[i]; const {text} = child.props; if (text) { nameList.push(text); } } const NameListNode = () => ( {nameList.map((name) => ( {name}
))}
); return ( } bodyMaxLines={maxTooltipLines} placement={placement} elevation={tooltipElevation} >
); }; const childrenWithProps = React.Children.map(children, (child, index) => { const {imageSrc} = child.props; if (!imageSrc) { colorIndex++; if (colorIndex === COLOR_SEQUENCE.length) { colorIndex = 0; } } const color = COLOR_SEQUENCE[colorIndex]; if (childAvatarCount <= maxAvatars) { return avatarInGroup(child, index, color); } else { if (index < maxAvatars - 1) { return avatarInGroup(child, index, color); } else if (index === maxAvatars) { return plusAvatar(); } } }); return (
{childrenWithProps}
); }, );