mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-03 04:27:41 +08:00
148 lines
3.8 KiB
JavaScript
148 lines
3.8 KiB
JavaScript
|
||
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(computedType)),
|
||
dangerousTheme || theme || defaultTheme,
|
||
)
|
||
innerNode = (
|
||
<VueIcon
|
||
class={svgClassString}
|
||
type={computedType}
|
||
primaryColor={twoToneColor}
|
||
/>
|
||
)
|
||
}
|
||
// functional component not support nativeOn,https://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
|