refactor: move avatar into design

pull/81/head
moonrailgun 3 years ago
parent a655a0d136
commit 5245c49635

@ -0,0 +1,50 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Avatar } from '.';
export default {
title: 'Tailchat/Avatar',
component: Avatar,
argTypes: {
name: {
description: '显示名称,用于无图片下的展示',
},
isOnline: {
description: '是否在线, 可不传',
},
size: {
description: '图标大小',
type: 'number',
},
src: {
description: '头像图片地址',
type: 'string',
},
},
} as ComponentMeta<typeof Avatar>;
const Template: ComponentStory<typeof Avatar> = (args) => <Avatar {...args} />;
export const normal = Template.bind({});
normal.args = {
name: 'Anonymous',
};
export const withSize = Template.bind({});
withSize.args = {
name: 'Anonymous',
size: 48,
};
export const withOnline = Template.bind({});
withOnline.args = {
name: 'Anonymous',
isOnline: true,
};
export const withImage = Template.bind({});
withImage.args = {
name: 'Anonymous',
src: 'http://dummyimage.com/50x50',
};

@ -0,0 +1,76 @@
import React, { useMemo } from 'react';
import { Avatar as AntdAvatar, Badge } from 'antd';
import _head from 'lodash/head';
import _upperCase from 'lodash/upperCase';
import _isNil from 'lodash/isNil';
import _isEmpty from 'lodash/isEmpty';
import _isNumber from 'lodash/isNumber';
import type { AvatarProps as AntdAvatarProps } from 'antd/lib/avatar';
import { getTextColorHex } from './utils';
import { isValidStr } from '../utils';
interface AvatarProps extends AntdAvatarProps {
name?: string;
isOnline?: boolean;
}
export const Avatar: React.FC<AvatarProps> = React.memo((_props) => {
const { isOnline, ...props } = _props;
const src = isValidStr(props.src) ? props.src : undefined;
const name = useMemo(() => _upperCase(_head(props.name)), [props.name]);
const color = useMemo(
() =>
// 如果src为空 且 icon为空 则给个固定颜色
_isEmpty(src) && _isNil(props.icon)
? getTextColorHex(props.name)
: undefined,
[src, props.icon, props.name]
);
const style: React.CSSProperties = useMemo(
() => ({
cursor: 'inherit',
userSelect: 'none',
...props.style,
backgroundColor: color,
}),
[props.style, color]
);
if (_isNumber(props.size) && typeof style.fontSize === 'undefined') {
// 如果props.size是数字且没有指定文字大小
// 则自动增加fontSize大小
style.fontSize = props.size * 0.4;
}
const inner = (
<AntdAvatar {...props} src={src} style={style}>
{name}
</AntdAvatar>
);
if (typeof isOnline === 'boolean') {
const style = {
bottom: 0,
top: 'auto',
};
if (isOnline === true) {
return (
<Badge dot={true} color="green" style={style}>
{inner}
</Badge>
);
} else {
return (
<Badge dot={true} color="#999" style={style}>
{inner}
</Badge>
);
}
}
return inner;
});
Avatar.displayName = 'Avatar';

@ -0,0 +1,34 @@
import _isString from 'lodash/isString';
import str2int from 'str2int';
const colors = [
'#333333',
'#2c3e50',
'#8e44ad',
'#2980b9',
'#27ae60',
'#16a085',
'#f39c12',
'#d35400',
'#c0392b',
'#3498db',
'#9b59b6',
'#2ecc71',
'#1abc9c',
'#f1c40f',
'#e74c3c',
'#e67e22',
];
/**
*
* @param text
*/
export function getTextColorHex(text: unknown): string {
if (!text || !_isString(text)) {
return '#ffffff'; // 如果获取不到文本,则返回白色
}
const id = str2int(text);
return colors[id % colors.length];
}

@ -1,3 +1,4 @@
export { Avatar } from './Avatar';
export { DelayTip } from './DelayTip';
export { Highlight } from './Highlight';
export { Icon } from './Icon';

@ -0,0 +1,7 @@
/**
*
*
*/
export function isValidStr(str: unknown): str is string {
return typeof str == 'string' && str !== '';
}

