refactor: steps #6406

pull/6423/head
tangjinzhou 2023-04-05 16:28:49 +08:00
parent 9a5cbeee50
commit fbfec0a062
21 changed files with 663 additions and 320 deletions

View File

@ -239,17 +239,43 @@ Components which support rtl direction are listed here, you can toggle the direc
<a-col :span="24">
<a-divider orientation="left">Steps example</a-divider>
<div>
<a-steps progress-dot :current="state.currentStep">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
progress-dot
:current="state.currentStep"
:items="[
{
title: 'Finished',
description: 'This is a description.',
},
{
title: 'In Progress',
description: 'This is a description.',
},
{
title: 'Waiting',
description: 'This is a description.',
},
]"
></a-steps>
<br />
<a-steps :current="state.currentStep" @change="onStepsChange">
<a-step title="Step 1" description="This is a description." />
<a-step title="Step 2" description="This is a description." />
<a-step title="Step 3" description="This is a description." />
</a-steps>
<a-steps
:current="state.currentStep"
:items="[
{
title: 'Step 1',
description: 'This is a description.',
},
{
title: 'Step 2',
description: 'This is a description.',
},
{
title: 'Step 3',
description: 'This is a description.',
},
]"
@change="onStepsChange"
></a-steps>
</div>
</a-col>
</a-row>

View File

@ -198,23 +198,10 @@ Modify global theme color by css variable. Css variable depends on the design, i
<a-pagination show-quick-jumper :default-current="2" :total="500" />
<!-- Steps -->
<a-steps :current="1" :percent="60">
<a-step title="Finished" description="This is a description." />
<a-step
title="In Progress"
sub-title="Left 00:00:08"
description="This is a description."
/>
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps :current="1" :percent="60" :items="stepsItems"></a-steps>
<!-- Steps - dot -->
<a-steps :current="2" status="error" progress-dot>
<a-step title="Finished" description="You can hover on the dot." />
<a-step title="In Progress" description="You can hover on the dot." />
<a-step title="Error" description="You can hover on the dot." />
<a-step title="Waiting" description="You can hover on the dot." />
</a-steps>
<a-steps :current="2" status="error" progress-dot :items="stepsItems2"></a-steps>
<!-- Form - Input -->
<a-form>
@ -568,6 +555,34 @@ export default defineComponent({
colorState,
inputProps,
selectedKeys: ref(['mail']),
stepsItems: [
{
title: 'Finished',
description: 'This is a description.',
},
{
title: 'In Progress',
description: 'This is a description.',
},
{
title: 'Waiting',
description: 'This is a description.',
},
],
stepsItems2: [
{
title: 'Finished',
description: 'You can hover on the dot.',
},
{
title: 'In Progress',
description: 'You can hover on the dot.',
},
{
title: 'Waiting',
description: 'You can hover on the dot.',
},
],
};
},
});

View File

@ -17,17 +17,42 @@ Setting `v-model` makes Steps clickable.
<template>
<div>
<a-steps v-model:current="current">
<a-step title="Step 1" description="This is a description." />
<a-step title="Step 2" description="This is a description." />
<a-step title="Step 3" description="This is a description." />
</a-steps>
<a-steps
v-model:current="current"
:items="[
{
title: 'Step 1',
description,
},
{
title: 'Step 2',
description,
},
{
title: 'Step 3',
description,
},
]"
></a-steps>
<a-divider />
<a-steps v-model:current="current" direction="vertical">
<a-step title="Step 1" description="This is a description." />
<a-step title="Step 2" description="This is a description." />
<a-step title="Step 3" description="This is a description." />
</a-steps>
<a-steps
v-model:current="current"
direction="vertical"
:items="[
{
title: 'Step 1',
description,
},
{
title: 'Step 2',
description,
},
{
title: 'Step 3',
description,
},
]"
></a-steps>
</div>
</template>
<script lang="ts">
@ -39,6 +64,7 @@ export default defineComponent({
return {
current,
description: 'This is a description.',
};
},
});

View File

