feat: button use newicon
parent
6289705e73
commit
bb59d121c3
|
@ -1 +1 @@
|
||||||
Subproject commit aa3cee226dd1d25b3e598a37c692a9fa043d6b73
|
Subproject commit 600a6380580c96e418875d1690c5fa9f66b5023d
|
|
@ -1,9 +1,10 @@
|
||||||
import Wave from '../_util/wave';
|
import Wave from '../_util/wave';
|
||||||
import Icon from '../icon';
|
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||||
import buttonTypes from './buttonTypes';
|
import buttonTypes from './buttonTypes';
|
||||||
import { filterEmpty, getListeners } from '../_util/props-util';
|
import { filterEmpty, getListeners } from '../_util/props-util';
|
||||||
import { ConfigConsumerProps } from '../config-provider';
|
import { ConfigConsumerProps } from '../config-provider';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
|
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
|
||||||
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
|
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
|
||||||
const props = buttonTypes();
|
const props = buttonTypes();
|
||||||
|
@ -25,8 +26,33 @@ export default {
|
||||||
hasTwoCNChar: false,
|
hasTwoCNChar: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
watch: {
|
||||||
classes() {
|
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 {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
type,
|
type,
|
||||||
|
@ -70,36 +96,6 @@ export default {
|
||||||
[`${prefixCls}-block`]: block,
|
[`${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() {
|
fixTwoCNChar() {
|
||||||
// Fix for HOC usage like <FormatMessage />
|
// Fix for HOC usage like <FormatMessage />
|
||||||
const node = this.$refs.buttonNode;
|
const node = this.$refs.buttonNode;
|
||||||
|
@ -139,7 +135,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render() {
|
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 = {
|
const buttonProps = {
|
||||||
attrs: {
|
attrs: {
|
||||||
...$attrs,
|
...$attrs,
|
||||||
|
@ -151,8 +149,7 @@ export default {
|
||||||
click: handleClick,
|
click: handleClick,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const iconType = sLoading ? 'loading' : icon;
|
const iconNode = sLoading ? <LoadingOutlined /> : icon || null;
|
||||||
const iconNode = iconType ? <Icon type={iconType} /> : null;
|
|
||||||
const children = filterEmpty($slots.default);
|
const children = filterEmpty($slots.default);
|
||||||
const autoInsertSpace = this.configProvider.autoInsertSpaceInButton !== false;
|
const autoInsertSpace = this.configProvider.autoInsertSpaceInButton !== false;
|
||||||
const kids = children.map(child =>
|
const kids = children.map(child =>
|
||||||
|
|
|
@ -3,7 +3,7 @@ export default () => ({
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']).def('button'),
|
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']).def('button'),
|
||||||
icon: PropTypes.string,
|
// icon: PropTypes.string,
|
||||||
shape: PropTypes.oneOf(['circle', 'circle-outline', 'round']),
|
shape: PropTypes.oneOf(['circle', 'circle-outline', 'round']),
|
||||||
size: PropTypes.oneOf(['small', 'large', 'default']).def('default'),
|
size: PropTypes.oneOf(['small', 'large', 'default']).def('default'),
|
||||||
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
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 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';
|
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 = {
|
const Icon = {
|
||||||
functional: true,
|
functional: true,
|
||||||
name: 'AIcon',
|
name: 'AIcon',
|
||||||
props: {
|
render() {
|
||||||
tabIndex: PropTypes.number,
|
warning(false, 'Icon', 'Empty Icon');
|
||||||
type: PropTypes.string,
|
return null;
|
||||||
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) }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Icon.createFromIconfontCN = createFromIconfontCN;
|
|
||||||
Icon.getTwoToneColor = getTwoToneColor;
|
|
||||||
Icon.setTwoToneColor = setTwoToneColor;
|
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
Icon.install = function(Vue) {
|
Icon.install = function(Vue) {
|
||||||
Vue.use(Base);
|
Vue.use(Base);
|
||||||
|
|
|
@ -174,8 +174,7 @@
|
||||||
"xhr-mock": "^2.5.1"
|
"xhr-mock": "^2.5.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^2.1.1",
|
"@ant-design/icons-vue": "^4.0.4",
|
||||||
"@ant-design/icons-vue": "^2.0.0",
|
|
||||||
"add-dom-event-listener": "^1.0.2",
|
"add-dom-event-listener": "^1.0.2",
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"async-validator": "^3.0.3",
|
"async-validator": "^3.0.3",
|
||||||
|
|
Loading…
Reference in New Issue