diff --git a/components/icon/demo/basic.md b/components/icon/demo/basic.md index 63c7e76c0..180f40e1b 100644 --- a/components/icon/demo/basic.md +++ b/components/icon/demo/basic.md @@ -15,6 +15,7 @@ Use tag `` to create an icon and set its type in the `type` prop. Specif + diff --git a/components/icon/index.en-US.md b/components/icon/index.en-US.md index 057dea421..6c95b708e 100644 --- a/components/icon/index.en-US.md +++ b/components/icon/index.en-US.md @@ -6,6 +6,7 @@ | style | Style properties of icon, like `fontSize` and `color` | CSSProperties | - | | theme | Theme of the ant design icon | 'filled' \| 'outlined' \| 'twoTone' | 'outlined' | | spin | Rotate icon with animation | boolean | false | +| rotate | Rotate degrees (added in 1.40.0, not working in IE9) | number | - | | component | The component used for the root node. This will override the **`type`** property. | ComponentType | - | | twoToneColor | Only support the two-tone icon. Specific the primary color. | string (hex color) | - | diff --git a/components/icon/index.js b/components/icon/index.js index b5d438b6e..8cde86400 100644 --- a/components/icon/index.js +++ b/components/icon/index.js @@ -11,6 +11,7 @@ import { alias, } from './utils'; import warning from '../_util/warning'; +import LocaleReceiver from '../locale-provider/LocaleReceiver'; import { getTwoToneColor, setTwoToneColor } from './twoTonePrimaryColor'; import { filterEmpty, getClass } from '../_util/props-util'; @@ -20,109 +21,146 @@ setTwoToneColor('#1890ff'); const defaultTheme = 'outlined'; let dangerousTheme; +function renderIcon(h, locale, context) { + const { props, slots, listeners, data } = context; + const { + // affect inner ... + type, + component: Component, + viewBox, + spin, + // other + theme, // default to outlined + twoToneColor, + rotate, + tabIndex, + } = 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', + }); + + const svgStyle = rotate + ? { + msTransform: `rotate(${rotate}deg)`, + transform: `rotate(${rotate}deg)`, + } + : undefined; + + let innerNode; + + // component > children > type + if (Component) { + const innerSvgProps = { + attrs: { + ...svgBaseProps, + style: svgStyle, + viewBox, + }, + class: svgClassString, + }; + if (!viewBox) { + delete innerSvgProps.attrs.viewBox; + } + + innerNode = {children}; + } + 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 = ( + + {children} + + ); + } + + 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 = ( + + ); + } + let iconTabIndex = tabIndex; + if (iconTabIndex === undefined && ('click' in listeners)) { + iconTabIndex = -1; + } + const { attrs, ...restDataProps } = data; + // functional component not support nativeOn,https://github.com/vuejs/vue/issues/7526 + const iProps = { + ...restDataProps, + attrs: { + ...attrs, + 'aria-label': type && `${locale.icon}: ${type}`, + tabIndex: iconTabIndex, + }, + on: { ...listeners, ...data.nativeOn }, + class: classString, + staticClass: '', + }; + return {innerNode}; +} + const Icon = { functional: true, name: 'AIcon', props: { + tabIndex: PropTypes.number, type: PropTypes.string, component: PropTypes.any, viewBox: PropTypes.any, spin: PropTypes.bool.def(false), + rotate: PropTypes.number, theme: PropTypes.oneOf(['filled', 'outlined', 'twoTone']), twoToneColor: PropTypes.string, + role: PropTypes.string, }, render(h, context) { - const { props, slots, listeners, data } = context; - const { - // affect inner ... - 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`.', + return ( + renderIcon(h, locale, context) }} + /> ); - - 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 = {children}; - } - 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 = ( - - {children} - - ); - } - - 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 = ( - - ); - } - // functional component not support nativeOn,https://github.com/vuejs/vue/issues/7526 - const iProps = { - ...data, - on: { ...listeners, ...data.nativeOn }, - class: classString, - staticClass: '', - }; - return {innerNode}; }, }; diff --git a/components/icon/index.zh-CN.md b/components/icon/index.zh-CN.md index 538b39e86..eed622db4 100644 --- a/components/icon/index.zh-CN.md +++ b/components/icon/index.zh-CN.md @@ -7,6 +7,7 @@ | style | 设置图标的样式,例如 `fontSize` 和 `color` | CSSProperties | - | | theme | 图标主题风格。可选实心、描线、双色等主题风格,适用于官方图标 | 'filled' \| 'outlined' \| 'twoTone' | 'outlined' | | spin | 是否有旋转动画 | boolean | false | +| rotate | 图标旋转角度(1.40.0 后新增,IE9 无效) | number | - | | component | 控制如何渲染图标,通常是一个渲染根标签为 `` 的 `Vue` 组件,**会使 `type` 属性失效** | ComponentType | - | | twoToneColor | 仅适用双色图标。设置双色图标的主要颜色 | string (十六进制颜色) | - | diff --git a/components/list/index.jsx b/components/list/index.jsx index bb3d7dc1d..4f1c926ad 100644 --- a/components/list/index.jsx +++ b/components/list/index.jsx @@ -1,8 +1,6 @@ import PropTypes from '../_util/vue-types'; import classNames from 'classnames'; import omit from 'omit.js'; -import LocaleReceiver from '../locale-provider/LocaleReceiver'; -import defaultLocale from '../locale-provider/default'; import { ConfigConsumerProps } from '../config-provider'; import Spin from '../spin';