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.
103 lines
2.5 KiB
103 lines
2.5 KiB
6 years ago
|
import * as React from 'react';
|
||
|
import classNames from 'classnames';
|
||
|
import omit from 'omit.js';
|
||
6 years ago
|
import { Omit } from '../_util/type';
|
||
|
import { IconProps } from './index';
|
||
6 years ago
|
|
||
|
export interface CustomIconProps extends Omit<IconProps, 'type'> {
|
||
|
src?: string;
|
||
|
}
|
||
|
|
||
|
const CustomIcon: React.SFC<CustomIconProps> = (props) => {
|
||
|
const { className = '', spin, src, children } = props;
|
||
|
const classString = classNames({
|
||
|
anticon: true,
|
||
|
'anticon-spin': !!spin,
|
||
|
}, className);
|
||
|
|
||
|
if (typeof src === 'string' && src.length) {
|
||
|
return (
|
||
|
<object
|
||
|
{...omit(props, ['spin'])}
|
||
|
className={classString}
|
||
|
width={'1em'}
|
||
|
height={'1em'}
|
||
|
fill={'currentColor'}
|
||
|
type={'image/svg+xml'}
|
||
|
aria-hidden={'true'}
|
||
|
data={src}
|
||
|
/>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<svg
|
||
|
{...omit(props, ['spin'])}
|
||
|
className={classString}
|
||
|
width={'1em'}
|
||
|
height={'1em'}
|
||
|
fill={'currentColor'}
|
||
|
aria-hidden={'true'}
|
||
|
>
|
||
|
{children}
|
||
|
</svg>
|
||
|
);
|
||
|
};
|
||
|
|
||
6 years ago
|
const customCache = new Set<string>();
|
||
|
|
||
|
export interface CustomIconOptions {
|
||
|
namespace?: string;
|
||
|
prefix?: string;
|
||
|
scriptLink?: string;
|
||
|
}
|
||
|
|
||
6 years ago
|
export function create(options: CustomIconOptions = {}): React.ComponentClass<IconProps> {
|
||
6 years ago
|
const { namespace, prefix = '', scriptLink } = options;
|
||
|
|
||
|
class Custom extends React.Component<IconProps> {
|
||
|
render() {
|
||
|
const { type, className = '', spin } = this.props;
|
||
|
const classString = classNames({
|
||
|
anticon: true,
|
||
|
'anticon-spin': !!spin || type === 'loading',
|
||
|
}, className);
|
||
|
return (
|
||
|
<svg
|
||
|
{...omit(this.props, ['type', 'spin'])}
|
||
|
className={classString}
|
||
|
width={'1em'}
|
||
|
height={'1em'}
|
||
|
fill={'currentColor'}
|
||
|
aria-hidden={'true'}
|
||
|
>
|
||
|
<use xlinkHref={`#${prefix}${type}`} />
|
||
|
</svg>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
componentDidMount() {
|
||
|
/**
|
||
6 years ago
|
* DOM API required.
|
||
6 years ago
|
* The Custom Icon will create a <script/>
|
||
|
* that loads SVG symbols and insert the SVG Element into the document body.
|
||
|
*/
|
||
|
if (document && window
|
||
|
&& typeof scriptLink === 'string' && scriptLink.length
|
||
|
&& typeof namespace === 'string' && namespace.length
|
||
|
&& !customCache.has(namespace)
|
||
|
) {
|
||
|
const script = document.createElement('script');
|
||
|
script.setAttribute('src', scriptLink);
|
||
|
script.setAttribute('data-namespace', namespace);
|
||
|
customCache.add(namespace);
|
||
|
document.body.appendChild(script);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Custom;
|
||
|
}
|
||
|
|
||
6 years ago
|
export default CustomIcon;
|