UNPKG

9.48 kBJavaScriptView Raw
1'use client';
2
3import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
5import _extends from "@babel/runtime/helpers/esm/extends";
6import * as React from 'react';
7import PropTypes from 'prop-types';
8import clsx from 'clsx';
9import composeClasses from '@mui/utils/composeClasses';
10import { styled } from '../zero-styled';
11import { useDefaultProps } from '../DefaultPropsProvider';
12import Person from '../internal/svg-icons/Person';
13import { getAvatarUtilityClass } from './avatarClasses';
14import useSlot from '../utils/useSlot';
15import { jsx as _jsx } from "react/jsx-runtime";
16var useUtilityClasses = function useUtilityClasses(ownerState) {
17 var classes = ownerState.classes,
18 variant = ownerState.variant,
19 colorDefault = ownerState.colorDefault;
20 var slots = {
21 root: ['root', variant, colorDefault && 'colorDefault'],
22 img: ['img'],
23 fallback: ['fallback']
24 };
25 return composeClasses(slots, getAvatarUtilityClass, classes);
26};
27var AvatarRoot = styled('div', {
28 name: 'MuiAvatar',
29 slot: 'Root',
30 overridesResolver: function overridesResolver(props, styles) {
31 var ownerState = props.ownerState;
32 return [styles.root, styles[ownerState.variant], ownerState.colorDefault && styles.colorDefault];
33 }
34})(function (_ref) {
35 var theme = _ref.theme;
36 return {
37 position: 'relative',
38 display: 'flex',
39 alignItems: 'center',
40 justifyContent: 'center',
41 flexShrink: 0,
42 width: 40,
43 height: 40,
44 fontFamily: theme.typography.fontFamily,
45 fontSize: theme.typography.pxToRem(20),
46 lineHeight: 1,
47 borderRadius: '50%',
48 overflow: 'hidden',
49 userSelect: 'none',
50 variants: [{
51 props: {
52 variant: 'rounded'
53 },
54 style: {
55 borderRadius: (theme.vars || theme).shape.borderRadius
56 }
57 }, {
58 props: {
59 variant: 'square'
60 },
61 style: {
62 borderRadius: 0
63 }
64 }, {
65 props: {
66 colorDefault: true
67 },
68 style: _extends({
69 color: (theme.vars || theme).palette.background.default
70 }, theme.vars ? {
71 backgroundColor: theme.vars.palette.Avatar.defaultBg
72 } : _extends({
73 backgroundColor: theme.palette.grey[400]
74 }, theme.applyStyles('dark', {
75 backgroundColor: theme.palette.grey[600]
76 })))
77 }]
78 };
79});
80var AvatarImg = styled('img', {
81 name: 'MuiAvatar',
82 slot: 'Img',
83 overridesResolver: function overridesResolver(props, styles) {
84 return styles.img;
85 }
86})({
87 width: '100%',
88 height: '100%',
89 textAlign: 'center',
90 // Handle non-square image. The property isn't supported by IE11.
91 objectFit: 'cover',
92 // Hide alt text.
93 color: 'transparent',
94 // Hide the image broken icon, only works on Chrome.
95 textIndent: 10000
96});
97var AvatarFallback = styled(Person, {
98 name: 'MuiAvatar',
99 slot: 'Fallback',
100 overridesResolver: function overridesResolver(props, styles) {
101 return styles.fallback;
102 }
103})({
104 width: '75%',
105 height: '75%'
106});
107function useLoaded(_ref2) {
108 var crossOrigin = _ref2.crossOrigin,
109 referrerPolicy = _ref2.referrerPolicy,
110 src = _ref2.src,
111 srcSet = _ref2.srcSet;
112 var _React$useState = React.useState(false),
113 loaded = _React$useState[0],
114 setLoaded = _React$useState[1];
115 React.useEffect(function () {
116 if (!src && !srcSet) {
117 return undefined;
118 }
119 setLoaded(false);
120 var active = true;
121 var image = new Image();
122 image.onload = function () {
123 if (!active) {
124 return;
125 }
126 setLoaded('loaded');
127 };
128 image.onerror = function () {
129 if (!active) {
130 return;
131 }
132 setLoaded('error');
133 };
134 image.crossOrigin = crossOrigin;
135 image.referrerPolicy = referrerPolicy;
136 image.src = src;
137 if (srcSet) {
138 image.srcset = srcSet;
139 }
140 return function () {
141 active = false;
142 };
143 }, [crossOrigin, referrerPolicy, src, srcSet]);
144 return loaded;
145}
146var Avatar = /*#__PURE__*/React.forwardRef(function Avatar(inProps, ref) {
147 var props = useDefaultProps({
148 props: inProps,
149 name: 'MuiAvatar'
150 });
151 var alt = props.alt,
152 childrenProp = props.children,
153 className = props.className,
154 _props$component = props.component,
155 component = _props$component === void 0 ? 'div' : _props$component,
156 _props$slots = props.slots,
157 slots = _props$slots === void 0 ? {} : _props$slots,
158 _props$slotProps = props.slotProps,
159 slotProps = _props$slotProps === void 0 ? {} : _props$slotProps,
160 imgProps = props.imgProps,
161 sizes = props.sizes,
162 src = props.src,
163 srcSet = props.srcSet,
164 _props$variant = props.variant,
165 variant = _props$variant === void 0 ? 'circular' : _props$variant,
166 other = _objectWithoutProperties(props, ["alt", "children", "className", "component", "slots", "slotProps", "imgProps", "sizes", "src", "srcSet", "variant"]);
167 var children = null;
168
169 // Use a hook instead of onError on the img element to support server-side rendering.
170 var loaded = useLoaded(_extends({}, imgProps, {
171 src: src,
172 srcSet: srcSet
173 }));
174 var hasImg = src || srcSet;
175 var hasImgNotFailing = hasImg && loaded !== 'error';
176 var ownerState = _extends({}, props, {
177 colorDefault: !hasImgNotFailing,
178 component: component,
179 variant: variant
180 });
181 var classes = useUtilityClasses(ownerState);
182 var _useSlot = useSlot('img', {
183 className: classes.img,
184 elementType: AvatarImg,
185 externalForwardedProps: {
186 slots: slots,
187 slotProps: {
188 img: _extends({}, imgProps, slotProps.img)
189 }
190 },
191 additionalProps: {
192 alt: alt,
193 src: src,
194 srcSet: srcSet,
195 sizes: sizes
196 },
197 ownerState: ownerState
198 }),
199 _useSlot2 = _slicedToArray(_useSlot, 2),
200 ImgSlot = _useSlot2[0],
201 imgSlotProps = _useSlot2[1];
202 if (hasImgNotFailing) {
203 children = /*#__PURE__*/_jsx(ImgSlot, _extends({}, imgSlotProps));
204 // We only render valid children, non valid children are rendered with a fallback
205 // We consider that invalid children are all falsy values, except 0, which is valid.
206 } else if (!!childrenProp || childrenProp === 0) {
207 children = childrenProp;
208 } else if (hasImg && alt) {
209 children = alt[0];
210 } else {
211 children = /*#__PURE__*/_jsx(AvatarFallback, {
212 ownerState: ownerState,
213 className: classes.fallback
214 });
215 }
216 return /*#__PURE__*/_jsx(AvatarRoot, _extends({
217 as: component,
218 ownerState: ownerState,
219 className: clsx(classes.root, className),
220 ref: ref
221 }, other, {
222 children: children
223 }));
224});
225process.env.NODE_ENV !== "production" ? Avatar.propTypes /* remove-proptypes */ = {
226 // ┌────────────────────────────── Warning ──────────────────────────────┐
227 // │ These PropTypes are generated from the TypeScript type definitions. │
228 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
229 // └─────────────────────────────────────────────────────────────────────┘
230 /**
231 * Used in combination with `src` or `srcSet` to
232 * provide an alt attribute for the rendered `img` element.
233 */
234 alt: PropTypes.string,
235 /**
236 * Used to render icon or text elements inside the Avatar if `src` is not set.
237 * This can be an element, or just a string.
238 */
239 children: PropTypes.node,
240 /**
241 * Override or extend the styles applied to the component.
242 */
243 classes: PropTypes.object,
244 /**
245 * @ignore
246 */
247 className: PropTypes.string,
248 /**
249 * The component used for the root node.
250 * Either a string to use a HTML element or a component.
251 */
252 component: PropTypes.elementType,
253 /**
254 * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) applied to the `img` element if the component is used to display an image.
255 * It can be used to listen for the loading error event.
256 * @deprecated Use `slotProps.img` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/).
257 */
258 imgProps: PropTypes.object,
259 /**
260 * The `sizes` attribute for the `img` element.
261 */
262 sizes: PropTypes.string,
263 /**
264 * The props used for each slot inside.
265 * @default {}
266 */
267 slotProps: PropTypes.shape({
268 img: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
269 }),
270 /**
271 * The components used for each slot inside.
272 * @default {}
273 */
274 slots: PropTypes.shape({
275 img: PropTypes.elementType
276 }),
277 /**
278 * The `src` attribute for the `img` element.
279 */
280 src: PropTypes.string,
281 /**
282 * The `srcSet` attribute for the `img` element.
283 * Use this attribute for responsive image display.
284 */
285 srcSet: PropTypes.string,
286 /**
287 * The system prop that allows defining system overrides as well as additional CSS styles.
288 */
289 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
290 /**
291 * The shape of the avatar.
292 * @default 'circular'
293 */
294 variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['circular', 'rounded', 'square']), PropTypes.string])
295} : void 0;
296export default Avatar;
\No newline at end of file