1 | 'use client';
|
2 |
|
3 | import * as React from 'react';
|
4 | import PropTypes from 'prop-types';
|
5 | import { isFragment } from 'react-is';
|
6 | import clsx from 'clsx';
|
7 | import chainPropTypes from '@mui/utils/chainPropTypes';
|
8 | import composeClasses from '@mui/utils/composeClasses';
|
9 | import { styled } from "../zero-styled/index.js";
|
10 | import memoTheme from "../utils/memoTheme.js";
|
11 | import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
12 | import Avatar, { avatarClasses } from "../Avatar/index.js";
|
13 | import avatarGroupClasses, { getAvatarGroupUtilityClass } from "./avatarGroupClasses.js";
|
14 | import useSlot from "../utils/useSlot.js";
|
15 | import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
16 | const SPACINGS = {
|
17 | small: -16,
|
18 | medium: -8
|
19 | };
|
20 | const 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 | const AvatarGroupRoot = styled('div', {
|
31 | name: 'MuiAvatarGroup',
|
32 | slot: 'Root',
|
33 | overridesResolver: (props, styles) => ({
|
34 | [`& .${avatarGroupClasses.avatar}`]: styles.avatar,
|
35 | ...styles.root
|
36 | })
|
37 | })(memoTheme(({
|
38 | theme
|
39 | }) => ({
|
40 | display: 'flex',
|
41 | flexDirection: 'row-reverse',
|
42 | [`& .${avatarClasses.root}`]: {
|
43 | border: `2px solid ${(theme.vars || theme).palette.background.default}`,
|
44 | boxSizing: 'content-box',
|
45 | marginLeft: 'var(--AvatarGroup-spacing, -8px)',
|
46 | '&:last-child': {
|
47 | marginLeft: 0
|
48 | }
|
49 | }
|
50 | })));
|
51 | const AvatarGroup = React.forwardRef(function AvatarGroup(inProps, ref) {
|
52 | const props = useDefaultProps({
|
53 | props: inProps,
|
54 | name: 'MuiAvatarGroup'
|
55 | });
|
56 | const {
|
57 | children: childrenProp,
|
58 | className,
|
59 | component = 'div',
|
60 | componentsProps,
|
61 | max = 5,
|
62 | renderSurplus,
|
63 | slotProps = {},
|
64 | slots = {},
|
65 | spacing = 'medium',
|
66 | total,
|
67 | variant = 'circular',
|
68 | ...other
|
69 | } = props;
|
70 | let clampedMax = max < 2 ? 2 : max;
|
71 | const ownerState = {
|
72 | ...props,
|
73 | max,
|
74 | spacing,
|
75 | component,
|
76 | variant
|
77 | };
|
78 | const classes = useUtilityClasses(ownerState);
|
79 | const children = React.Children.toArray(childrenProp).filter(child => {
|
80 | if (process.env.NODE_ENV !== 'production') {
|
81 | if (isFragment(child)) {
|
82 | console.error(["MUI: The AvatarGroup component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
|
83 | }
|
84 | }
|
85 | return React.isValidElement(child);
|
86 | });
|
87 | const totalAvatars = total || children.length;
|
88 | if (totalAvatars === clampedMax) {
|
89 | clampedMax += 1;
|
90 | }
|
91 | clampedMax = Math.min(totalAvatars + 1, clampedMax);
|
92 | const maxAvatars = Math.min(children.length, clampedMax - 1);
|
93 | const extraAvatars = Math.max(totalAvatars - clampedMax, totalAvatars - maxAvatars, 0);
|
94 | const extraAvatarsElement = renderSurplus ? renderSurplus(extraAvatars) : `+${extraAvatars}`;
|
95 | const marginValue = ownerState.spacing && SPACINGS[ownerState.spacing] !== undefined ? SPACINGS[ownerState.spacing] : -ownerState.spacing || -8;
|
96 | const externalForwardedProps = {
|
97 | slots,
|
98 | slotProps: {
|
99 | surplus: slotProps.additionalAvatar ?? componentsProps?.additionalAvatar,
|
100 | ...componentsProps,
|
101 | ...slotProps
|
102 | }
|
103 | };
|
104 | const [SurplusSlot, surplusProps] = useSlot('surplus', {
|
105 | elementType: Avatar,
|
106 | externalForwardedProps,
|
107 | className: classes.avatar,
|
108 | ownerState,
|
109 | additionalProps: {
|
110 | variant
|
111 | }
|
112 | });
|
113 | return _jsxs(AvatarGroupRoot, {
|
114 | as: component,
|
115 | ownerState: ownerState,
|
116 | className: clsx(classes.root, className),
|
117 | ref: ref,
|
118 | ...other,
|
119 | style: {
|
120 | '--AvatarGroup-spacing': marginValue ? `${marginValue}px` : undefined,
|
121 | ...other.style
|
122 | },
|
123 | children: [extraAvatars ? _jsx(SurplusSlot, {
|
124 | ...surplusProps,
|
125 | children: extraAvatarsElement
|
126 | }) : null, children.slice(0, maxAvatars).reverse().map(child => {
|
127 | return React.cloneElement(child, {
|
128 | className: clsx(child.props.className, classes.avatar),
|
129 | variant: child.props.variant || variant
|
130 | });
|
131 | })]
|
132 | });
|
133 | });
|
134 | process.env.NODE_ENV !== "production" ? AvatarGroup.propTypes = {
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | |
140 |
|
141 |
|
142 | children: PropTypes.node,
|
143 | |
144 |
|
145 |
|
146 | classes: PropTypes.object,
|
147 | |
148 |
|
149 |
|
150 | className: PropTypes.string,
|
151 | |
152 |
|
153 |
|
154 |
|
155 | component: PropTypes.elementType,
|
156 | |
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | componentsProps: PropTypes.shape({
|
165 | additionalAvatar: PropTypes.object
|
166 | }),
|
167 | |
168 |
|
169 |
|
170 |
|
171 | max: chainPropTypes(PropTypes.number, props => {
|
172 | if (props.max < 2) {
|
173 | return new Error(['MUI: The prop `max` should be equal to 2 or above.', 'A value below is clamped to 2.'].join('\n'));
|
174 | }
|
175 | return null;
|
176 | }),
|
177 | |
178 |
|
179 |
|
180 |
|
181 |
|
182 | renderSurplus: PropTypes.func,
|
183 | |
184 |
|
185 |
|
186 |
|
187 | slotProps: PropTypes.shape({
|
188 | additionalAvatar: PropTypes.object,
|
189 | surplus: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
|
190 | }),
|
191 | |
192 |
|
193 |
|
194 |
|
195 | slots: PropTypes.shape({
|
196 | surplus: PropTypes.elementType
|
197 | }),
|
198 | |
199 |
|
200 |
|
201 |
|
202 | spacing: PropTypes.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.number]),
|
203 | |
204 |
|
205 |
|
206 | style: PropTypes.object,
|
207 | |
208 |
|
209 |
|
210 | sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
211 | |
212 |
|
213 |
|
214 |
|
215 | total: PropTypes.number,
|
216 | |
217 |
|
218 |
|
219 |
|
220 | variant: PropTypes .oneOfType([PropTypes.oneOf(['circular', 'rounded', 'square']), PropTypes.string])
|
221 | } : void 0;
|
222 | export default AvatarGroup; |
\ | No newline at end of file |