mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-11-30 02:57:50 +08:00
feat: button use newicon
This commit is contained in:
parent
6289705e73
commit
bb59d121c3
@ -1 +1 @@
|
||||
Subproject commit aa3cee226dd1d25b3e598a37c692a9fa043d6b73
|
||||
Subproject commit 600a6380580c96e418875d1690c5fa9f66b5023d
|
@ -1,9 +1,10 @@
|
||||
import Wave from '../_util/wave';
|
||||
import Icon from '../icon';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import buttonTypes from './buttonTypes';
|
||||
import { filterEmpty, getListeners } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
|
||||
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
|
||||
const props = buttonTypes();
|
||||
@ -25,8 +26,33 @@ export default {
|
||||
hasTwoCNChar: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
watch: {
|
||||
loading(val, preVal) {
|
||||
if (preVal && typeof preVal !== 'boolean') {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
if (val && typeof val !== 'boolean' && val.delay) {
|
||||
this.delayTimeout = setTimeout(() => {
|
||||
this.sLoading = !!val;
|
||||
}, val.delay);
|
||||
} else {
|
||||
this.sLoading = !!val;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fixTwoCNChar();
|
||||
},
|
||||
updated() {
|
||||
this.fixTwoCNChar();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getClasses() {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type,
|
||||
@ -70,36 +96,6 @@ export default {
|
||||
[`${prefixCls}-block`]: block,
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
loading(val, preVal) {
|
||||
if (preVal && typeof preVal !== 'boolean') {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
if (val && typeof val !== 'boolean' && val.delay) {
|
||||
this.delayTimeout = setTimeout(() => {
|
||||
this.sLoading = !!val;
|
||||
}, val.delay);
|
||||
} else {
|
||||
this.sLoading = !!val;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fixTwoCNChar();
|
||||
},
|
||||
updated() {
|
||||
this.fixTwoCNChar();
|
||||
},
|
||||
beforeDestroy() {
|
||||
// if (this.timeout) {
|
||||
// clearTimeout(this.timeout)
|
||||
// }
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fixTwoCNChar() {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
const node = this.$refs.buttonNode;
|
||||
@ -139,7 +135,9 @@ export default {
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { type, htmlType, classes, icon, disabled, handleClick, sLoading, $slots, $attrs } = this;
|
||||
this.icon = this.$scopedSlots.icon && this.$scopedSlots.icon();
|
||||
const classes = this.getClasses();
|
||||
const { type, htmlType, icon, disabled, handleClick, sLoading, $slots, $attrs } = this;
|
||||
const buttonProps = {
|
||||
attrs: {
|
||||
...$attrs,
|
||||
@ -151,8 +149,7 @@ export default {
|
||||
click: handleClick,
|
||||
},
|
||||
};
|
||||
const iconType = sLoading ? 'loading' : icon;
|
||||
const iconNode = iconType ? <Icon type={iconType} /> : null;
|
||||
const iconNode = sLoading ? <LoadingOutlined /> : icon || null;
|
||||
const children = filterEmpty($slots.default);
|
||||
const autoInsertSpace = this.configProvider.autoInsertSpaceInButton !== false;
|
||||
const kids = children.map(child =>
|
||||
|
@ -3,7 +3,7 @@ export default () => ({
|
||||
prefixCls: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']).def('button'),
|
||||
icon: PropTypes.string,
|
||||
// icon: PropTypes.string,
|
||||
shape: PropTypes.oneOf(['circle', 'circle-outline', 'round']),
|
||||
size: PropTypes.oneOf(['small', 'large', 'default']).def('default'),
|
||||
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
||||
|
@ -1,180 +1,15 @@
|
||||
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 LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { getTwoToneColor, setTwoToneColor } from './twoTonePrimaryColor';
|
||||
import { filterEmpty, getClass } from '../_util/props-util';
|
||||
import Base from '../base';
|
||||
|
||||
// Initial setting
|
||||
VueIcon.add(...Object.keys(allIcons).map(key => allIcons[key]));
|
||||
setTwoToneColor('#1890ff');
|
||||
const defaultTheme = 'outlined';
|
||||
let dangerousTheme;
|
||||
|
||||
function renderIcon(h, locale, context) {
|
||||
const { props, slots, listeners, data } = context;
|
||||
const {
|
||||
// affect inner <svg>...</svg>
|
||||
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',
|
||||
'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;
|
||||
|
||||
const innerSvgProps = {
|
||||
attrs: {
|
||||
...svgBaseProps,
|
||||
viewBox,
|
||||
},
|
||||
class: svgClassString,
|
||||
style: svgStyle,
|
||||
};
|
||||
if (!viewBox) {
|
||||
delete innerSvgProps.attrs.viewBox;
|
||||
}
|
||||
|
||||
const renderInnerNode = () => {
|
||||
// component > children > type
|
||||
if (Component) {
|
||||
return <Component {...innerSvgProps}>{children}</Component>;
|
||||
}
|
||||
if (children) {
|
||||
warning(
|
||||
Boolean(viewBox) || (children.length === 1 && children[0].tag === 'use'),
|
||||
'Icon',
|
||||
'Make sure that you provide correct `viewBox`' +
|
||||
' prop (default `0 0 1024 1024`) to the icon.',
|
||||
);
|
||||
const innerSvgProps = {
|
||||
attrs: {
|
||||
...svgBaseProps,
|
||||
},
|
||||
class: svgClassString,
|
||||
style: svgStyle,
|
||||
};
|
||||
return (
|
||||
<svg {...innerSvgProps} viewBox={viewBox}>
|
||||
{children}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof type === 'string') {
|
||||
let computedType = type;
|
||||
if (theme) {
|
||||
const themeInName = getThemeFromTypeName(type);
|
||||
warning(
|
||||
!themeInName || theme === themeInName,
|
||||
'Icon',
|
||||
`The icon name '${type}' already specify a theme '${themeInName}',` +
|
||||
` the 'theme' prop '${theme}' will be ignored.`,
|
||||
);
|
||||
}
|
||||
computedType = withThemeSuffix(
|
||||
removeTypeTheme(alias(computedType)),
|
||||
dangerousTheme || theme || defaultTheme,
|
||||
);
|
||||
|
||||
return (
|
||||
<VueIcon
|
||||
focusable="false"
|
||||
class={svgClassString}
|
||||
type={computedType}
|
||||
primaryColor={twoToneColor}
|
||||
style={svgStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
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 <i {...iProps}>{renderInnerNode()}</i>;
|
||||
}
|
||||
|
||||
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) {
|
||||
return (
|
||||
<LocaleReceiver
|
||||
componentName="Icon"
|
||||
scopedSlots={{ default: locale => renderIcon(h, locale, context) }}
|
||||
/>
|
||||
);
|
||||
render() {
|
||||
warning(false, 'Icon', 'Empty Icon');
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
Icon.createFromIconfontCN = createFromIconfontCN;
|
||||
Icon.getTwoToneColor = getTwoToneColor;
|
||||
Icon.setTwoToneColor = setTwoToneColor;
|
||||
|
||||
/* istanbul ignore next */
|
||||
Icon.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
|
@ -174,8 +174,7 @@
|
||||
"xhr-mock": "^2.5.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^2.1.1",
|
||||
"@ant-design/icons-vue": "^2.0.0",
|
||||
"@ant-design/icons-vue": "^4.0.4",
|
||||
"add-dom-event-listener": "^1.0.2",
|
||||
"array-tree-filter": "^2.1.0",
|
||||
"async-validator": "^3.0.3",
|
||||
|
Loading…
Reference in New Issue
Block a user