wix-style-react
Version:
200 lines (180 loc) • 4.93 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { st, classes } from './AvatarGroup.st.css';
import Avatar from '../Avatar';
import Text from '../Text';
import Divider from '../Divider';
import { dataHooks } from './constants';
const getRandomColorPattern = () => {
const patternColor = [
'A1',
'A2',
'A3',
'A4',
'A5',
'A6',
'A1',
'A2',
'A3',
'A4',
'A5',
'A6',
];
const firstIndex = Math.floor(Math.random() * 6); // get random number between 0 to 5
const lastIndex = firstIndex + 6;
return patternColor.slice(firstIndex, lastIndex);
};
const myPatternColors = getRandomColorPattern();
const getAvatarColor = ({ index, color }) => {
let colorIndex = index;
if (color) {
return color;
}
while (colorIndex > 5) {
colorIndex = colorIndex - 6;
}
return myPatternColors[colorIndex];
};
const setAvatarCompPropsArr = (items, avatarSize, itemsMaxLength) => {
// gets the items prop from avatarGroup component and set it with the proper prop for avatar component such as size, shape etc.
const avatarItems = items.map((item, index) => {
const { ariaLabel, color, imgProps, name, text, placeholder, title } = item;
const size = avatarSize === 'small' ? 'size24' : 'size30';
const shape = 'circle';
const avatarColor = getAvatarColor({ index, color });
return {
size,
shape,
ariaLabel,
color: avatarColor,
imgProps,
name,
text,
placeholder,
title,
};
});
const avatars = avatarItemsLenghtHandler(
avatarItems,
avatarItems.length,
itemsMaxLength,
avatarSize,
);
return avatars;
};
const avatarItemsLenghtHandler = (items, itemsLength, maxItems, avatarSize) => {
const moreItemAvatar = {
text: `${itemsLength - maxItems + 1}+`,
size: avatarSize === 'small' ? 'size24' : 'size30',
isMoreItem: true,
};
if (itemsLength > maxItems && maxItems >= 2) {
items.length = maxItems;
items[maxItems - 1] = moreItemAvatar;
}
return items;
};
const MoreIndicator = ({ text, size }) => (
<div
data-hook={dataHooks.avatarGroupMoreItem}
className={st(classes.moreIndicatorCircle, { size })}
>
<Text secondary weight="normal" className={classes.moreIndicatorText}>
{text}
</Text>
</div>
);
/** AvatarGroup */
const AvatarGroup = ({
dataHook,
className,
type,
items,
maxItems,
size,
showDivider,
}) => {
const itemsMaxLength = maxItems < 2 ? 2 : maxItems;
const avatarCompArr = setAvatarCompPropsArr(items, size, itemsMaxLength);
return (
<div
className={st(classes.root, { size, type }, className)}
data-hook={dataHook}
>
{avatarCompArr.map((item, index) => {
const key = `${Object.values(item)}`;
if (item.isMoreItem) {
return (
<div key={key} className={classes.avatarContainer}>
<MoreIndicator text={item.text} size={size} />
</div>
);
}
const shouldIncludeDivider =
index === 0 && showDivider && avatarCompArr.length > 1;
return (
<React.Fragment key={key}>
<div className={classes.avatarContainer}>
<Avatar {...item} dataHook={dataHooks.avatarGroupItem} />
</div>
{shouldIncludeDivider && (
<Divider
direction={'vertical'}
className={st(classes.divider, { size, type })}
/>
)}
</React.Fragment>
);
})}
</div>
);
};
AvatarGroup.displayName = 'AvatarGroup';
AvatarGroup.propTypes = {
/**
* Applies a data-hook HTML attribute that can be used in the tests
*/
dataHook: PropTypes.string,
/**
* Allows to apply a CSS class to the component’s root element
*/
className: PropTypes.string,
/**
* Changes the way avatars are displayed inside the group.
*/
type: PropTypes.oneOf(['stretched', 'condensed']),
/**
* Changes the size of avatars in the group
*/
size: PropTypes.oneOf(['medium', 'small']),
/**
* Separates the first avatar with a divider from the rest of the group
*/
showDivider: PropTypes.bool,
/**
* Sets the maximum number of avatars to be displayed. Number which exceeds this limit will be hidden under the “N+” item.
*/
maxItems: PropTypes.number,
/**
* Use to pass an array of avatars
*/
items: PropTypes.arrayOf(
PropTypes.shape({
ariaLabel: PropTypes.string,
color: PropTypes.oneOf(['A1', 'A2', 'A3', 'A4', 'A5', 'A6']),
imgProp: PropTypes.object,
name: PropTypes.string,
text: PropTypes.string,
placeholder: PropTypes.node,
title: PropTypes.string,
}),
).isRequired,
};
AvatarGroup.defaultProps = {
type: 'stretched',
size: 'medium',
showDivider: false,
maxItems: 5,
items: [],
};
export default AvatarGroup;