You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
3.1 KiB

import * as React from 'react';
import classNames from 'classnames';
import { antDesignIcons } from '@ant-design/icons';
import ReactIcon from '@ant-design/icons-react';
import create from './IconFont';
6 years ago
import { getComputedSvgStyle, svgBaseProps } from './utils';
import warning from '../_util/warning';
6 years ago
ReactIcon.add(...antDesignIcons);
6 years ago
export interface CustomIconComponentProps {
width: string | number;
height: string | number;
fill: string;
viewBox: string;
className?: string;
style?: React.CSSProperties;
}
export interface IconProps {
6 years ago
type?: string;
className?: string;
title?: string;
6 years ago
onClick?: React.MouseEventHandler<HTMLElement>;
component?: React.ComponentType<CustomIconComponentProps>;
viewBox?: string;
spin?: boolean;
style?: React.CSSProperties;
svgStyle?: React.CSSProperties;
svgClassName?: string;
rotate?: number;
flip?: 'horizontal' | 'vertical' | 'both';
tag?: string;
prefixCls?: string;
}
6 years ago
const Icon: React.SFC<IconProps> = (props) => {
const {
6 years ago
// affect outter <i>...</i>
tag = 'i',
className = '',
6 years ago
onClick,
style,
// affect inner <svg>...</svg>
type,
component,
viewBox = '0 0 1024 1024',
spin,
flip,
svgClassName,
rotate = 0,
svgStyle = {},
6 years ago
// children
children,
} = props;
6 years ago
warning(
Boolean(type || component || children),
'Icon should have `type` prop or `component` prop or `children`.',
);
if (component || children) {
warning(
Boolean(viewBox),
'Make sure that you provide correct `viewBox`' +
' prop (default `0 0 1024 1024`) to Icon.',
);
}
const classString = classNames(
6 years ago
{ [`anticon`]: true, [`anticon-${type}`]: Boolean(type) },
className,
);
const svgClassString = classNames({
svgClassName,
[`anticon-spin`]: !!spin || type === 'loading',
});
6 years ago
const computedSvgStyle = getComputedSvgStyle(
{ rotate, flip },
svgStyle,
);
// component > children > type
if (component) {
const innerSvgProps = {
...svgBaseProps,
viewBox,
className: svgClassString,
style: computedSvgStyle,
};
return React.createElement(
tag,
{ className: classString, style, onClick },
React.createElement(
component,
innerSvgProps,
children,
),
);
}
if (children) {
const innerSvgProps = {
...svgBaseProps,
viewBox,
className: svgClassString,
style: computedSvgStyle,
};
return React.createElement(
tag,
{ className: classString, style, onClick },
React.createElement(
'svg',
innerSvgProps,
children,
),
);
}
if (type) {
return React.createElement(
tag,
{ className: classString, style, onClick },
<ReactIcon
className={svgClassString}
type={type}
style={computedSvgStyle}
/>,
);
}
return React.createElement(
tag,
6 years ago
{ className: classString, style, onClick },
);
8 years ago
};
export type IconType = React.SFC<IconProps> & {
create: typeof create;
};
6 years ago
Icon.displayName = 'Icon';
(Icon as IconType).create = create;
export default Icon as IconType;