ant-design-vue/components/icon/index.js

148 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import classNames from 'classnames'
import * as allIcons from '@ant-design/icons/lib/dist'
import VueIcon from '@ant-design/icons-vue'
import PropTypes from '../_util/vue-types'
import createFromIconfontCN from './IconFont'
import {
svgBaseProps, withThemeSuffix,
removeTypeTheme, getThemeFromTypeName,
alias,
} from './utils'
import warning from '../_util/warning'
import { getTwoToneColor, setTwoToneColor } from './twoTonePrimaryColor'
import { filterEmpty, getClass } from '../_util/props-util'
// Initial setting
VueIcon.add(...Object.keys(allIcons).map((key) => allIcons[key]))
setTwoToneColor('#1890ff')
const defaultTheme = 'outlined'
let dangerousTheme
const Icon = {
functional: true,
name: 'AIcon',
props: {
type: PropTypes.string,
component: PropTypes.any,
viewBox: PropTypes.any,
spin: PropTypes.bool.def(false),
theme: PropTypes.oneOf(['filled', 'outlined', 'twoTone']),
twoToneColor: PropTypes.string,
},
render (h, context) {
const { props, slots, listeners, data } = context
const {
// affect inner <svg>...</svg>
type,
component: Component,
viewBox,
spin,
// other
theme, // default to outlined
twoToneColor,
} = props
const slotsMap = slots()
let children = filterEmpty(slotsMap.default)
children = children.length === 0 ? undefined : children
warning(
Boolean(type || Component || children),
'Icon should have `type` prop or `component` prop or `children`.',
)
const classString = classNames({
...getClass(context),
[`anticon`]: true,
[`anticon-${type}`]: !!type,
})
const svgClassString = classNames({
[`anticon-spin`]: !!spin || type === 'loading',
})
let innerNode
// component > children > type
if (Component) {
const innerSvgProps = {
attrs: {
...svgBaseProps,
viewBox,
},
class: svgClassString,
}
if (!viewBox) {
delete innerSvgProps.attrs.viewBox
}
innerNode = (
<Component {...innerSvgProps} >
{children}
</Component>
)
}
if (children) {
warning(
Boolean(viewBox) || (
children.length === 1 &&
children[0].tag === 'use'
),
'Make sure that you provide correct `viewBox`' +
' prop (default `0 0 1024 1024`) to the icon.',
)
const innerSvgProps = {
attrs: {
...svgBaseProps,
},
class: svgClassString,
}
innerNode = (
<svg {...innerSvgProps} viewBox={viewBox}>
{children}
</svg>
)
}
if (typeof type === 'string') {
let computedType = type
if (theme) {
const themeInName = getThemeFromTypeName(type)
warning(!themeInName || theme === themeInName,
`The icon name '${type}' already specify a theme '${themeInName}',` +
` the 'theme' prop '${theme}' will be ignored.`)
}
computedType = withThemeSuffix(
removeTypeTheme(alias(type)),
dangerousTheme || theme || defaultTheme,
)
innerNode = (
<VueIcon
class={svgClassString}
type={computedType}
primaryColor={twoToneColor}
/>
)
}
// functional component not support nativeOnhttps://github.com/vuejs/vue/issues/7526
const iProps = {
...data, on: { ...listeners, ...data.nativeOn }, class: classString, staticClass: '',
}
return (
<i {...iProps}>
{innerNode}
</i>
)
},
}
Icon.createFromIconfontCN = createFromIconfontCN
Icon.getTwoToneColor = getTwoToneColor
Icon.setTwoToneColor = setTwoToneColor
/* istanbul ignore next */
Icon.install = function (Vue) {
Vue.component(Icon.name, Icon)
}
export default Icon