refactor: steps
							parent
							
								
									899757a054
								
							
						
					
					
						commit
						740ba04c02
					
				|  | @ -3,3 +3,5 @@ timeline: 新增 label | |||
| tree、tree-slelct: 新增虚拟滚动、title 逻辑变动 | ||||
| 
 | ||||
| date 相关组件: dayjs, UI 变动 | ||||
| 
 | ||||
| steps: add responsive、percent | ||||
|  |  | |||
|  | @ -1,19 +1,25 @@ | |||
| import type { App, ExtractPropTypes, Plugin } from 'vue'; | ||||
| import { defineComponent, inject } from 'vue'; | ||||
| import { computed } from 'vue'; | ||||
| import { defineComponent } from 'vue'; | ||||
| import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; | ||||
| import CheckOutlined from '@ant-design/icons-vue/CheckOutlined'; | ||||
| import PropTypes, { withUndefined } from '../_util/vue-types'; | ||||
| import { getOptionProps, getComponent, getSlot } from '../_util/props-util'; | ||||
| import initDefaultProps from '../_util/props-util/initDefaultProps'; | ||||
| import VcSteps from '../vc-steps'; | ||||
| import { defaultConfigProvider } from '../config-provider'; | ||||
| import { tuple } from '../_util/type'; | ||||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import useBreakpoint from '../_util/hooks/useBreakpoint'; | ||||
| import classNames from '../_util/classNames'; | ||||
| import Progress from '../progress'; | ||||
| import omit from '../_util/omit'; | ||||
| 
 | ||||