@ -25,7 +25,8 @@
"@iconify/react": "^3.2.1",
"antd": "^4.19.5",
"lodash": "^4.17.21",
"meta-form": "^1.0.0"
"meta-form": "^1.0.0",
"str2int": "^1.1.0"
},
"devDependencies": {
"@babel/core": "^7.17.9",

File diff suppressed because it is too large Load Diff

@ -1,24 +0,0 @@
/**
* Tailchat
*/
export const config = {
color: [
'#333333',
'#2c3e50',
'#8e44ad',
'#2980b9',
'#27ae60',
'#16a085',
'#f39c12',
'#d35400',
'#c0392b',
'#3498db',
'#9b59b6',
'#2ecc71',
'#1abc9c',
'#f1c40f',
'#e74c3c',
'#e67e22',
],
};

@ -185,7 +185,7 @@ export {
isDevelopment,
version,
} from './utils/environment';
export { getTextColorHex, isValidStr } from './utils/string-helper';
export { isValidStr } from './utils/string-helper';
export { isValidJson } from './utils/json-helper';
export { MessageHelper } from './utils/message-helper';
export { uploadFile } from './utils/upload-helper';

@ -24,7 +24,6 @@
"react-redux": "^7.2.6",
"regenerator-runtime": "^0.13.9",
"socket.io-client": "^4.1.2",
"str2int": "^1.0.0",
"url-regex": "^5.0.0",
"yup": "^0.32.9"
},

@ -1,7 +1,5 @@
import _isString from 'lodash/isString';
import str2int from 'str2int';
import urlRegex from 'url-regex';
import { config } from '../config';
/**
* ()
@ -42,20 +40,6 @@ export function is(it: string) {
return !!it && it !== '0' && it !== 'false';
}
/**
*
* @param text
*/
export function getTextColorHex(text: unknown): string {
if (!text || !_isString(text)) {
return '#ffffff'; // 如果获取不到文本,则返回白色
}
const color = config.color;
const id = str2int(text);
return color[id % color.length];
}
/**
*
*

@ -54,7 +54,6 @@
"react-virtualized-auto-sizer": "^1.0.6",
"react-virtuoso": "^2.8.3",
"socket.io-client": "^4.1.2",
"str2int": "^1.1.0",
"tailchat-design": "workspace:^1.0.0",
"tailchat-shared": "*",
"tailwindcss": "^2.2.4",

@ -1,75 +1 @@
import React, { useMemo } from 'react';
import { Avatar as AntdAvatar, Badge } from 'antd';
import _head from 'lodash/head';
import _upperCase from 'lodash/upperCase';
import _isNil from 'lodash/isNil';
import _isEmpty from 'lodash/isEmpty';
import _isNumber from 'lodash/isNumber';
import type { AvatarProps as AntdAvatarProps } from 'antd/lib/avatar';
import { getTextColorHex, isValidStr } from 'tailchat-shared';
interface AvatarProps extends AntdAvatarProps {
name?: string;
isOnline?: boolean;
}
export const Avatar: React.FC<AvatarProps> = React.memo((_props) => {
const { isOnline, ...props } = _props;
const src = isValidStr(props.src) ? props.src : undefined;
const name = useMemo(() => _upperCase(_head(props.name)), [props.name]);
const color = useMemo(
() =>
// 如果src为空 且 icon为空 则给个固定颜色
_isEmpty(src) && _isNil(props.icon)
? getTextColorHex(props.name)
: undefined,
[src, props.icon, props.name]
);
const style: React.CSSProperties = useMemo(
() => ({
cursor: 'inherit',
userSelect: 'none',
...props.style,
backgroundColor: color,
}),
[props.style, color]
);
if (_isNumber(props.size) && typeof style.fontSize === 'undefined') {
// 如果props.size是数字且没有指定文字大小
// 则自动增加fontSize大小
style.fontSize = props.size * 0.4;
}
const inner = (
<AntdAvatar {...props} src={src} style={style}>
{name}
</AntdAvatar>
);
if (typeof isOnline === 'boolean') {
const style = {
bottom: 0,
top: 'auto',
};
if (isOnline === true) {
return (
<Badge dot={true} color="green" style={style}>
{inner}
</Badge>
);
} else {
return (
<Badge dot={true} color="#999" style={style}>
{inner}
</Badge>
);
}
}
return inner;
});
Avatar.displayName = 'Avatar';
export { Avatar } from 'tailchat-design';

Loading…
Cancel
Save