UNPKG

6.27 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/esm/extends";
3const _excluded = ["children", "className", "componentsProps", "max", "spacing", "total", "variant"];
4import * as React from 'react';
5import PropTypes from 'prop-types';
6import { isFragment } from 'react-is';
7import clsx from 'clsx';
8import { chainPropTypes } from '@mui/utils';
9import { unstable_composeClasses as composeClasses } from '@mui/base';
10import styled from '../styles/styled';
11import useThemeProps from '../styles/useThemeProps';
12import Avatar, { avatarClasses } from '../Avatar';
13import avatarGroupClasses, { getAvatarGroupUtilityClass } from './avatarGroupClasses';
14import { jsxs as _jsxs } from "react/jsx-runtime";
15const SPACINGS = {
16 small: -16,
17 medium: null
18};
19
20const useUtilityClasses = ownerState => {
21 const {
22 classes
23 } = ownerState;
24 const slots = {
25 root: ['root'],
26 avatar: ['avatar']
27 };
28 return composeClasses(slots, getAvatarGroupUtilityClass, classes);
29};
30
31const AvatarGroupRoot = styled('div', {
32 name: 'MuiAvatarGroup',
33 slot: 'Root',
34 overridesResolver: (props, styles) => _extends({
35 [`& .${avatarGroupClasses.avatar}`]: styles.avatar
36 }, styles.root)
37})(({
38 theme
39}) => ({
40 [`& .${avatarClasses.root}`]: {
41 border: `2px solid ${(theme.vars || theme).palette.background.default}`,
42 boxSizing: 'content-box',
43 marginLeft: -8,
44 '&:last-child': {
45 marginLeft: 0
46 }
47 },
48 display: 'flex',
49 flexDirection: 'row-reverse'
50}));
51const AvatarGroupAvatar = styled(Avatar, {
52 name: 'MuiAvatarGroup',
53 slot: 'Avatar',
54 overridesResolver: (props, styles) => styles.avatar
55})(({
56 theme
57}) => ({
58 border: `2px solid ${(theme.vars || theme).palette.background.default}`,
59 boxSizing: 'content-box',
60 marginLeft: -8,
61 '&:last-child': {
62 marginLeft: 0
63 }
64}));
65const AvatarGroup = /*#__PURE__*/React.forwardRef(function AvatarGroup(inProps, ref) {
66 const props = useThemeProps({
67 props: inProps,
68 name: 'MuiAvatarGroup'
69 });
70
71 const {
72 children: childrenProp,
73 className,
74 componentsProps = {},
75 max = 5,
76 spacing = 'medium',
77 total,
78 variant = 'circular'
79 } = props,
80 other = _objectWithoutPropertiesLoose(props, _excluded);
81
82 let clampedMax = max < 2 ? 2 : max;
83
84 const ownerState = _extends({}, props, {
85 max,
86 spacing,
87 variant
88 });
89
90 const classes = useUtilityClasses(ownerState);
91 const children = React.Children.toArray(childrenProp).filter(child => {
92 if (process.env.NODE_ENV !== 'production') {
93 if (isFragment(child)) {
94 console.error(["MUI: The AvatarGroup component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
95 }
96 }
97
98 return /*#__PURE__*/React.isValidElement(child);
99 });
100 const totalAvatars = total || children.length;
101
102 if (totalAvatars === clampedMax) {
103 clampedMax += 1;
104 }
105
106 clampedMax = Math.min(totalAvatars + 1, clampedMax);
107 const maxAvatars = Math.min(children.length, clampedMax - 1);
108 const extraAvatars = Math.max(totalAvatars - clampedMax, totalAvatars - maxAvatars, 0);
109 const marginLeft = spacing && SPACINGS[spacing] !== undefined ? SPACINGS[spacing] : -spacing;
110 return /*#__PURE__*/_jsxs(AvatarGroupRoot, _extends({
111 ownerState: ownerState,
112 className: clsx(classes.root, className),
113 ref: ref
114 }, other, {
115 children: [extraAvatars ? /*#__PURE__*/_jsxs(AvatarGroupAvatar, _extends({
116 ownerState: ownerState,
117 variant: variant
118 }, componentsProps.additionalAvatar, {
119 className: clsx(classes.avatar, componentsProps.additionalAvatar?.className),
120 style: _extends({
121 marginLeft
122 }, componentsProps.additionalAvatar?.style),
123 children: ["+", extraAvatars]
124 })) : null, children.slice(0, maxAvatars).reverse().map((child, index) => {
125 return /*#__PURE__*/React.cloneElement(child, {
126 className: clsx(child.props.className, classes.avatar),
127 style: _extends({
128 // Consistent with "&:last-child" styling for the default spacing,
129 // we do not apply custom marginLeft spacing on the last child
130 marginLeft: index === maxAvatars - 1 ? undefined : marginLeft
131 }, child.props.style),
132 variant: child.props.variant || variant
133 });
134 })]
135 }));
136});
137process.env.NODE_ENV !== "production" ? AvatarGroup.propTypes
138/* remove-proptypes */
139= {
140 // ----------------------------- Warning --------------------------------
141 // | These PropTypes are generated from the TypeScript type definitions |
142 // | To update them edit the d.ts file and run "yarn proptypes" |
143 // ----------------------------------------------------------------------
144
145 /**
146 * The avatars to stack.
147 */
148 children: PropTypes.node,
149
150 /**
151 * Override or extend the styles applied to the component.
152 */
153 classes: PropTypes.object,
154
155 /**
156 * @ignore
157 */
158 className: PropTypes.string,
159
160 /**
161 * The props used for each slot inside the AvatarGroup.
162 * @default {}
163 */
164 componentsProps: PropTypes.shape({
165 additionalAvatar: PropTypes.object
166 }),
167
168 /**
169 * Max avatars to show before +x.
170 * @default 5
171 */
172 max: chainPropTypes(PropTypes.number, props => {
173 if (props.max < 2) {
174 return new Error(['MUI: The prop `max` should be equal to 2 or above.', 'A value below is clamped to 2.'].join('\n'));
175 }
176
177 return null;
178 }),
179
180 /**
181 * Spacing between avatars.
182 * @default 'medium'
183 */
184 spacing: PropTypes.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.number]),
185
186 /**
187 * The system prop that allows defining system overrides as well as additional CSS styles.
188 */
189 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
190
191 /**
192 * The total number of avatars. Used for calculating the number of extra avatars.
193 * @default children.length
194 */
195 total: PropTypes.number,
196
197 /**
198 * The variant to use.
199 * @default 'circular'
200 */
201 variant: PropTypes
202 /* @typescript-to-proptypes-ignore */
203 .oneOfType([PropTypes.oneOf(['circular', 'rounded', 'square']), PropTypes.string])
204} : void 0;
205export default AvatarGroup;
\No newline at end of file