@ -17,7 +17,27 @@ You can customize the display for Steps with progress dot style.
<template>
<div>
<a-steps :current="1">
<a-steps
v-model:current="current"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Progress',
description,
},
{
title: 'Waiting',
description,
},
{
title: 'Waiting',
description,
},
]"
>
<template #progressDot="{ index, status, prefixCls }">
<a-popover>
<template #content>
@ -26,10 +46,20 @@ You can customize the display for Steps with progress dot style.
<span :class="`${prefixCls}-icon-dot`" />
</a-popover>
</template>
<a-step title="Finished" description="You can hover on the dot." />
<a-step title="In Progress" description="You can hover on the dot." />
<a-step title="Waiting" description="You can hover on the dot." />
<a-step title="Waiting" description="You can hover on the dot." />
</a-steps>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -15,9 +15,36 @@ title:
By using `status` of `Steps`, you can specify the state for current step.
</docs>
<template>
<a-steps :current="1" status="error">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
:v-model:current="current"
status="error"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Process',
description,
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -15,44 +15,47 @@ title:
You can use your own custom icons by setting the property `icon` for `Steps.Step`.
</docs>
<template>
<a-steps>
<a-step status="finish" title="Login">
<template #icon>
<user-outlined />
</template>
</a-step>
<a-step status="finish" title="Verification">
<template #icon>
<solution-outlined />
</template>
</a-step>
<a-step status="process" title="Pay">
<template #icon>
<loading-outlined />
</template>
</a-step>
<a-step status="wait" title="Done">
<template #icon>
<smile-outlined />
</template>
</a-step>
</a-steps>
<a-steps :items="items"></a-steps>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, ref, h } from 'vue';
import {
UserOutlined,
SolutionOutlined,
LoadingOutlined,
SmileOutlined,
} from '@ant-design/icons-vue';
import { StepProps } from 'ant-design-vue';
export default defineComponent({
components: {
UserOutlined,
SolutionOutlined,
LoadingOutlined,
SmileOutlined,
setup() {
const current = ref<number>(0);
return {
current,
items: [
{
title: 'Login',
status: 'finish',
icon: h(UserOutlined),
},
{
title: 'Verification',
status: 'finish',
icon: h(SolutionOutlined),
},
{
title: 'Pay',
status: 'process',
icon: h(LoadingOutlined),
},
{
title: 'Done',
status: 'wait',
icon: h(SmileOutlined),
},
] as StepProps[],
};
},
});
</script>

View File

@ -43,15 +43,8 @@ Inline type steps, suitable for displaying the process and current state of the
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { List, Steps, Avatar } from 'ant-design-vue';
export default defineComponent({
components: {
[List.name]: List,
[Steps.name]: Steps,
[Avatar.name]: Avatar,
},
setup() {
const data = [
{

View File

@ -17,38 +17,80 @@ Navigation steps.
<template>
<div>
<a-steps v-model:current="current" type="navigation" size="small" :style="stepStyle">
<a-step
title="Step 1"
sub-title="00:00:05"
status="finish"
description="This is a description."
/>
<a-step
title="Step 2"
sub-title="00:01:02"
status="process"
description="This is a description."
/>
<a-step
title="Step 3"
sub-title="waiting for longlong time"
status="wait"
description="This is a description."
/>
</a-steps>
<a-steps v-model:current="current" type="navigation" :style="stepStyle">
<a-step status="finish" title="Step 1" />
<a-step status="process" title="Step 2" />
<a-step status="wait" title="Step 3" />
<a-step status="wait" title="Step 4" />
</a-steps>
<a-steps v-model:current="current" type="navigation" size="small" :style="stepStyle">
<a-step status="finish" title="finish 1" />
<a-step status="finish" title="finish 2" />
<a-step status="process" title="current process" />
<a-step status="wait" title="wait" disabled />
</a-steps>
<a-steps
v-model:current="current"
type="navigation"
size="small"
:style="stepStyle"
:items="[
{
title: 'Step 1',
subTitle: '00:00:05',
status: 'finish',
description: 'This is a description.',
},
{
title: 'Step 2',
subTitle: '00:01:02',
status: 'process',
description: 'This is a description.',
},
{
title: 'Step 3',
subTitle: 'waiting for longlong time',
status: 'wait',
description: 'This is a description.',
},
]"
></a-steps>
<a-steps
v-model:current="current"
type="navigation"
:style="stepStyle"
:items="[
{
status: 'finish',
title: 'Step 1',
},
{
status: 'process',
title: 'Step 2',
},
{
status: 'wait',
title: 'Step 3',
},
{
status: 'wait',
title: 'Step 4',
},
]"
></a-steps>
<a-steps
v-model:current="current"
type="navigation"
size="small"
:style="stepStyle"
:items="[
{
status: 'finish',
title: 'finish 1',
},
{
status: 'finish',
title: 'finish 2',
},
{
status: 'process',
title: 'current process',
},
{
status: 'wait',
title: 'wait',
disabled: true,
},
]"
></a-steps>
</div>
</template>
<script lang="ts">

View File

@ -17,18 +17,51 @@ Steps with progress dot style.
<template>
<div>
<a-steps progress-dot :current="1">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
progress-dot
:current="1"
:items="[
{
title: 'Finished',
description: 'This is a description.',
},
{
title: 'In Progress',
description: 'This is a description.',
},
{
title: 'Waiting',
description: 'This is a description.',
},
]"
></a-steps>
<a-divider />
<a-steps progress-dot :current="1" direction="vertical">
<a-step title="Finished" description="This is a description. This is a description." />
<a-step title="Finished" description="This is a description. This is a description." />
<a-step title="In Progress" description="This is a description. This is a description." />
<a-step title="Waiting" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
progress-dot
:current="1"
direction="vertical"
:items="[
{
title: 'Finished',
description: 'This is a description. This is a description.',
},
{
title: 'Finished',
description: 'This is a description. This is a description.',
},
{
title: 'In Progress',
description: 'This is a description. This is a description.',
},
{
title: 'Waiting',
description: 'This is a description.',
},
{
title: 'Waiting',
description: 'This is a description.',
},
]"
></a-steps>
</div>
</template>

View File

@ -17,14 +17,57 @@ Steps with progress.
</docs>
<template>
<a-steps :percent="60" :current="1">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" sub-title="Left 00:00:08" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps :percent="60" :current="1" size="small">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" sub-title="Left 00:00:08" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
:percent="60"
:v-model:current="current"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Progress',
subTitle: 'Left 00:00:08',
description,
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
<a-steps
:percent="60"
:current="1"
size="small"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Progress',
subTitle: 'Left 00:00:08',
description,
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -15,15 +15,36 @@ title:
The most basic step bar.
</docs>
<template>
<a-steps :current="1">
<a-step>
<!-- <span slot="title">Finished</span> -->
<template #title>Finished</template>
<template #description>
<span>This is a description.</span>
</template>
</a-step>
<a-step title="In Progress" sub-title="Left 00:00:08" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
:current="1"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Progress',
description,
subTitle: 'Left 00:00:08',
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -15,9 +15,33 @@ title:
By setting like this: `<Steps size="small">`, you can get a mini version.
</docs>
<template>
<a-steps :current="1" size="small">
<a-step title="Finished" />
<a-step title="In Progress" />
<a-step title="Waiting" />
</a-steps>
<a-steps
:current="1"
size="small"
:items="[
{
title: 'Finished',
},
{
title: 'In Progress',
},
{
title: 'Waiting',
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -16,9 +16,7 @@ Cooperate with the content and buttons, to represent the progress of a process.
</docs>
<template>
<div>
<a-steps :current="current">
<a-step v-for="item in steps" :key="item.title" :title="item.title" />
</a-steps>
<a-steps :current="current" :items="items"></a-steps>
<div class="steps-content">
{{ steps[current].content }}
</div>
@ -48,23 +46,26 @@ export default defineComponent({
const prev = () => {
current.value--;
};
const steps = [
{
title: 'First',
content: 'First-content',
},
{
title: 'Second',
content: 'Second-content',
},
{
title: 'Last',
content: 'Last-content',
},
];
const items = steps.map(item => ({ key: item.title, title: item.title }));
return {
message,
current,
steps: [
{
title: 'First',
content: 'First-content',
},
{
title: 'Second',
content: 'Second-content',
},
{
title: 'Last',
content: 'Last-content',
},
],
steps,
items,
next,
prev,
};

View File

@ -15,9 +15,34 @@ title:
A simple mini version step bar in the vertical direction.
</docs>
<template>
<a-steps direction="vertical" size="small" :current="1">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
direction="vertical"
size="small"
:current="1"
:items="[
{ title: 'Finished', description },
{
title: 'In Progress',
description,
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -16,9 +16,36 @@ A simple step bar in the vertical direction.
</docs>
<template>
<a-steps direction="vertical" :current="1">
<a-step title="Finished" description="This is a description." />
<a-step title="In Progress" description="This is a description." />
<a-step title="Waiting" description="This is a description." />
</a-steps>
<a-steps
direction="vertical"
:current="1"
:items="[
{
title: 'Finished',
description,
},
{
title: 'In Progress',
description,
},
{
title: 'Waiting',
description,
},
]"
></a-steps>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const current = ref<number>(0);
return {
current,
description: 'This is a description.',
};
},
});
</script>

View File

@ -29,23 +29,21 @@ The whole of the step bar.
| type | Type of steps, can be set to one of the following values: `default`, `navigation` | string | `default` | 1.5.0 |
| items | StepItem content | [StepItem](#stepsstep) | [] | |
### `type="inline"` (4.0+)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| current | To set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | 0 | |
| initial | Set the initial step, counting from 0 | number | 0 | |
| status | To specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` | |
| items | StepItem content. not supported: `icon` `subtitle` | [StepItem](#stepsstep) | [] | |
#### Steps Events
| Events Name | Description | Arguments | Version | |
| ----------- | ---------------------------- | ----------------- | ------- | ----- |
| change | Trigger when Step is changed | (current) => void | - | 1.5.0 |
### `type="inline"`
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| className | Additional class to Steps | string | - | |
| current | To set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | 0 | |
| initial | Set the initial step, counting from 0 | number | 0 | |
| status | To specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` | |
| onChange | Trigger when Step is changed | (current) => void | - | |
| items | StepItem content. not supported: `icon` `subtitle` | [StepItem](#stepsstep) | [] | 4.24.0 |
### Steps.Step
A single step in the step bar.

View File

@ -2,8 +2,8 @@ import type { App, ExtractPropTypes } from 'vue';
import { computed, defineComponent } 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 type { VueNode } from '../_util/type';
import { anyType, booleanType, stringType, functionType, someType, arrayType } from '../_util/type';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import VcSteps, { Step as VcStep } from '../vc-steps';
import useConfigInject from '../config-provider/hooks/useConfigInject';
@ -13,9 +13,8 @@ import Progress from '../progress';
import omit from '../_util/omit';
import Tooltip from '../tooltip';
import { VcStepProps } from '../vc-steps/Step';
import type { ProgressDotRender } from '../vc-steps/Steps';
import type { Status, ProgressDotRender } from '../vc-steps/interface';
import type { MouseEventHandler } from '../_util/EventInterface';
import { booleanType, stringType, functionType, someType, arrayType } from '../_util/type';
// CSSINJS
import useStyle from './style';
@ -29,7 +28,7 @@ export const stepsProps = () => ({
responsive: booleanType(),
items: arrayType<StepProps[]>(),
labelPlacement: stringType<'horizontal' | 'vertical'>(),
status: stringType<'wait' | 'process' | 'finish' | 'error'>(),
status: stringType<Status>(),
size: stringType<'default' | 'small'>(),
direction: stringType<'horizontal' | 'vertical'>(),
progressDot: someType<boolean | ProgressDotRender>([Boolean, Function]),
@ -39,12 +38,12 @@ export const stepsProps = () => ({
});
export const stepProps = () => ({
description: PropTypes.any,
icon: PropTypes.any,
status: stringType<'wait' | 'process' | 'finish' | 'error'>(),
description: anyType(),
icon: anyType(),
status: stringType<Status>(),
disabled: booleanType(),
title: PropTypes.any,
subTitle: PropTypes.any,
title: anyType(),
subTitle: anyType(),
onClick: functionType<MouseEventHandler>(),
});
@ -65,7 +64,6 @@ const Steps = defineComponent({
// emits: ['update:current', 'change'],
setup(props, { attrs, slots, emit }) {
const { prefixCls, direction: rtlDirection, configProvider } = useConfigInject('steps', props);
const mergedItems = computed(() => props.items);
// style
const [wrapSSR, hashId] = useStyle(prefixCls);
@ -130,7 +128,7 @@ const Steps = defineComponent({
icons={icons.value}
{...attrs}
{...omit(props, ['percent', 'responsive'])}
items={mergedItems.value}
items={props.items}
direction={direction.value}
prefixCls={prefixCls.value}
iconPrefix={iconPrefix.value}

View File

@ -34,23 +34,21 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cFsBQLA0b7UAAA
| type | 步骤条类型,有 `default``navigation` 两种 | string | `default` | 1.5.0 |
| items | 配置选项卡内容 | [StepItem](#stepsstep)[] | [] | |
### `type="inline"` (4.0+)
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| current | 指定当前步骤,从 0 开始记数。在子 Step 元素中,可以通过 `status` 属性覆盖状态 | number | 0 | |
| initial | 起始序号,从 0 开始记数 | number | 0 | |
| status | 指定当前步骤的状态,可选 `wait` `process` `finish` `error` | string | `process` | |
| items | 配置选项卡内容,不支持 `icon` `subtitle` | [StepItem](#stepsstep) | [] | |
#### Steps 事件
| 事件名称 | 说明 | 回调参数 | 版本 | |
| -------- | ------------------ | ----------------- | ---- | ----- |
| change | 点击切换步骤时触发 | (current) => void | - | 1.5.0 |
### `type="inline"`
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| className | 步骤条类名 | string | - | |
| current | 指定当前步骤,从 0 开始记数。在子 Step 元素中,可以通过 `status` 属性覆盖状态 | number | 0 | |
| initial | 起始序号,从 0 开始记数 | number | 0 | |
| status | 指定当前步骤的状态,可选 `wait` `process` `finish` `error` | string | `process` | |
| onChange | 点击切换步骤时触发 | (current) => void | - | |
| items | 配置选项卡内容,不支持 `icon` `subtitle` | [StepItem](#stepsstep) | [] | 4.24.0 |
### Steps.Step
步骤条内的每一个步骤。

View File

@ -1,27 +1,28 @@
import PropTypes, { withUndefined } from '../_util/vue-types';
import type { CSSProperties, PropType } from 'vue';
import type { CSSProperties, ExtractPropTypes } from 'vue';
import { defineComponent } from 'vue';
import type { EventHandler } from '../_util/EventInterface';
import classNames from '../_util/classNames';
import warning from '../_util/warning';
import type { VueNode } from '../_util/type';
import { stringType, functionType } from '../_util/type';
import type { StepIconRender, Status } from './interface';
function isString(str: any): str is string {
return typeof str === 'string';
}
function noop() {}
export const VcStepProps = () => ({
class: PropTypes.string,
prefixCls: String,
wrapperStyle: { type: Object as PropType<CSSProperties>, default: undefined as CSSProperties },
itemWidth: String,
active: { type: Boolean, default: undefined },
disabled: { type: Boolean, default: undefined },
status: String,
status: stringType<Status>(),
iconPrefix: String,
icon: PropTypes.any,
adjustMarginRight: String,
stepNumber: Number,
stepIndex: Number,
style: PropTypes.style,
description: PropTypes.any,
title: PropTypes.any,
subTitle: PropTypes.any,
@ -31,22 +32,30 @@ export const VcStepProps = () => ({
finish: PropTypes.any,
error: PropTypes.any,
}).loose,
onClick: Function,
onStepClick: Function,
stepIcon: Function,
onClick: functionType(),
onStepClick: functionType<(next: number) => void>(),
stepIcon: functionType<StepIconRender>(),
itemRender: functionType<(stepItem: VueNode) => VueNode>(),
});
export type VCStepProps = Partial<ExtractPropTypes<ReturnType<typeof VcStepProps>>>;
export default defineComponent({
compatConfig: { MODE: 3 },
name: 'Step',
props: VcStepProps(),
slots: ['title', 'subTitle', 'description', 'tailContent', 'stepIcon', 'progressDot'],
emits: ['click', 'stepClick'],
setup(props, { slots, emit }) {
setup(props, { slots, emit, attrs }) {
const onItemClick: EventHandler = e => {
emit('click', e);
emit('stepClick', props.stepIndex);
};
if (attrs.__legacy !== false) {
warning(
false,
'Steps',
'Step is deprecated, and not support inline type. Please use `items` directly. ',
);
}
const renderIconNode = ({ icon, title, description }) => {
const {
prefixCls,
@ -113,7 +122,6 @@ export default defineComponent({
const {
prefixCls,
itemWidth,
style,
active,
status = 'wait',
tailContent,
@ -127,20 +135,15 @@ export default defineComponent({
onStepClick,
} = props;
const mergedStatus = status || 'wait';
const classString = classNames(
`${prefixCls}-item`,
`${prefixCls}-item-${mergedStatus}`,
props.class,
{
[`${prefixCls}-item-custom`]: icon,
[`${prefixCls}-item-active`]: active,
[`${prefixCls}-item-disabled`]: disabled === true,
},
);
const classString = classNames(`${prefixCls}-item`, `${prefixCls}-item-${mergedStatus}`, {
[`${prefixCls}-item-custom`]: icon,
[`${prefixCls}-item-active`]: active,
[`${prefixCls}-item-disabled`]: disabled === true,
});
const stepProps = {
class: classString,
};
const stepItemStyle: CSSProperties = { ...style };
const stepItemStyle: CSSProperties = {};
if (itemWidth) {
stepItemStyle.width = itemWidth;
}
@ -161,8 +164,8 @@ export default defineComponent({
accessibilityProps.tabindex = 0;
accessibilityProps.onClick = onItemClick;
}
return (
<div {...stepProps} style={stepItemStyle}>
const stepNode = (
<div {...stepProps} style={[attrs.style as CSSProperties, stepItemStyle]}>
<div {...accessibilityProps} class={`${prefixCls}-item-container`}>
<div class={`${prefixCls}-item-tail`}>{tailContent}</div>
<div class={`${prefixCls}-item-icon`}>
@ -185,6 +188,10 @@ export default defineComponent({
</div>
</div>
);
if (props.itemRender) {
return props.itemRender(stepNode);
}
return stepNode;
};
},
});

View File

@ -1,25 +1,13 @@
import PropTypes from '../_util/vue-types';
import { defineComponent } from 'vue';
import classNames from '../_util/classNames';
import type { VCStepProps } from './Step';
import Step from './Step';
import { cloneElement } from '../_util/vnode';
import type { VueNode } from '../_util/type';
import { functionType, stringType } from '../_util/type';
import { filterEmpty } from '../_util/props-util';
export type Status = 'error' | 'process' | 'finish' | 'wait';
export type StepIconRender = (info: {
index: number;
status: Status;
title: any;
description: any;
node: any;
}) => any;
export type ProgressDotRender = (info: {
iconDot: any;
index: number;
status: Status;
title: any;
description: any;
}) => any;
import { cloneElement } from '../_util/vnode';
import type { Status, StepIconRender } from './interface';
export default defineComponent({
compatConfig: { MODE: 3 },
@ -30,7 +18,7 @@ export default defineComponent({
iconPrefix: PropTypes.string.def('vc'),
direction: PropTypes.string.def('horizontal'),
labelPlacement: PropTypes.string.def('horizontal'),
status: PropTypes.string.def('process'),
status: stringType<Status>('process'),
size: PropTypes.string.def(''),
progressDot: PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func]).def(undefined),
initial: PropTypes.number.def(0),
@ -40,25 +28,85 @@ export default defineComponent({
finish: PropTypes.any,
error: PropTypes.any,
}).loose,
style: PropTypes.style,
stepIcon: Function,
stepIcon: functionType<StepIconRender>(),
isInline: PropTypes.looseBool,
itemRender: Function,
itemRender: functionType<(item: Record<string, any>, stepItem: VueNode) => VueNode>(),
},
slots: ['stepIcon', 'progressDot'],
emits: ['change'],
setup(props, { slots, emit }) {
const onStepClick = next => {
const onStepClick = (next: number) => {
const { current } = props;
if (current !== next) {
emit('change', next);
}
};
const renderStep = (item: VCStepProps, index: number, legacyRender?: any) => {
const {
prefixCls,
iconPrefix,
status,
current,
initial,
icons,
stepIcon = slots.stepIcon,
isInline,
itemRender,
progressDot = slots.progressDot,
} = props;
const mergedProgressDot = isInline || progressDot;
const mergedItem = { ...item, class: '' };
const stepNumber = initial + index;
const commonProps = {
active: stepNumber === current,
stepNumber: stepNumber + 1,
stepIndex: stepNumber,
key: stepNumber,
prefixCls,
iconPrefix,
progressDot: mergedProgressDot,
stepIcon,
icons,
onStepClick,
};
// fix tail color
if (status === 'error' && index === current - 1) {
mergedItem.class = `${prefixCls}-next-error`;
}
if (!mergedItem.status) {
if (stepNumber === current) {
mergedItem.status = status;
} else if (stepNumber < current) {
mergedItem.status = 'finish';
} else {
mergedItem.status = 'wait';
}
}
if (isInline) {
mergedItem.icon = undefined;
mergedItem.subTitle = undefined;
}
if (legacyRender) {
return legacyRender({ ...mergedItem, ...commonProps });
}
if (itemRender) {
mergedItem.itemRender = stepItem => itemRender(mergedItem, stepItem);
}
return <Step {...mergedItem} {...commonProps} __legacy={false} />;
};
const renderStepWithNode = (node: any, index: number) => {
return renderStep({ ...node.props }, index, stepProps => {
const stepNode = cloneElement(node, stepProps);
return stepNode;
});
};
return () => {
const {
prefixCls,
direction,
style = {},
type,
labelPlacement,
iconPrefix,
@ -68,7 +116,6 @@ export default defineComponent({
progressDot = slots.progressDot,
initial,
icons,
stepIcon = slots.stepIcon,
items,
isInline,
itemRender,
@ -87,68 +134,11 @@ export default defineComponent({
[`${prefixCls}-navigation`]: isNav,
[`${prefixCls}-inline`]: isInline,
});
const renderStep = (props, index, render) => {
const { prefixCls: pre = prefixCls, ...restProps } = props || {};
const stepNumber = initial + index;
const stepProps = {
...restProps,
stepNumber: stepNumber + 1,
stepIndex: stepNumber,
key: stepNumber,
prefixCls: pre,
iconPrefix,
progressDot: mergedProgressDot,
icons,
stepIcon,
onStepClick,
active: stepNumber === current,
};
// fix tail color
if (status === 'error' && index === current - 1) {
stepProps.class = `${prefixCls}-next-error`;
}
if (!restProps.status) {
if (stepNumber === current) {
stepProps.status = status;
} else if (stepNumber < current) {
stepProps.status = 'finish';
} else {
stepProps.status = 'wait';
}
}
if (isInline) {
stepProps.icon = undefined;
stepProps.subTitle = undefined;
}
stepProps.active = stepNumber === current;
return render(stepProps);
};
const renderStepWithNode = (node, index) => {
return renderStep({ ...node.props }, index, stepProps => {
const stepNode = cloneElement(node, stepProps);
if (itemRender) {
return itemRender(stepProps, stepNode);
}
return stepNode;
});
};
const renderStepWithItem = (item, index) => {
return renderStep(item, index, stepProps => {
const stepNode = <Step {...stepProps} />;
if (itemRender) {
return itemRender(stepProps, stepNode);
}
return stepNode;
});
};
return (
<div class={classString} style={style} {...restProps}>
{items.length
? items.map(renderStepWithItem)
: filterEmpty(slots.default?.()).map(renderStepWithNode)}
<div class={classString} {...restProps}>
{items.filter(item => item).map((item, index) => renderStep(item, index))}
{filterEmpty(slots.default?.()).map(renderStepWithNode)}
</div>
);
};

View File

@ -0,0 +1,16 @@
export type Status = 'error' | 'process' | 'finish' | 'wait';
export type StepIconRender = (info: {
index: number;
status: Status;
title: any;
description: any;
node: any;
}) => any;
export type ProgressDotRender = (info: {
iconDot: any;
index: number;
status: Status;
title: any;
description: any;
}) => any;