diff --git a/breakChange-2.x.md b/breakChange-2.x.md
index 91ca89edb..7fbbf9020 100644
--- a/breakChange-2.x.md
+++ b/breakChange-2.x.md
@@ -47,3 +47,7 @@ v-model -> v-model:selectedKeys :openKeys.sync -> v-mdoel:openKeys
## dropdown
v-model -> v-model:visible
+
+## Steps
+
+v-model -> v-model:current
diff --git a/components/_util/props-util.js b/components/_util/props-util.js
index 5ea7f004c..700d6f377 100644
--- a/components/_util/props-util.js
+++ b/components/_util/props-util.js
@@ -302,6 +302,10 @@ export function getComponentName(opts) {
return opts && (opts.Ctor.options.name || opts.tag);
}
+export function isFragment(c) {
+ return c.length === 1 && c[0].type === Fragment;
+}
+
export function isEmptyElement(c) {
return c.type === Comment || (c.type === Text && c.children.trim() === '');
}
@@ -311,6 +315,9 @@ export function isStringElement(c) {
}
export function filterEmpty(children = []) {
+ if (isFragment(children)) {
+ return children[0].children.filter(c => !isEmptyElement(c));
+ }
return children.filter(c => !isEmptyElement(c));
}
const initDefaultProps = (propTypes, defaultProps) => {
diff --git a/components/steps/index.jsx b/components/steps/index.jsx
index 2c60e6c81..677a5a7f4 100644
--- a/components/steps/index.jsx
+++ b/components/steps/index.jsx
@@ -1,10 +1,10 @@
+import { inject } from 'vue';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CheckOutlined from '@ant-design/icons-vue/CheckOutlined';
import PropTypes from '../_util/vue-types';
-import { initDefaultProps, getOptionProps, getListeners } from '../_util/props-util';
+import { initDefaultProps, getOptionProps, getComponent } from '../_util/props-util';
import VcSteps from '../vc-steps';
import { ConfigConsumerProps } from '../config-provider';
-import Base from '../base';
const getStepsProps = (defaultProps = {}) => {
const props = {
@@ -27,12 +27,10 @@ const Steps = {
props: getStepsProps({
current: 0,
}),
- inject: {
- configProvider: { default: () => ConfigConsumerProps },
- },
- model: {
- prop: 'current',
- event: 'change',
+ setup() {
+ return {
+ configProvider: inject('configProvider', ConfigConsumerProps),
+ };
},
Step: { ...VcSteps.Step, name: 'AStep' },
render() {
@@ -41,30 +39,27 @@ const Steps = {
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('steps', customizePrefixCls);
const iconPrefix = getPrefixCls('', customizeIconPrefixCls);
+ const progressDot = getComponent(this, 'progressDot', this, false);
const icons = {
finish: ,
error: ,
};
const stepsProps = {
- props: {
- icons,
- iconPrefix,
- prefixCls,
- ...props,
- },
- on: getListeners(this),
- scopedSlots: this.$scopedSlots,
+ icons,
+ iconPrefix,
+ prefixCls,
+ progressDot,
+ ...props,
};
- return {this.$slots.default};
+ return {this.$slots.default && this.$slots.default()};
},
};
/* istanbul ignore next */
-Steps.install = function(Vue) {
- Vue.use(Base);
- Vue.component(Steps.name, Steps);
- Vue.component(Steps.Step.name, Steps.Step);
+Steps.install = function(app) {
+ app.component(Steps.name, Steps);
+ app.component(Steps.Step.name, Steps.Step);
};
export default Steps;
diff --git a/components/vc-steps/Step.jsx b/components/vc-steps/Step.jsx
index a586f4721..e7af603d6 100644
--- a/components/vc-steps/Step.jsx
+++ b/components/vc-steps/Step.jsx
@@ -1,5 +1,5 @@
import PropTypes from '../_util/vue-types';
-import { getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util';
+import { getOptionProps, getComponent } from '../_util/props-util';
function isString(str) {
return typeof str === 'string';
@@ -28,21 +28,26 @@ export default {
finish: PropTypes.any,
error: PropTypes.any,
}).loose,
+ onClick: PropTypes.func,
+ onStepClick: PropTypes.func,
},
methods: {
- onClick(...args) {
- this.$emit('click', ...args);
+ onItemClick(...args) {
+ const { onClick } = this.$props;
+
+ if (onClick) {
+ this.$emit('click', ...args);
+ }
+
this.$emit('stepClick', this.stepIndex);
},
renderIconNode() {
- const { prefixCls, stepNumber, status, iconPrefix, icons } = getOptionProps(this);
- let progressDot = this.progressDot;
- if (progressDot === undefined) {
- progressDot = this.$scopedSlots.progressDot;
- }
- const icon = getComponentFromProp(this, 'icon');
- const title = getComponentFromProp(this, 'title');
- const description = getComponentFromProp(this, 'description');
+ const { prefixCls, stepNumber, status, iconPrefix, icons, progressDot } = getOptionProps(
+ this,
+ );
+ const icon = getComponent(this, 'icon');
+ const title = getComponent(this, 'title');
+ const description = getComponent(this, 'description');
let iconNode;
const iconClassName = {
[`${prefixCls}-icon`]: true,
@@ -86,22 +91,23 @@ export default {
tailContent,
adjustMarginRight,
disabled,
+ onClick,
+ onStepClick,
} = getOptionProps(this);
- const title = getComponentFromProp(this, 'title');
- const subTitle = getComponentFromProp(this, 'subTitle');
- const description = getComponentFromProp(this, 'description');
+ const title = getComponent(this, 'title');
+ const subTitle = getComponent(this, 'subTitle');
+ const description = getComponent(this, 'description');
const classString = {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-${status}`]: true,
- [`${prefixCls}-item-custom`]: getComponentFromProp(this, 'icon'),
+ [`${prefixCls}-item-custom`]: getComponent(this, 'icon'),
[`${prefixCls}-item-active`]: active,
[`${prefixCls}-item-disabled`]: disabled === true,
};
const stepProps = {
class: classString,
- on: getListeners(this),
};
const stepItemStyle = {};
if (itemWidth) {
@@ -110,17 +116,15 @@ export default {
if (adjustMarginRight) {
stepItemStyle.marginRight = adjustMarginRight;
}
- const listeners = getListeners(this);
+
const accessibilityProps = {
- attrs: {},
- on: {
- click: listeners.click || noop,
- },
+ onClick: onClick || noop,
};
- if (listeners.stepClick && !disabled) {
- accessibilityProps.attrs.role = 'button';
- accessibilityProps.attrs.tabIndex = 0;
- accessibilityProps.on.click = this.onClick;
+
+ if (onStepClick && !disabled) {
+ accessibilityProps.role = 'button';
+ accessibilityProps.tabIndex = 0;
+ accessibilityProps.onClick = this.onItemClick;
}
return (
diff --git a/components/vc-steps/Steps.jsx b/components/vc-steps/Steps.jsx
index 25a9cda62..b210e6efb 100644
--- a/components/vc-steps/Steps.jsx
+++ b/components/vc-steps/Steps.jsx
@@ -2,7 +2,7 @@ import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
import debounce from 'lodash/debounce';
import isFlexSupported from '../_util/isFlexSupported';
-import { filterEmpty, getEvents, getPropsData, getListeners } from '../_util/props-util';
+import { filterEmpty } from '../_util/props-util';
import { cloneElement } from '../_util/vnode';
export default {
@@ -59,6 +59,7 @@ export default {
const { current } = this.$props;
if (current !== next) {
this.$emit('change', next);
+ this.$emit('update:current', next);
}
},
calcStepOffsetWidth() {
@@ -97,17 +98,14 @@ export default {
status,
size,
current,
- $scopedSlots,
+ $slots,
+ progressDot,
initial,
icons,
} = this;
const isNav = type === 'navigation';
- let progressDot = this.progressDot;
- if (progressDot === undefined) {
- progressDot = $scopedSlots.progressDot;
- }
const { lastStepOffsetWidth, flexSupported } = this;
- const filteredChildren = filterEmpty(this.$slots.default);
+ const filteredChildren = filterEmpty($slots.default && $slots.default());
const lastIndex = filteredChildren.length - 1;
const adjustedlabelPlacement = progressDot ? 'vertical' : labelPlacement;
const classString = {
@@ -119,42 +117,36 @@ export default {
[`${prefixCls}-navigation`]: isNav,
[`${prefixCls}-flex-not-supported`]: !flexSupported,
};
- const listeners = getListeners(this);
const stepsProps = {
class: classString,
ref: 'vcStepsRef',
- on: listeners,
};
return (
{filteredChildren.map((child, index) => {
- const childProps = getPropsData(child);
+ const childProps = child.props || {};
const stepNumber = initial + index;
const stepProps = {
- props: {
- stepNumber: `${stepNumber + 1}`,
- stepIndex: stepNumber,
- prefixCls,
- iconPrefix,
- progressDot: this.progressDot,
- icons,
- ...childProps,
- },
- on: getEvents(child),
- scopedSlots: $scopedSlots,
+ stepNumber: `${stepNumber + 1}`,
+ stepIndex: stepNumber,
+ prefixCls,
+ iconPrefix,
+ progressDot,
+ icons,
+ ...childProps,
};
- if (listeners.change) {
- stepProps.on.stepClick = this.onStepClick;
+
+ const { onChange } = this.$attrs;
+ if (onChange || this.$attrs['onUpdate:current']) {
+ stepProps.onStepClick = this.onStepClick;
}
if (!flexSupported && direction !== 'vertical') {
if (isNav) {
- stepProps.props.itemWidth = `${100 / (lastIndex + 1)}%`;
- stepProps.props.adjustMarginRight = 0;
+ stepProps.itemWidth = `${100 / (lastIndex + 1)}%`;
+ stepProps.adjustMarginRight = 0;
} else if (index !== lastIndex) {
- stepProps.props.itemWidth = `${100 / lastIndex}%`;
- stepProps.props.adjustMarginRight = `${-Math.round(
- lastStepOffsetWidth / lastIndex + 1,
- )}px`;
+ stepProps.itemWidth = `${100 / lastIndex}%`;
+ stepProps.adjustMarginRight = `${-Math.round(lastStepOffsetWidth / lastIndex + 1)}px`;
}
}
// fix tail color
@@ -163,14 +155,14 @@ export default {
}
if (!childProps.status) {
if (stepNumber === current) {
- stepProps.props.status = status;
+ stepProps.status = status;
} else if (stepNumber < current) {
- stepProps.props.status = 'finish';
+ stepProps.status = 'finish';
} else {
- stepProps.props.status = 'wait';
+ stepProps.status = 'wait';
}
}
- stepProps.props.active = stepNumber === current;
+ stepProps.active = stepNumber === current;
return cloneElement(child, stepProps);
})}
diff --git a/examples/index.js b/examples/index.js
index 9f0851cfd..a7e80cb3b 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -33,6 +33,7 @@ import Modal from 'ant-design-vue/modal';
import Menu from 'ant-design-vue/menu';
import Mentions from 'ant-design-vue/mentions';
import Dropdown from 'ant-design-vue/dropdown';
+import Steps from 'ant-design-vue/steps';
import 'ant-design-vue/style.js';
const basic = {
@@ -79,4 +80,5 @@ app
.use(Menu)
.use(Mentions)
.use(Dropdown)
+ .use(Steps)
.mount('#app');