| const stepsProps = { | ||||
| export const stepsProps = () => ({ | ||||
|   prefixCls: PropTypes.string, | ||||
|   iconPrefix: PropTypes.string, | ||||
|   current: PropTypes.number, | ||||
|   initial: PropTypes.number, | ||||
|   percent: PropTypes.number, | ||||
|   responsive: PropTypes.looseBool, | ||||
|   labelPlacement: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'), | ||||
|   status: PropTypes.oneOf(tuple('wait', 'process', 'finish', 'error')), | ||||
|   size: PropTypes.oneOf(tuple('default', 'small')), | ||||
|  | @ -22,52 +28,98 @@ const stepsProps = { | |||
|   type: PropTypes.oneOf(tuple('default', 'navigation')), | ||||
|   onChange: PropTypes.func, | ||||
|   'onUpdate:current': PropTypes.func, | ||||
| }; | ||||
| }); | ||||
| 
 | ||||
| export type StepsProps = Partial<ExtractPropTypes<typeof stepsProps>>; | ||||
| export const stepProps = () => ({ | ||||
|   description: PropTypes.any, | ||||
|   icon: PropTypes.any, | ||||
|   status: PropTypes.oneOf(tuple('wait', 'process', 'finish', 'error')), | ||||
|   disabled: PropTypes.looseBool, | ||||
|   title: PropTypes.any, | ||||
|   subTitle: PropTypes.any, | ||||
|   onClick: PropTypes.func, | ||||
| }); | ||||
| 
 | ||||
| export type StepsProps = Partial<ExtractPropTypes<ReturnType<typeof stepsProps>>>; | ||||
| 
 | ||||
| export type StepProps = Partial<ExtractPropTypes<ReturnType<typeof stepProps>>>; | ||||
| 
 | ||||
| const Steps = defineComponent({ | ||||
|   name: 'ASteps', | ||||
|   inheritAttrs: false, | ||||
|   props: initDefaultProps(stepsProps, { | ||||
|   props: initDefaultProps(stepsProps(), { | ||||
|     current: 0, | ||||
|     responsive: true, | ||||
|   }), | ||||
|   slots: ['progressDot'], | ||||
|   emits: ['update:current', 'change'], | ||||
|   setup() { | ||||
|     return { | ||||
|       configProvider: inject('configProvider', defaultConfigProvider), | ||||
|   setup(props, { attrs, slots, emit }) { | ||||
|     const { prefixCls, direction: rtlDirection, configProvider } = useConfigInject('steps', props); | ||||
|     const screens = useBreakpoint(); | ||||
|     const direction = computed(() => | ||||
|       props.responsive && screens.value.xs ? 'vertical' : props.direction, | ||||
|     ); | ||||
|     const iconPrefix = computed(() => configProvider.getPrefixCls('', props.iconPrefix)); | ||||
|     const handleChange = (current: number) => { | ||||
|       emit('update:current', current); | ||||
|       emit('change', current); | ||||
|     }; | ||||
|     const stepIconRender = ({ | ||||
|       node, | ||||
|       status, | ||||
|     }: { | ||||
|       node: any; | ||||
|       index: number; | ||||
|       status: string; | ||||
|       title: any; | ||||
|       description: any; | ||||
|     }) => { | ||||
|       if (status === 'process' && props.percent !== undefined) { | ||||
|         // currently it's hard-coded, since we can't easily read the actually width of icon | ||||
|         const progressWidth = props.size === 'small' ? 32 : 40; | ||||
|         const iconWithProgress = ( | ||||
|           <div class={`${prefixCls}-progress-icon`}> | ||||
|             <Progress | ||||
|               type="circle" | ||||
|               percent={props.percent} | ||||
|               width={progressWidth} | ||||
|               strokeWidth={4} | ||||
|               format={() => null} | ||||
|             /> | ||||
|             {node} | ||||
|           </div> | ||||
|         ); | ||||
|         return iconWithProgress; | ||||
|       } | ||||
|       return node; | ||||
|     }; | ||||
|     return () => { | ||||
|       const stepsClassName = classNames( | ||||
|         { | ||||
|           [`${prefixCls.value}-rtl`]: rtlDirection.value === 'rtl', | ||||
|           [`${prefixCls.value}-with-progress`]: props.percent !== undefined, | ||||
|         }, | ||||
|         attrs.class, | ||||
|       ); | ||||
|       const icons = { | ||||
|         finish: <CheckOutlined class={`${prefixCls}-finish-icon`} />, | ||||
|         error: <CloseOutlined class={`${prefixCls}-error-icon`} />, | ||||
|       }; | ||||
|       return ( | ||||
|         <VcSteps | ||||
|           icons={icons} | ||||
|           {...omit(props, ['percent', 'responsive'])} | ||||
|           direction={direction.value} | ||||
|           prefixCls={prefixCls.value} | ||||
|           iconPrefix={iconPrefix.value} | ||||
|           class={stepsClassName} | ||||
|           onChange={handleChange} | ||||
|           v-slots={{ ...slots, stepIcon: stepIconRender }} | ||||
|         /> | ||||
|       ); | ||||
|     }; | ||||
|   }, | ||||
|   Step: { ...VcSteps.Step, name: 'AStep' }, | ||||
|   methods: { | ||||
|     handleChange(current: number) { | ||||
|       this.$emit('update:current', current); | ||||
|       this.$emit('change', current); | ||||
|     }, | ||||
|   }, | ||||
|   render() { | ||||
|     const props: StepsProps = { ...getOptionProps(this), ...this.$attrs }; | ||||
|     const { prefixCls: customizePrefixCls, iconPrefix: customizeIconPrefixCls } = props; | ||||
|     const getPrefixCls = this.configProvider.getPrefixCls; | ||||
|     const prefixCls = getPrefixCls('steps', customizePrefixCls); | ||||
|     const iconPrefix = getPrefixCls('', customizeIconPrefixCls); | ||||
|     const progressDot = getComponent(this, 'progressDot', this, false); | ||||
| 
 | ||||
|     const icons = { | ||||
|       finish: <CheckOutlined class={`${prefixCls}-finish-icon`} />, | ||||
|       error: <CloseOutlined class={`${prefixCls}-error-icon`} />, | ||||
|     }; | ||||
|     const stepsProps = { | ||||
|       icons, | ||||
|       iconPrefix, | ||||
|       prefixCls, | ||||
|       progressDot, | ||||
|       ...props, | ||||
|       canClick: !!(this.onChange || this['onUpdate:current']), | ||||
|       onChange: this.handleChange, | ||||
|     }; | ||||
|     return <VcSteps {...stepsProps}>{getSlot(this)}</VcSteps>; | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| /* istanbul ignore next */ | ||||
|  |  | |||
|  | @ -1,50 +0,0 @@ | |||
| .@{steps-prefix-cls}-flex-not-supported { | ||||
|   &.@{steps-prefix-cls}-horizontal.@{steps-prefix-cls}-label-horizontal { | ||||
|     .@{steps-prefix-cls}-item { | ||||
|       margin-left: -16px; | ||||
|       padding-left: 16px; | ||||
|       background: @steps-background; | ||||
|     } | ||||
| 
 | ||||
|     &.@{steps-prefix-cls}-small .@{steps-prefix-cls}-item { | ||||
|       margin-left: -12px; | ||||
|       padding-left: 12px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &.@{steps-prefix-cls}-dot { | ||||
|     .@{steps-prefix-cls}-item { | ||||
|       &:last-child { | ||||
|         overflow: hidden; | ||||
| 
 | ||||
|         .@{steps-prefix-cls}-icon-dot::after { | ||||
|           right: -200px; | ||||
|           width: 200px; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       .@{steps-prefix-cls}-icon-dot::before, | ||||
|       .@{steps-prefix-cls}-icon-dot::after { | ||||
|         position: absolute; | ||||
|         top: 0; | ||||
|         left: -10px; | ||||
|         width: 10px; | ||||
|         height: 8px; | ||||
|         background: @steps-background; | ||||
|         content: ''; | ||||
|       } | ||||
| 
 | ||||
|       .@{steps-prefix-cls}-icon-dot::after { | ||||
|         right: -10px; | ||||
|         left: auto; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-wait | ||||
|       .@{steps-prefix-cls}-item-icon | ||||
|       > .@{steps-prefix-cls}-icon | ||||
|       .@{steps-prefix-cls}-icon-dot { | ||||
|       background: #ccc; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -1,15 +1,15 @@ | |||
| .@{steps-prefix-cls}-item-custom { | ||||
|   .@{steps-prefix-cls}-item-icon { | ||||
|   > .@{steps-prefix-cls}-item-container > .@{steps-prefix-cls}-item-icon { | ||||
|     height: auto; | ||||
|     background: none; | ||||
|     border: 0; | ||||
|     > .@{steps-prefix-cls}-icon { | ||||
|       top: 0; | ||||
|       top: @steps-icon-custom-top; | ||||
|       left: 0.5px; | ||||
|       width: @steps-icon-size; | ||||
|       height: @steps-icon-size; | ||||
|       font-size: 24px; | ||||
|       line-height: @steps-icon-size; | ||||
|       width: @steps-icon-custom-size; | ||||
|       height: @steps-icon-custom-size; | ||||
|       font-size: @steps-icon-custom-font-size; | ||||
|       line-height: @steps-icon-custom-size; | ||||
|     } | ||||
|   } | ||||
|   &.@{steps-prefix-cls}-item-process { | ||||
|  | @ -25,6 +25,7 @@ | |||
|     .@{steps-prefix-cls}-item-custom { | ||||
|       .@{steps-prefix-cls}-item-icon { | ||||
|         width: auto; | ||||
|         background: none; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ | |||
| @process-icon-color: @primary-color; | ||||
| @process-title-color: @heading-color; | ||||
| @process-description-color: @text-color; | ||||
| @process-tail-color: @border-color-split; | ||||
| @process-icon-text-color: @text-color-inverse; | ||||
| @wait-icon-color: @disabled-color; | ||||
| @wait-title-color: @text-color-secondary; | ||||
|  | @ -21,19 +20,13 @@ | |||
| @error-tail-color: @wait-tail-color; | ||||
| @steps-nav-active-color: @primary-color; | ||||
| 
 | ||||
| @steps-icon-size: 32px; | ||||
| @steps-small-icon-size: 24px; | ||||
| @steps-dot-size: 8px; | ||||
| @steps-current-dot-size: 10px; | ||||
| @steps-desciption-max-width: 140px; | ||||
| @steps-nav-content-max-width: auto; | ||||
| 
 | ||||
| .@{steps-prefix-cls} { | ||||
|   .reset-component(); | ||||
| 
 | ||||
|   display: flex; | ||||
|   width: 100%; | ||||
|   font-size: 0; | ||||
|   text-align: initial; | ||||
| } | ||||
| 
 | ||||
| .@{steps-prefix-cls}-item { | ||||
|  | @ -65,8 +58,8 @@ | |||
|   &-icon { | ||||
|     width: @steps-icon-size; | ||||
|     height: @steps-icon-size; | ||||
|     margin-right: 8px; | ||||
|     font-size: @font-size-lg; | ||||
|     margin: @steps-icon-margin; | ||||
|     font-size: @steps-icon-font-size; | ||||
|     font-family: @font-family; | ||||
|     line-height: @steps-icon-size; | ||||
|     text-align: center; | ||||
|  | @ -74,9 +67,9 @@ | |||
|     border-radius: @steps-icon-size; | ||||
|     transition: background-color 0.3s, border-color 0.3s; | ||||
| 
 | ||||
|     > .@{steps-prefix-cls}-icon { | ||||
|     .@{steps-prefix-cls}-icon { | ||||
|       position: relative; | ||||
|       top: -1px; | ||||
|       top: @steps-icon-top; | ||||
|       color: @primary-color; | ||||
|       line-height: 1; | ||||
|     } | ||||
|  | @ -87,6 +80,7 @@ | |||
|     left: 0; | ||||
|     width: 100%; | ||||
|     padding: 0 10px; | ||||
| 
 | ||||
|     &::after { | ||||
|       display: inline-block; | ||||
|       width: 100%; | ||||
|  | @ -103,10 +97,11 @@ | |||
|     padding-right: 16px; | ||||
|     color: @text-color; | ||||
|     font-size: @font-size-lg; | ||||
|     line-height: @steps-icon-size; | ||||
|     line-height: @steps-title-line-height; | ||||
| 
 | ||||
|     &::after { | ||||
|       position: absolute; | ||||
|       top: (@steps-icon-size / 2); | ||||
|       top: (@steps-title-line-height / 2); | ||||
|       left: 100%; | ||||
|       display: block; | ||||
|       width: 9999px; | ||||
|  | @ -128,13 +123,13 @@ | |||
|   } | ||||
|   .step-item-status(wait); | ||||
|   .step-item-status(process); | ||||
|   &-process &-icon { | ||||
|   &-process > &-container > &-icon { | ||||
|     background: @process-icon-color; | ||||
|     > .@{steps-prefix-cls}-icon { | ||||
|     .@{steps-prefix-cls}-icon { | ||||
|       color: @process-icon-text-color; | ||||
|     } | ||||
|   } | ||||
|   &-process &-title { | ||||
|   &-process > &-container > &-title { | ||||
|     font-weight: 500; | ||||
|   } | ||||
|   .step-item-status(finish); | ||||
|  | @ -143,6 +138,10 @@ | |||
|   &.@{steps-prefix-cls}-next-error .@{steps-prefix-cls}-item-title::after { | ||||
|     background: @error-icon-color; | ||||
|   } | ||||
| 
 | ||||
|   &-disabled { | ||||
|     cursor: not-allowed; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // ===================== Clickable ===================== | ||||
|  | @ -153,6 +152,7 @@ | |||
| 
 | ||||
|       .@{steps-prefix-cls}-item { | ||||
|         &-title, | ||||
|         &-subtitle, | ||||
|         &-description, | ||||
|         &-icon .@{steps-prefix-cls}-icon { | ||||
|           transition: color 0.3s; | ||||
|  | @ -188,10 +188,11 @@ | |||
| 
 | ||||
| .@{steps-prefix-cls}-horizontal:not(.@{steps-prefix-cls}-label-vertical) { | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     margin-right: 16px; | ||||
|     padding-left: 16px; | ||||
|     white-space: nowrap; | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
| 
 | ||||
|     &:first-child { | ||||
|       padding-left: 0; | ||||
|     } | ||||
|     &:last-child .@{steps-prefix-cls}-item-title { | ||||
|       padding-right: 0; | ||||
|  | @ -200,7 +201,7 @@ | |||
|       display: none; | ||||
|     } | ||||
|     &-description { | ||||
|       max-width: @steps-desciption-max-width; | ||||
|       max-width: @steps-description-max-width; | ||||
|       white-space: normal; | ||||
|     } | ||||
|   } | ||||
|  | @ -235,10 +236,11 @@ | |||
|   } | ||||
| } | ||||
| 
 | ||||
| @import 'custom-icon'; | ||||
| @import 'small'; | ||||
| @import 'vertical'; | ||||
| @import 'label-placement'; | ||||
| @import 'progress-dot'; | ||||
| @import 'nav'; | ||||
| @import 'compatibility'; | ||||
| @import './custom-icon'; | ||||
| @import './small'; | ||||
| @import './vertical'; | ||||
| @import './label-placement'; | ||||
| @import './progress-dot'; | ||||
| @import './nav'; | ||||
| @import './rtl'; | ||||
| @import './progress.less'; | ||||
|  |  | |||
|  | @ -1,2 +0,0 @@ | |||
| import '../../style/index.less'; | ||||
| import './index.less'; | ||||
|  | @ -0,0 +1,6 @@ | |||
| import '../../style/index.less'; | ||||
| import './index.less'; | ||||
| 
 | ||||
| // style dependencies | ||||
| // deps-lint-skip: grid | ||||
| import '../../progress/style'; | ||||
|  | @ -17,6 +17,7 @@ | |||
|     } | ||||
|     &-title { | ||||
|       padding-right: 0; | ||||
|       padding-left: 0; | ||||
|       &::after { | ||||
|         display: none; | ||||
|       } | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ | |||
|       left: 50%; | ||||
|       display: inline-block; | ||||
|       width: 0; | ||||
|       height: 3px; | ||||
|       height: 2px; | ||||
|       background-color: @steps-nav-active-color; | ||||
|       transition: width 0.3s, left 0.3s; | ||||
|       transition-timing-function: ease-out; | ||||
|  | @ -90,35 +90,33 @@ | |||
|   } | ||||
| } | ||||
| 
 | ||||
| @media (max-width: @screen-xs) { | ||||
|   .@{steps-prefix-cls}-navigation { | ||||
|     > .@{steps-prefix-cls}-item { | ||||
|       margin-right: 0 !important; | ||||
|       &::before { | ||||
|         display: none; | ||||
|       } | ||||
|       &.@{steps-prefix-cls}-item-active::before { | ||||
|         top: 0; | ||||
|         right: 0; | ||||
|         left: unset; | ||||
|         display: block; | ||||
|         width: 3px; | ||||
|         height: calc(100% - 24px); | ||||
|       } | ||||
|       &::after { | ||||
|         position: relative; | ||||
|         top: -2px; | ||||
|         left: 50%; | ||||
|         display: block; | ||||
|         width: 8px; | ||||
|         height: 8px; | ||||
|         margin-bottom: 8px; | ||||
|         text-align: center; | ||||
|         transform: rotate(135deg); | ||||
|       } | ||||
|       > .@{steps-prefix-cls}-item-container > .@{steps-prefix-cls}-item-tail { | ||||
|         visibility: hidden; | ||||
|       } | ||||
| .@{steps-prefix-cls}-navigation.@{steps-prefix-cls}-vertical { | ||||
|   > .@{steps-prefix-cls}-item { | ||||
|     margin-right: 0 !important; | ||||
|     &::before { | ||||
|       display: none; | ||||
|     } | ||||
|     &.@{steps-prefix-cls}-item-active::before { | ||||
|       top: 0; | ||||
|       right: 0; | ||||
|       left: unset; | ||||
|       display: block; | ||||
|       width: 3px; | ||||
|       height: calc(100% - 24px); | ||||
|     } | ||||
|     &::after { | ||||
|       position: relative; | ||||
|       top: -2px; | ||||
|       left: 50%; | ||||
|       display: block; | ||||
|       width: 8px; | ||||
|       height: 8px; | ||||
|       margin-bottom: 8px; | ||||
|       text-align: center; | ||||
|       transform: rotate(135deg); | ||||
|     } | ||||
|     > .@{steps-prefix-cls}-item-container > .@{steps-prefix-cls}-item-tail { | ||||
|       visibility: hidden; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -5,10 +5,11 @@ | |||
|       line-height: @line-height-base; | ||||
|     } | ||||
|     &-tail { | ||||
|       top: 2px; | ||||
|       top: @steps-dot-top; | ||||
|       width: 100%; | ||||
|       margin: 0 0 0 (@steps-desciption-max-width / 2); | ||||
|       margin: 0 0 0 (@steps-description-max-width / 2); | ||||
|       padding: 0; | ||||
| 
 | ||||
|       &::after { | ||||
|         width: ~'calc(100% - 20px)'; | ||||
|         height: 3px; | ||||
|  | @ -26,6 +27,7 @@ | |||
|       line-height: @steps-dot-size; | ||||
|       background: transparent; | ||||
|       border: 0; | ||||
| 
 | ||||
|       .@{steps-prefix-cls}-icon-dot { | ||||
|         position: relative; | ||||
|         float: left; | ||||
|  | @ -46,14 +48,19 @@ | |||
|       } | ||||
|     } | ||||
|     &-content { | ||||
|       width: @steps-desciption-max-width; | ||||
|       width: @steps-description-max-width; | ||||
|     } | ||||
|     &-process .@{steps-prefix-cls}-item-icon { | ||||
|       position: relative; | ||||
|       top: -1px; | ||||
|       width: @steps-current-dot-size; | ||||
|       height: @steps-current-dot-size; | ||||
|       line-height: @steps-current-dot-size; | ||||
|       .@{steps-prefix-cls}-icon-dot { | ||||
|         top: -1px; | ||||
|       background: none; | ||||
|     } | ||||
|     &-process .@{steps-prefix-cls}-icon { | ||||
|       &:first-child .@{steps-prefix-cls}-icon-dot { | ||||
|         left: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | @ -63,6 +70,7 @@ | |||
|   .@{steps-prefix-cls}-item-icon { | ||||
|     margin-top: 8px; | ||||
|     margin-left: 0; | ||||
|     background: none; | ||||
|   } | ||||
|   // https://github.com/ant-design/ant-design/issues/18354 | ||||
|   .@{steps-prefix-cls}-item > .@{steps-prefix-cls}-item-container > .@{steps-prefix-cls}-item-tail { | ||||
|  | @ -74,7 +82,13 @@ | |||
|   .@{steps-prefix-cls}-item:first-child .@{steps-prefix-cls}-icon-dot { | ||||
|     left: 0; | ||||
|   } | ||||
|   .@{steps-prefix-cls}-item-process .@{steps-prefix-cls}-icon-dot { | ||||
|   .@{steps-prefix-cls}-item-content { | ||||
|     width: inherit; | ||||
|   } | ||||
|   .@{steps-prefix-cls}-item-process | ||||
|     .@{steps-prefix-cls}-item-container | ||||
|     .@{steps-prefix-cls}-item-icon | ||||
|     .@{steps-prefix-cls}-icon-dot { | ||||
|     left: -2px; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,28 @@ | |||
| @progress-prefix-cls: ~'@{ant-prefix}-progress'; | ||||
| 
 | ||||
| .@{steps-prefix-cls}-with-progress { | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     padding-top: 4px; | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-tail { | ||||
|       top: 4px !important; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &.@{steps-prefix-cls}-horizontal .@{steps-prefix-cls}-item:first-child { | ||||
|     padding-bottom: 4px; | ||||
|     padding-left: 4px; | ||||
|   } | ||||
| 
 | ||||
|   .@{steps-prefix-cls}-item-icon { | ||||
|     position: relative; | ||||
| 
 | ||||
|     .@{progress-prefix-cls} { | ||||
|       position: absolute; | ||||
|       top: -5px; | ||||
|       right: -5px; | ||||
|       bottom: -5px; | ||||
|       left: -5px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,251 @@ | |||
| .@{steps-prefix-cls} { | ||||
|   &-rtl { | ||||
|     direction: rtl; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .@{steps-prefix-cls}-item { | ||||
|   &-icon { | ||||
|     .@{steps-prefix-cls}.@{steps-prefix-cls}-rtl & { | ||||
|       margin-right: 0; | ||||
|       margin-left: 8px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-tail { | ||||
|     .@{steps-prefix-cls}-rtl & { | ||||
|       right: 0; | ||||
|       left: auto; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-title { | ||||
|     .@{steps-prefix-cls}-rtl & { | ||||
|       padding-right: 0; | ||||
|       padding-left: 16px; | ||||
|     } | ||||
| 
 | ||||
|     &::after { | ||||
|       .@{steps-prefix-cls}-rtl & { | ||||
|         right: 100%; | ||||
|         left: auto; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .@{steps-prefix-cls}-horizontal:not(.@{steps-prefix-cls}-label-vertical) { | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       padding-right: 16px; | ||||
|       padding-left: 0; | ||||
|     } | ||||
| 
 | ||||
|     &:first-child { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         padding-right: 0; | ||||
|       } | ||||
|     } | ||||
|     &:last-child .@{steps-prefix-cls}-item-title { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         padding-left: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // custom-icon | ||||
| .@{steps-prefix-cls}-item-custom { | ||||
|   .@{steps-prefix-cls}-item-icon { | ||||
|     > .@{steps-prefix-cls}-icon { | ||||
|       .@{steps-prefix-cls}-rtl & { | ||||
|         right: 0.5px; | ||||
|         left: auto; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // nav | ||||
| .@{steps-prefix-cls}-navigation { | ||||
|   &.@{steps-prefix-cls}-small { | ||||
|     .@{steps-prefix-cls}-item { | ||||
|       &-container { | ||||
|         .@{steps-prefix-cls}-rtl& { | ||||
|           margin-right: -12px; | ||||
|           margin-left: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     &-container { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         margin-right: -16px; | ||||
|         margin-left: 0; | ||||
|         text-align: right; | ||||
|       } | ||||
|       .@{steps-prefix-cls}-item-title { | ||||
|         .@{steps-prefix-cls}-rtl& { | ||||
|           padding-left: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &::after { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         right: 100%; | ||||
|         left: auto; | ||||
|         margin-right: -2px; | ||||
|         margin-left: 0; | ||||
|         transform: rotate(225deg); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // small | ||||
| .@{steps-prefix-cls}-small { | ||||
|   &.@{steps-prefix-cls}-horizontal:not(.@{steps-prefix-cls}-label-vertical) | ||||
|     .@{steps-prefix-cls}-item { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       padding-right: 12px; | ||||
|       padding-left: 0; | ||||
|     } | ||||
| 
 | ||||
|     &:first-child { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         padding-right: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .@{steps-prefix-cls}-item-title { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       padding-right: 0; | ||||
|       padding-left: 12px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // vertical | ||||
| .@{steps-prefix-cls}-vertical { | ||||
|   > .@{steps-prefix-cls}-item { | ||||
|     .@{steps-prefix-cls}-item-icon { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         float: right; | ||||
|         margin-right: 0; | ||||
|         margin-left: @steps-vertical-icon-width; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   > .@{steps-prefix-cls}-item | ||||
|     > .@{steps-prefix-cls}-item-container | ||||
|     > .@{steps-prefix-cls}-item-tail { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       right: @steps-vertical-tail-width; | ||||
|       left: auto; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &.@{steps-prefix-cls}-small .@{steps-prefix-cls}-item-container { | ||||
|     .@{steps-prefix-cls}-item-tail { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         right: @steps-vertical-tail-width-sm; | ||||
|         left: auto; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // label | ||||
| .@{steps-prefix-cls}-label-vertical { | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     &-title { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         padding-left: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // progress-dot | ||||
| .@{steps-prefix-cls}-dot, | ||||
| .@{steps-prefix-cls}-dot.@{steps-prefix-cls}-small { | ||||
|   .@{steps-prefix-cls}-item { | ||||
|     &-tail { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         margin: 0 (@steps-description-max-width / 2) 0 0; | ||||
|       } | ||||
| 
 | ||||
|       &::after { | ||||
|         .@{steps-prefix-cls}-rtl& { | ||||
|           margin-right: 12px; | ||||
|           margin-left: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     &:first-child .@{steps-prefix-cls}-icon-dot { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         right: 2px; | ||||
|         left: auto; | ||||
|       } | ||||
|     } | ||||
|     &-icon { | ||||
|       .@{steps-prefix-cls}-rtl& { | ||||
|         margin-right: 67px; | ||||
|         margin-left: 0; | ||||
|       } | ||||
| 
 | ||||
|       .@{steps-prefix-cls}-icon-dot { | ||||
|         .@{steps-prefix-cls}-rtl& { | ||||
|           float: right; | ||||
|         } | ||||
|         /* expand hover area */ | ||||
|         &::after { | ||||
|           .@{steps-prefix-cls}-rtl& { | ||||
|             right: -26px; | ||||
|             left: auto; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .@{steps-prefix-cls}-vertical.@{steps-prefix-cls}-dot { | ||||
|   .@{steps-prefix-cls}-item-icon { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       margin-right: 0; | ||||
|       margin-left: 16px; | ||||
|     } | ||||
|   } | ||||
|   // https://github.com/ant-design/ant-design/issues/18354 | ||||
|   .@{steps-prefix-cls}-item > .@{steps-prefix-cls}-item-container > .@{steps-prefix-cls}-item-tail { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       right: -9px; | ||||
|       left: auto; | ||||
|     } | ||||
|   } | ||||
|   .@{steps-prefix-cls}-item:first-child .@{steps-prefix-cls}-icon-dot { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       right: 0; | ||||
|       left: auto; | ||||
|     } | ||||
|   } | ||||
|   .@{steps-prefix-cls}-item-process .@{steps-prefix-cls}-icon-dot { | ||||
|     .@{steps-prefix-cls}-rtl& { | ||||
|       right: -2px; | ||||
|       left: auto; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // RTL Steps with progress | ||||
| .@{steps-prefix-cls}-rtl.@{steps-prefix-cls}-with-progress.@{steps-prefix-cls}-horizontal.@{steps-prefix-cls}-label-horizontal { | ||||
|   .@{steps-prefix-cls}-item:first-child.@{steps-prefix-cls}-item-active { | ||||
|     padding-right: 4px; | ||||
|   } | ||||
| } | ||||
|  | @ -1,14 +1,16 @@ | |||
| .@{steps-prefix-cls}-small { | ||||
|   &.@{steps-prefix-cls}-horizontal:not(.@{steps-prefix-cls}-label-vertical) | ||||
|     .@{steps-prefix-cls}-item { | ||||
|     margin-right: 12px; | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
|     padding-left: 12px; | ||||
| 
 | ||||
|     &:first-child { | ||||
|       padding-left: 0; | ||||
|     } | ||||
|   } | ||||
|   .@{steps-prefix-cls}-item-icon { | ||||
|     width: @steps-small-icon-size; | ||||
|     height: @steps-small-icon-size; | ||||
|     margin: @steps-small-icon-margin; | ||||
|     font-size: @font-size-sm; | ||||
|     line-height: @steps-small-icon-size; | ||||
|     text-align: center; | ||||
|  |  | |||
|  | @ -1,21 +1,29 @@ | |||
| .steps-vertical() { | ||||
|   display: block; | ||||
|   .@{steps-prefix-cls}-item { | ||||
| .@{steps-prefix-cls}-vertical { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
| 
 | ||||
|   > .@{steps-prefix-cls}-item { | ||||
|     display: block; | ||||
|     flex: 1 0 auto; | ||||
|     padding-left: 0; | ||||
|     overflow: visible; | ||||
|     &-icon { | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-icon { | ||||
|       float: left; | ||||
|       margin-right: 16px; | ||||
|       margin-right: @steps-vertical-icon-width; | ||||
|     } | ||||
|     &-content { | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-content { | ||||
|       display: block; | ||||
|       min-height: 48px; | ||||
|       overflow: hidden; | ||||
|     } | ||||
|     &-title { | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-title { | ||||
|       line-height: @steps-icon-size; | ||||
|     } | ||||
|     &-description { | ||||
| 
 | ||||
|     .@{steps-prefix-cls}-item-description { | ||||
|       padding-bottom: 12px; | ||||
|     } | ||||
|   } | ||||
|  | @ -25,10 +33,11 @@ | |||
|     > .@{steps-prefix-cls}-item-tail { | ||||
|     position: absolute; | ||||
|     top: 0; | ||||
|     left: 16px; | ||||
|     left: @steps-vertical-tail-width; | ||||
|     width: 1px; | ||||
|     height: 100%; | ||||
|     padding: @steps-icon-size + 6px 0 6px; | ||||
| 
 | ||||
|     &::after { | ||||
|       width: 1px; | ||||
|       height: 100%; | ||||
|  | @ -54,7 +63,7 @@ | |||
|     .@{steps-prefix-cls}-item-tail { | ||||
|       position: absolute; | ||||
|       top: 0; | ||||
|       left: 12px; | ||||
|       left: @steps-vertical-tail-width-sm; | ||||
|       padding: @steps-small-icon-size + 6px 0 6px; | ||||
|     } | ||||
|     .@{steps-prefix-cls}-item-title { | ||||
|  | @ -62,13 +71,3 @@ | |||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .@{steps-prefix-cls}-vertical { | ||||
|   .steps-vertical(); | ||||
| } | ||||
| 
 | ||||
| @media (max-width: @screen-xs) { | ||||
|   .@{steps-prefix-cls}-horizontal.@{steps-prefix-cls}-label-horizontal { | ||||
|     .steps-vertical(); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -887,8 +887,28 @@ | |||
| @image-preview-operation-disabled-color: fade(@image-preview-operation-color, 45%); | ||||
| 
 | ||||
| // Steps | ||||
| // --- | ||||
| @process-tail-color: @border-color-split; | ||||
| @steps-nav-arrow-color: fade(@black, 25%); | ||||
| @steps-background: @component-background; | ||||
| @steps-icon-size: 32px; | ||||
| @steps-icon-custom-size: @steps-icon-size; | ||||
| @steps-icon-custom-top: 0px; | ||||
| @steps-icon-custom-font-size: 24px; | ||||
| @steps-icon-top: -0.5px; | ||||
| @steps-icon-font-size: @font-size-lg; | ||||
| @steps-icon-margin: 0 8px 0 0; | ||||
| @steps-title-line-height: @height-base; | ||||
| @steps-small-icon-size: 24px; | ||||
| @steps-small-icon-margin: 0 8px 0 0; | ||||
| @steps-dot-size: 8px; | ||||
| @steps-dot-top: 2px; | ||||
| @steps-current-dot-size: 10px; | ||||
| @steps-description-max-width: 140px; | ||||
| @steps-nav-content-max-width: auto; | ||||
| @steps-vertical-icon-width: 16px; | ||||
| @steps-vertical-tail-width: 16px; | ||||
| @steps-vertical-tail-width-sm: 12px; | ||||
| 
 | ||||
| // Notification | ||||
| // --- | ||||
|  |  | |||
|  | @ -1,146 +0,0 @@ | |||
| import PropTypes, { withUndefined } from '../_util/vue-types'; | ||||
| import { getOptionProps, getComponent } from '../_util/props-util'; | ||||
| import BaseMixin from '../_util/BaseMixin'; | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| function isString(str) { | ||||
|   return typeof str === 'string'; | ||||
| } | ||||
| function noop() {} | ||||
| export default defineComponent({ | ||||
|   name: 'Step', | ||||
|   mixins: [BaseMixin], | ||||
|   props: { | ||||
|     prefixCls: PropTypes.string, | ||||
|     wrapperStyle: PropTypes.object, | ||||
|     itemWidth: PropTypes.string, | ||||
|     active: PropTypes.looseBool, | ||||
|     disabled: PropTypes.looseBool, | ||||
|     status: PropTypes.string, | ||||
|     iconPrefix: PropTypes.string, | ||||
|     icon: PropTypes.any, | ||||
|     adjustMarginRight: PropTypes.string, | ||||
|     stepNumber: PropTypes.string, | ||||
|     stepIndex: PropTypes.number, | ||||
|     description: PropTypes.any, | ||||
|     title: PropTypes.any, | ||||
|     subTitle: PropTypes.any, | ||||
|     progressDot: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func])), | ||||
|     tailContent: PropTypes.any, | ||||
|     icons: PropTypes.shape({ | ||||
|       finish: PropTypes.any, | ||||
|       error: PropTypes.any, | ||||
|     }).loose, | ||||
|     onClick: PropTypes.func, | ||||
|     onStepClick: PropTypes.func, | ||||
|   }, | ||||
|   methods: { | ||||
|     onItemClick(...args) { | ||||
|       this.__emit('click', ...args); | ||||
|       this.__emit('stepClick', this.stepIndex); | ||||
|     }, | ||||
|     renderIconNode() { | ||||
|       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, | ||||
|         [`${iconPrefix}icon`]: true, | ||||
|         [`${iconPrefix}icon-${icon}`]: icon && isString(icon), | ||||
|         [`${iconPrefix}icon-check`]: !icon && status === 'finish' && icons && !icons.finish, | ||||
|         [`${iconPrefix}icon-close`]: !icon && status === 'error' && icons && !icons.error, | ||||
|       }; | ||||
|       const iconDot = <span class={`${prefixCls}-icon-dot`} />; | ||||
|       // `progressDot` enjoy the highest priority | ||||
|       if (progressDot) { | ||||
|         if (typeof progressDot === 'function') { | ||||
|           iconNode = ( | ||||
|             <span class={`${prefixCls}-icon`}> | ||||
|               {progressDot({ index: stepNumber - 1, status, title, description, prefixCls })} | ||||
|             </span> | ||||
|           ); | ||||
|         } else { | ||||
|           iconNode = <span class={`${prefixCls}-icon`}>{iconDot}</span>; | ||||
|         } | ||||
|       } else if (icon && !isString(icon)) { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icon}</span>; | ||||
|       } else if (icons && icons.finish && status === 'finish') { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icons.finish}</span>; | ||||
|       } else if (icons && icons.error && status === 'error') { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icons.error}</span>; | ||||
|       } else if (icon || status === 'finish' || status === 'error') { | ||||
|         iconNode = <span class={iconClassName} />; | ||||
|       } else { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{stepNumber}</span>; | ||||
|       } | ||||
|       return iconNode; | ||||
|     }, | ||||
|   }, | ||||
|   render() { | ||||
|     const { | ||||
|       prefixCls, | ||||
|       itemWidth, | ||||
|       active, | ||||
|       status = 'wait', | ||||
|       tailContent, | ||||
|       adjustMarginRight, | ||||
|       disabled, | ||||
|       onClick, | ||||
|       onStepClick, | ||||
|     } = getOptionProps(this); | ||||
| 
 | ||||
|     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`]: getComponent(this, 'icon'), | ||||
|       [`${prefixCls}-item-active`]: active, | ||||
|       [`${prefixCls}-item-disabled`]: disabled === true, | ||||
|     }; | ||||
|     const stepProps = { | ||||
|       class: classString, | ||||
|     }; | ||||
|     const stepItemStyle = {}; | ||||
|     if (itemWidth) { | ||||
|       stepItemStyle.width = itemWidth; | ||||
|     } | ||||
|     if (adjustMarginRight) { | ||||
|       stepItemStyle.marginRight = adjustMarginRight; | ||||
|     } | ||||
| 
 | ||||
|     const accessibilityProps = { | ||||
|       onClick: onClick || noop, | ||||
|     }; | ||||
| 
 | ||||
|     if (onStepClick && !disabled) { | ||||
|       accessibilityProps.role = 'button'; | ||||
|       accessibilityProps.tabindex = 0; | ||||
|       accessibilityProps.onClick = this.onItemClick; | ||||
|     } | ||||
|     return ( | ||||
|       <div {...stepProps} style={stepItemStyle}> | ||||
|         <div {...accessibilityProps} class={`${prefixCls}-item-container`}> | ||||
|           <div class={`${prefixCls}-item-tail`}>{tailContent}</div> | ||||
|           <div class={`${prefixCls}-item-icon`}>{this.renderIconNode()}</div> | ||||
|           <div class={`${prefixCls}-item-content`}> | ||||
|             <div class={`${prefixCls}-item-title`}> | ||||
|               {title} | ||||
|               {subTitle && ( | ||||
|                 <div title={subTitle} class={`${prefixCls}-item-subtitle`}> | ||||
|                   {subTitle} | ||||
|                 </div> | ||||
|               )} | ||||
|             </div> | ||||
|             {description && <div class={`${prefixCls}-item-description`}>{description}</div>} | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     ); | ||||
|   }, | ||||
| }); | ||||
|  | @ -0,0 +1,177 @@ | |||
| import PropTypes, { withUndefined } from '../_util/vue-types'; | ||||
| import type { CSSProperties } from 'vue'; | ||||
| import { defineComponent } from 'vue'; | ||||
| import type { EventHandler } from '../_util/EventInterface'; | ||||
| 
 | ||||
| function isString(str: any): str is string { | ||||
|   return typeof str === 'string'; | ||||
| } | ||||
| function noop() {} | ||||
| export default defineComponent({ | ||||
|   name: 'Step', | ||||
|   props: { | ||||
|     prefixCls: PropTypes.string, | ||||
|     wrapperStyle: PropTypes.style, | ||||
|     itemWidth: PropTypes.string, | ||||
|     active: PropTypes.looseBool, | ||||
|     disabled: PropTypes.looseBool, | ||||
|     status: PropTypes.string, | ||||
|     iconPrefix: PropTypes.string, | ||||
|     icon: PropTypes.any, | ||||
|     adjustMarginRight: PropTypes.string, | ||||
|     stepNumber: PropTypes.number, | ||||
|     stepIndex: PropTypes.number, | ||||
|     description: PropTypes.any, | ||||
|     title: PropTypes.any, | ||||
|     subTitle: PropTypes.any, | ||||
|     progressDot: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func])), | ||||
|     tailContent: PropTypes.any, | ||||
|     icons: PropTypes.shape({ | ||||
|       finish: PropTypes.any, | ||||
|       error: PropTypes.any, | ||||
|     }).loose, | ||||
|     onClick: PropTypes.func, | ||||
|     onStepClick: PropTypes.func, | ||||
|     stepIcon: PropTypes.func, | ||||
|   }, | ||||
|   slots: ['title', 'subTitle', 'description', 'tailContent', 'stepIcon', 'progressDot'], | ||||
|   emits: ['click', 'stepClick'], | ||||
|   setup(props, { slots, emit }) { | ||||
|     const onItemClick: EventHandler = e => { | ||||
|       emit('click', e); | ||||
|       emit('stepClick', props.stepIndex); | ||||
|     }; | ||||
| 
 | ||||
|     const renderIconNode = ({ icon, title, description }) => { | ||||
|       const { | ||||
|         prefixCls, | ||||
|         stepNumber, | ||||
|         status, | ||||
|         iconPrefix, | ||||
|         icons, | ||||
|         progressDot = slots.progressDot, | ||||
|         stepIcon = slots.stepIcon, | ||||
|       } = props; | ||||
| 
 | ||||
|       let iconNode: any; | ||||
|       const iconClassName = { | ||||
|         [`${prefixCls}-icon`]: true, | ||||
|         [`${iconPrefix}icon`]: true, | ||||
|         [`${iconPrefix}icon-${icon}`]: icon && isString(icon), | ||||
|         [`${iconPrefix}icon-check`]: !icon && status === 'finish' && icons && !icons.finish, | ||||
|         [`${iconPrefix}icon-close`]: !icon && status === 'error' && icons && !icons.error, | ||||
|       }; | ||||
|       const iconDot = <span class={`${prefixCls}-icon-dot`} />; | ||||
|       // `progressDot` enjoy the highest priority | ||||
|       if (progressDot) { | ||||
|         if (typeof progressDot === 'function') { | ||||
|           iconNode = ( | ||||
|             <span class={`${prefixCls}-icon`}> | ||||
|               {progressDot({ | ||||
|                 iconDot, | ||||
|                 index: stepNumber - 1, | ||||
|                 status, | ||||
|                 title, | ||||
|                 description, | ||||
|                 prefixCls, | ||||
|               })} | ||||
|             </span> | ||||
|           ); | ||||
|         } else { | ||||
|           iconNode = <span class={`${prefixCls}-icon`}>{iconDot}</span>; | ||||
|         } | ||||
|       } else if (icon && !isString(icon)) { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icon}</span>; | ||||
|       } else if (icons && icons.finish && status === 'finish') { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icons.finish}</span>; | ||||
|       } else if (icons && icons.error && status === 'error') { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{icons.error}</span>; | ||||
|       } else if (icon || status === 'finish' || status === 'error') { | ||||
|         iconNode = <span class={iconClassName} />; | ||||
|       } else { | ||||
|         iconNode = <span class={`${prefixCls}-icon`}>{stepNumber}</span>; | ||||
|       } | ||||
| 
 | ||||
|       if (stepIcon) { | ||||
|         iconNode = stepIcon({ | ||||
|           index: stepNumber - 1, | ||||
|           status, | ||||
|           title, | ||||
|           description, | ||||
|           node: iconNode, | ||||
|         }); | ||||
|       } | ||||
|       return iconNode; | ||||
|     }; | ||||
|     return () => { | ||||
|       const { | ||||
|         prefixCls, | ||||
|         itemWidth, | ||||
|         active, | ||||
|         status = 'wait', | ||||
|         tailContent, | ||||
|         adjustMarginRight, | ||||
|         disabled, | ||||
|         title = slots.title?.(), | ||||
|         description = slots.description?.(), | ||||
|         subTitle = slots.subTitle?.(), | ||||
|         icon = slots.icon?.(), | ||||
|         onClick, | ||||
|         onStepClick, | ||||
|       } = props; | ||||
| 
 | ||||
|       const classString = { | ||||
|         [`${prefixCls}-item`]: true, | ||||
|         [`${prefixCls}-item-${status}`]: true, | ||||
|         [`${prefixCls}-item-custom`]: icon, | ||||
|         [`${prefixCls}-item-active`]: active, | ||||
|         [`${prefixCls}-item-disabled`]: disabled === true, | ||||
|       }; | ||||
|       const stepProps = { | ||||
|         class: classString, | ||||
|       }; | ||||
|       const stepItemStyle: CSSProperties = {}; | ||||
|       if (itemWidth) { | ||||
|         stepItemStyle.width = itemWidth; | ||||
|       } | ||||
|       if (adjustMarginRight) { | ||||
|         stepItemStyle.marginRight = adjustMarginRight; | ||||
|       } | ||||
| 
 | ||||
|       const accessibilityProps: { | ||||
|         role?: string; | ||||
|         tabindex?: number; | ||||
|         onClick?: EventHandler; | ||||
|       } = { | ||||
|         onClick: onClick || noop, | ||||
|       }; | ||||
| 
 | ||||
|       if (onStepClick && !disabled) { | ||||
|         accessibilityProps.role = 'button'; | ||||
|         accessibilityProps.tabindex = 0; | ||||
|         accessibilityProps.onClick = onItemClick; | ||||
|       } | ||||
|       return ( | ||||
|         <div {...stepProps} style={stepItemStyle}> | ||||
|           <div {...accessibilityProps} class={`${prefixCls}-item-container`}> | ||||
|             <div class={`${prefixCls}-item-tail`}>{tailContent}</div> | ||||
|             <div class={`${prefixCls}-item-icon`}> | ||||
|               {renderIconNode({ icon, title, description })} | ||||
|             </div> | ||||
|             <div class={`${prefixCls}-item-content`}> | ||||
|               <div class={`${prefixCls}-item-title`}> | ||||
|                 {title} | ||||
|                 {subTitle && ( | ||||
|                   <div title={subTitle} class={`${prefixCls}-item-subtitle`}> | ||||
|                     {subTitle} | ||||
|                   </div> | ||||
|                 )} | ||||
|               </div> | ||||
|               {description && <div class={`${prefixCls}-item-description`}>{description}</div>} | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       ); | ||||
|     }; | ||||
|   }, | ||||
| }); | ||||
|  | @ -1,170 +0,0 @@ | |||
| import PropTypes, { withUndefined } from '../_util/vue-types'; | ||||
| import BaseMixin from '../_util/BaseMixin'; | ||||
| import debounce from 'lodash-es/debounce'; | ||||
| import isFlexSupported from '../_util/isFlexSupported'; | ||||
| import { getSlot, getPropsData } from '../_util/props-util'; | ||||
| import { cloneElement } from '../_util/vnode'; | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'Steps', | ||||
|   mixins: [BaseMixin], | ||||
|   props: { | ||||
|     type: PropTypes.string.def('default'), | ||||
|     prefixCls: PropTypes.string.def('rc-steps'), | ||||
|     iconPrefix: PropTypes.string.def('rc'), | ||||
|     direction: PropTypes.string.def('horizontal'), | ||||
|     labelPlacement: PropTypes.string.def('horizontal'), | ||||
|     status: PropTypes.string.def('process'), | ||||
|     size: PropTypes.string.def(''), | ||||
|     progressDot: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func])), | ||||
|     initial: PropTypes.number.def(0), | ||||
|     current: PropTypes.number.def(0), | ||||
|     icons: PropTypes.shape({ | ||||
|       finish: PropTypes.any, | ||||
|       error: PropTypes.any, | ||||
|     }).loose, | ||||
|     canClick: PropTypes.looseBool, | ||||
|   }, | ||||
|   data() { | ||||
|     this.calcStepOffsetWidth = debounce(this.calcStepOffsetWidth, 150); | ||||
|     return { | ||||
|       flexSupported: true, | ||||
|       lastStepOffsetWidth: 0, | ||||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.calcStepOffsetWidth(); | ||||
|       if (!isFlexSupported()) { | ||||
|         this.setState({ | ||||
|           flexSupported: false, | ||||
|         }); | ||||
|       } | ||||
|     }); | ||||
|   }, | ||||
|   updated() { | ||||
|     this.$nextTick(() => { | ||||
|       this.calcStepOffsetWidth(); | ||||
|     }); | ||||
|   }, | ||||
|   beforeUnmount() { | ||||
|     if (this.calcTimeout) { | ||||
|       clearTimeout(this.calcTimeout); | ||||
|     } | ||||
|     if (this.calcStepOffsetWidth && this.calcStepOffsetWidth.cancel) { | ||||
|       this.calcStepOffsetWidth.cancel(); | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     onStepClick(next) { | ||||
|       const { current } = this.$props; | ||||
|       if (current !== next) { | ||||
|         this.__emit('change', next); | ||||
|       } | ||||
|     }, | ||||
|     calcStepOffsetWidth() { | ||||
|       if (isFlexSupported()) { | ||||
|         return; | ||||
|       } | ||||
|       const { lastStepOffsetWidth } = this.$data; | ||||
|       // Just for IE9 | ||||
|       const domNode = this.$refs.vcStepsRef; | ||||
|       if (domNode.children.length > 0) { | ||||
|         if (this.calcTimeout) { | ||||
|           clearTimeout(this.calcTimeout); | ||||
|         } | ||||
|         this.calcTimeout = setTimeout(() => { | ||||
|           // +1 for fit edge bug of digit width, like 35.4px | ||||
|           const offsetWidth = (domNode.lastChild.offsetWidth || 0) + 1; | ||||
|           // Reduce shake bug | ||||
|           if ( | ||||
|             lastStepOffsetWidth === offsetWidth || | ||||
|             Math.abs(lastStepOffsetWidth - offsetWidth) <= 3 | ||||
|           ) { | ||||
|             return; | ||||
|           } | ||||
|           this.setState({ lastStepOffsetWidth: offsetWidth }); | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   render() { | ||||
|     const { | ||||
|       prefixCls, | ||||
|       direction, | ||||
|       type, | ||||
|       labelPlacement, | ||||
|       iconPrefix, | ||||
|       status, | ||||
|       size, | ||||
|       current, | ||||
|       progressDot, | ||||
|       initial, | ||||
|       icons, | ||||
|       canClick, | ||||
|     } = this; | ||||
|     const isNav = type === 'navigation'; | ||||
|     const { lastStepOffsetWidth, flexSupported } = this; | ||||
|     const filteredChildren = getSlot(this); | ||||
|     const lastIndex = filteredChildren.length - 1; | ||||
|     const adjustedlabelPlacement = progressDot ? 'vertical' : labelPlacement; | ||||
|     const classString = { | ||||
|       [prefixCls]: true, | ||||
|       [`${prefixCls}-${direction}`]: true, | ||||
|       [`${prefixCls}-${size}`]: size, | ||||
|       [`${prefixCls}-label-${adjustedlabelPlacement}`]: direction === 'horizontal', | ||||
|       [`${prefixCls}-dot`]: !!progressDot, | ||||
|       [`${prefixCls}-navigation`]: isNav, | ||||
|       [`${prefixCls}-flex-not-supported`]: !flexSupported, | ||||
|     }; | ||||
|     const stepsProps = { | ||||
|       class: classString, | ||||
|       ref: 'vcStepsRef', | ||||
|     }; | ||||
|     return ( | ||||
|       <div {...stepsProps}> | ||||
|         {filteredChildren.map((child, index) => { | ||||
|           const childProps = getPropsData(child); | ||||
|           const stepNumber = initial + index; | ||||
|           const stepProps = { | ||||
|             stepNumber: `${stepNumber + 1}`, | ||||
|             stepIndex: stepNumber, | ||||
|             prefixCls, | ||||
|             iconPrefix, | ||||
|             progressDot, | ||||
|             icons, | ||||
|             ...childProps, | ||||
|           }; | ||||
|           if (canClick) { | ||||
|             stepProps.onStepClick = this.onStepClick; | ||||
|           } | ||||
|           if (!flexSupported && direction !== 'vertical') { | ||||
|             if (isNav) { | ||||
|               stepProps.itemWidth = `${100 / (lastIndex + 1)}%`; | ||||
|               stepProps.adjustMarginRight = 0; | ||||
|             } else if (index !== lastIndex) { | ||||
|               stepProps.itemWidth = `${100 / lastIndex}%`; | ||||
|               stepProps.adjustMarginRight = `${-Math.round(lastStepOffsetWidth / lastIndex + 1)}px`; | ||||
|             } | ||||
|           } | ||||
|           // fix tail color | ||||
|           if (status === 'error' && index === current - 1) { | ||||
|             stepProps.class = `${prefixCls}-next-error`; | ||||
|           } | ||||
|           if (!childProps.status) { | ||||
|             if (stepNumber === current) { | ||||
|               stepProps.status = status; | ||||
|             } else if (stepNumber < current) { | ||||
|               stepProps.status = 'finish'; | ||||
|             } else { | ||||
|               stepProps.status = 'wait'; | ||||
|             } | ||||
|           } | ||||
|           stepProps.active = stepNumber === current; | ||||
|           return cloneElement(child, stepProps); | ||||
|         })} | ||||
|       </div> | ||||
|     ); | ||||
|   }, | ||||
| }); | ||||
|  | @ -0,0 +1,122 @@ | |||
| import PropTypes from '../_util/vue-types'; | ||||
| import BaseMixin from '../_util/BaseMixin'; | ||||
| import { filterEmpty } from '../_util/props-util'; | ||||
| import { cloneElement } from '../_util/vnode'; | ||||
| import { defineComponent } from 'vue'; | ||||
| import classNames from '../_util/classNames'; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'Steps', | ||||
|   mixins: [BaseMixin], | ||||
|   props: { | ||||
|     type: PropTypes.string.def('default'), | ||||
|     prefixCls: PropTypes.string.def('vc-steps'), | ||||
|     iconPrefix: PropTypes.string.def('vc'), | ||||
|     direction: PropTypes.string.def('horizontal'), | ||||
|     labelPlacement: PropTypes.string.def('horizontal'), | ||||
|     status: PropTypes.string.def('process'), | ||||
|     size: PropTypes.string.def(''), | ||||
|     progressDot: PropTypes.oneOfType([PropTypes.looseBool, PropTypes.func]).def(false), | ||||
|     initial: PropTypes.number.def(0), | ||||
|     current: PropTypes.number.def(0), | ||||
|     icons: PropTypes.shape({ | ||||
|       finish: PropTypes.any, | ||||
|       error: PropTypes.any, | ||||
|     }).loose, | ||||
|     stepIcon: PropTypes.func, | ||||
|   }, | ||||
|   slots: ['stepIcon', 'progressDot'], | ||||
|   emits: ['change'], | ||||
|   setup(props, { slots, emit }) { | ||||
|     const onStepClick = next => { | ||||
|       const { current } = props; | ||||
|       if (current !== next) { | ||||
|         emit('change', next); | ||||
|       } | ||||
|     }; | ||||
|     return () => { | ||||
|       const { | ||||
|         prefixCls, | ||||
|         direction, | ||||
|         type, | ||||
|         labelPlacement, | ||||
|         iconPrefix, | ||||
|         status, | ||||
|         size, | ||||
|         current, | ||||
|         progressDot = slots.progressDot, | ||||
|         initial, | ||||
|         icons, | ||||
|         stepIcon = slots.stepIcon, | ||||
|       } = props; | ||||
|       const isNav = type === 'navigation'; | ||||
|       const adjustedLabelPlacement = progressDot ? 'vertical' : labelPlacement; | ||||
|       const classString = classNames(prefixCls, `${prefixCls}-${direction}`, { | ||||
|         [`${prefixCls}-${size}`]: size, | ||||
|         [`${prefixCls}-label-${adjustedLabelPlacement}`]: direction === 'horizontal', | ||||
|         [`${prefixCls}-dot`]: !!progressDot, | ||||
|         [`${prefixCls}-navigation`]: isNav, | ||||
|       }); | ||||
|       const children = filterEmpty(slots.default?.()); | ||||
|       return ( | ||||
|         <div class={classString}> | ||||
|           {children.map((child, index) => { | ||||
|             // description: PropTypes.any, | ||||
|             // icon: PropTypes.any, | ||||
|             // status: PropTypes.oneOf(tuple('wait', 'process', 'finish', 'error')), | ||||
|             // disabled: PropTypes.looseBool, | ||||
|             // title: PropTypes.any, | ||||
|             // subTitle: PropTypes.any, | ||||
|             const { prefixCls: pre = prefixCls, ...restProps } = child.props || {}; | ||||
|             const stepNumber = initial + index; | ||||
|             const stepProps = { | ||||
|               ...restProps, | ||||
|               stepNumber: stepNumber + 1, | ||||
|               stepIndex: stepNumber, | ||||
|               key: stepNumber, | ||||
|               prefixCls: pre, | ||||
|               iconPrefix, | ||||
|               progressDot, | ||||
|               icons, | ||||
|               stepIcon, | ||||
|               onStepClick, | ||||
|             }; | ||||
| 
 | ||||
|             // 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'; | ||||
|               } | ||||
|             } | ||||
|             stepProps.active = stepNumber === current; | ||||
|             return cloneElement(child, stepProps); | ||||
|           })} | ||||
|         </div> | ||||
|       ); | ||||
|     }; | ||||
|   }, | ||||
| }); | ||||
|  | @ -124,7 +124,7 @@ module.exports = { | |||
|       'ant-design-vue': path.join(__dirname, './components'), | ||||
|       vue$: 'vue/dist/vue.runtime.esm-bundler.js', | ||||
|     }, | ||||
|     extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.md'], | ||||
|     extensions: ['.ts', '.tsx', '.js', '.jsx', '.vue', '.md'], | ||||
|   }, | ||||
|   devServer: { | ||||
|     historyApiFallback: { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou