import * as React from 'react'; import classNames from 'classnames'; import { Omit } from '../_util/type'; import { IconProps } from './index'; import { getComputedSvgStyle } from './utils'; export interface CustomIconProps extends Omit { type?: string | SpriteSvgIcon; viewBox?: string; component?: React.ComponentType; } export interface CustomIconComponentProps { width: string | number; height: string | number; fill: string; viewBox: string; className?: string; style?: React.CSSProperties; } export interface SpriteSvgIcon { id: string; viewBox?: string; [key: string]: any; } // These props make sure that the SVG behaviours like general text. // Reference: https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4 export const svgBaseProps = { width: '1em', height: '1em', fill: 'currentColor', ['aria-hidden']: 'true', }; const CustomIcon: React.SFC = (props) => { const { type: spriteSvgIcon, className = '', spin, // ⬇️ Todo, what's the best default value? // ⬇️ "0 0 24 24" for material-ui or "0 0 1024 1024" for ant-design viewBox = '0 0 1024 1024', children, svgClassName, rotate, flip, style, svgStyle = {}, tag = 'i', onClick, component: Component, } = props; const classString = classNames({ anticon: true, 'anticon-spin': !!spin, }, className); const innerSvgProps = { ...svgBaseProps, viewBox, className: svgClassName, style: getComputedSvgStyle({ rotate, flip }, svgStyle), }; let content = ( {children} ); if (spriteSvgIcon) { if (isSVGSpriteObject(spriteSvgIcon)) { content = ( ); } else { // typeof spriteSvgIcon === 'string' content = ( ); } } if (Component) { content = ( {children} ); } return React.createElement( tag, { className: classString, style, onClick, }, content, ); }; function isSVGSpriteObject(obj: any): obj is SpriteSvgIcon { return typeof obj.id === 'string'; } export default CustomIcon;