-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathavatar.tsx
More file actions
104 lines (94 loc) · 2.91 KB
/
Copy pathavatar.tsx
File metadata and controls
104 lines (94 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import React, { useRef, useEffect, useState, useContext } from 'react';
import classNames from 'classnames';
import { AVATAR_MARK, markComponent } from '../_utils/component-markers';
import { ConfigContext } from '../config-provider/config-context';
import { getPrefixCls } from '../_utils/general';
import { AvatarProps } from './types';
const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>((props, ref) => {
const {
size = 38,
shape = 'circle',
presence = undefined,
alt = 'avatar',
icon,
src,
children,
className,
style,
onClick,
prefixCls: customisedCls,
...otherProps
} = props;
const outerEl = useRef<HTMLSpanElement | null>(null);
const textEl = useRef<HTMLSpanElement | null>(null);
const [scale, setScale] = useState(1);
const configContext = useContext(ConfigContext);
const prefixCls = getPrefixCls('avatar', configContext.prefixCls, customisedCls);
const cls = classNames(prefixCls, className, `${prefixCls}_${shape}`, {
[`${prefixCls}_clickable`]: onClick,
});
const renderChildren = () => {
if (typeof children === 'string') {
let textStyle: React.CSSProperties = {};
if (textEl.current) {
const transformString = `scale(${scale}) translateX(-50%)`;
textStyle = {
msTransform: transformString,
WebkitTransform: transformString,
transform: transformString,
};
}
return (
<span ref={textEl} className={`${prefixCls}__text`} style={textStyle}>
{children}
</span>
);
} else {
return children;
}
};
const renderItem = (): React.ReactNode => {
if (children) {
return renderChildren();
} else if (src) {
return <img src={src} alt={alt} className={`${prefixCls}__img`} />;
} else {
return icon;
}
};
const renderPresence = (): React.ReactElement => {
return <i className={`${prefixCls}__presence ${prefixCls}__presence_${presence}`} />;
};
const styles: React.CSSProperties = {
width: size,
height: size,
fontSize: size / 2,
lineHeight: `${size - 4}px`,
...style,
};
useEffect(() => {
if (outerEl.current && textEl.current && textEl.current!.className === `${prefixCls}__text`) {
const textElWidth = textEl.current!.offsetWidth;
const outerElWidth = outerEl.current!.offsetWidth;
// leave 4px padding for left and right side
if (outerElWidth - 8 < textElWidth) {
setScale((outerElWidth - 8) / textElWidth);
} else {
setScale(1);
}
}
});
return (
<span {...otherProps} ref={(node) => {
outerEl.current = node;
if (typeof ref === 'function') ref(node);
else if (ref) ref.current = node;
}} className={cls} style={styles}>
{renderItem()}
{presence && renderPresence()}
</span>
);
});
Avatar.displayName = 'Avatar';
markComponent(Avatar, AVATAR_MARK);
export default Avatar;