diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index d8fcfdec..c6050819 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -235,7 +235,7 @@ export default { { title: 'Steps 步骤条', name: 'steps', - component: () => import('tdesign-mobile-react/steps/_example/index.jsx'), + component: () => import('tdesign-mobile-react/steps/_example/index.tsx'), }, { title: 'TabBar 标签栏', diff --git a/src/_common b/src/_common index f9683c1e..94849276 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit f9683c1edee5c09f455ba8cb19cb8ce07d4490be +Subproject commit 9484927641224d03788ee3298fc6b563f8adc637 diff --git a/src/steps/StepItem.tsx b/src/steps/StepItem.tsx index 2947854d..b740fd39 100644 --- a/src/steps/StepItem.tsx +++ b/src/steps/StepItem.tsx @@ -1,11 +1,13 @@ -import React, { FC, useContext, useMemo } from 'react'; -import classnames from 'classnames'; +import React, { FC, useContext, useEffect, useMemo, useRef, MouseEvent } from 'react'; +import classNames from 'classnames'; import { Icon } from 'tdesign-icons-react'; import withNativeProps, { NativeProps } from '../_util/withNativeProps'; +import parseTNode from '../_util/parseTNode'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePrefixClass } from '../hooks/useClass'; import { TdStepItemProps } from './type'; -import useConfig from '../_util/useConfig'; import { stepItemDefaultProps } from './defaultProps'; -import StepsContext from './StepsContext'; +import { StepsContext } from './StepsContext'; export enum StepItemStatusEnum { DEFAULT = 'default', @@ -19,106 +21,165 @@ export enum StepThemeEnum { DOT = 'dot', } -export enum StepLayoutEnum { - VERTICAL = 'vertical', - HORIZONTAL = 'horizontal', -} - -export interface StepItemProps extends TdStepItemProps, NativeProps { - index: number; -} +export interface StepItemProps extends TdStepItemProps, NativeProps {} const StepItem: FC = (props) => { - const { title, content, icon, status, index, children } = props; - - const { value, readonly, theme, layout, onChange } = useContext(StepsContext); + const { title, content, icon, status, children, titleRight, extra } = useDefaultProps(props, stepItemDefaultProps); + + const stepItemClass = usePrefixClass('step-item'); + const stepItemRef = useRef(null); + + const { + childrenNodes, + current, + relation, + removeRelation, + onClickItem, + currentStatus: stepsStatus, + layout, + readonly, + theme, + sequence, + } = useContext(StepsContext); + + useEffect(() => { + relation(stepItemRef.current); + const stepItemCur = stepItemRef.current; + return () => { + removeRelation(stepItemCur); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const index = useMemo(() => childrenNodes.indexOf(stepItemRef.current), [childrenNodes]); + const isLastChild = useMemo( + () => index === (sequence === 'positive' ? childrenNodes.length - 1 : 0), + [index, sequence, childrenNodes], + ); - const { classPrefix } = useConfig(); + const dot = useMemo(() => theme === StepThemeEnum.DOT, [theme]); + const currentStatus = useMemo(() => { + if (status !== 'default') return status; + if (index === current) return stepsStatus; + if (index < +current) return 'finish'; + return status; + }, [index, current, stepsStatus, status]); + + const rootClassName = useMemo( + () => + classNames(stepItemClass, `${stepItemClass}--${layout}`, { + [`${stepItemClass}--default`]: readonly, + [`${stepItemClass}--${currentStatus}`]: currentStatus, + }), + [stepItemClass, layout, readonly, currentStatus], + ); - const name = `${classPrefix}-step`; + const iconWrapperClassName = useMemo( + () => classNames(`${stepItemClass}__anchor`, `${stepItemClass}__anchor--${layout}`), + [stepItemClass, layout], + ); + const dotClassName = useMemo( + () => classNames(`${stepItemClass}__dot`, `${stepItemClass}__dot--${currentStatus}`), + [stepItemClass, currentStatus], + ); + const iconClassName = useMemo( + () => + classNames({ + [`${stepItemClass}__icon`]: icon, + [`${stepItemClass}__icon--${currentStatus}`]: icon, + [`${stepItemClass}__circle`]: !icon, + [`${stepItemClass}__circle--${currentStatus}`]: !icon, + }), + [stepItemClass, currentStatus, icon], + ); + const contentClassName = useMemo( + () => + classNames(`${stepItemClass}__content`, `${stepItemClass}__content--${layout}`, { + [`${stepItemClass}__content--last`]: isLastChild, + }), + [stepItemClass, layout, isLastChild], + ); - const dot = useMemo(() => theme === StepThemeEnum.DOT && layout === StepLayoutEnum.VERTICAL, [theme, layout]); + const titleClassName = useMemo( + () => + classNames( + `${stepItemClass}__title`, + `${stepItemClass}__title--${currentStatus}`, + `${stepItemClass}__title--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const descriptionClassName = useMemo( + () => + classNames( + `${stepItemClass}__description`, + `${stepItemClass}__description--${currentStatus}`, + `${stepItemClass}__description--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const extraClassName = useMemo( + () => + classNames( + `${stepItemClass}__extra`, + `${stepItemClass}__extra--${currentStatus}`, + `${stepItemClass}__extra--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const separatorClassName = useMemo( + () => + classNames( + `${stepItemClass}__line`, + `${stepItemClass}__line--${currentStatus}`, + `${stepItemClass}__line--${sequence}`, + `${stepItemClass}__line--${layout}`, + `${stepItemClass}__line--${theme}`, + ), + [stepItemClass, currentStatus, layout, sequence, theme], + ); - const onStepClick = (e) => { - if (readonly || dot) return; - const currentValue = index; - onChange(currentValue, value, { e }); + const onStepClick = (e: MouseEvent) => { + if (readonly) return; + onClickItem(index, current, { e }); }; - const innerClassName = useMemo(() => { - if (typeof icon === 'boolean') { - return `${name}__inner`; - } - return classnames(`${name}__inner`, `${name}__inner__icon`); - }, [name, icon]); - const iconContent = useMemo(() => { - if (dot) { - return ''; - } - - if (status === StepItemStatusEnum.ERROR) { - return ; - } - - if (index < value && readonly) { - return ; + if (icon) { + return parseTNode(icon); } - - if (typeof icon === 'boolean') { - return index + 1; + const iconDefault = { + check: , + close: , + }; + if (currentStatus === StepItemStatusEnum.ERROR) { + return iconDefault.close; } - - if (typeof icon === 'string') { - return ; + if (currentStatus === StepItemStatusEnum.FINISH) { + return iconDefault.check; } - - return icon; - }, [status, index, value, readonly, icon, dot]); - - const currentStatus = useMemo(() => { - if (status !== StepItemStatusEnum.DEFAULT) { - return status; - } - if (+value === index) { - return StepItemStatusEnum.PROCESS; - } - if (+value > index) { - return StepItemStatusEnum.FINISH; - } - return ''; - }, [value, index, status]); + return index + 1; + }, [icon, currentStatus, index]); return withNativeProps( props, -
-
-
-
- {iconContent} -
-
-
-
{title}
-
{content || children}
-
+
+
+ {dot ?
:
{iconContent}
} +
+
+
+ {parseTNode(title)} + {layout === 'vertical' && parseTNode(titleRight)}
+
{parseTNode(content) || parseTNode(children)}
+
{parseTNode(extra)}
+ {!isLastChild &&
}
, ); }; StepItem.displayName = 'StepItem'; -StepItem.defaultProps = stepItemDefaultProps; export default StepItem; diff --git a/src/steps/Steps.tsx b/src/steps/Steps.tsx index 9d38aa46..a413a313 100644 --- a/src/steps/Steps.tsx +++ b/src/steps/Steps.tsx @@ -1,12 +1,13 @@ -import React, { FC, useMemo } from 'react'; -import classnames from 'classnames'; +import React, { FC, useCallback, useMemo, useState } from 'react'; +import classNames from 'classnames'; import withNativeProps, { NativeProps } from '../_util/withNativeProps'; import useDefault from '../_util/useDefault'; +import parseTNode from '../_util/parseTNode'; +import { usePrefixClass } from '../hooks/useClass'; +import useDefaultProps from '../hooks/useDefaultProps'; import { TdStepsProps } from './type'; -import useConfig from '../_util/useConfig'; import { stepsDefaultProps } from './defaultProps'; -import StepsContext from './StepsContext'; -import StepItem from './StepItem'; +import { StepsProvider } from './StepsContext'; export interface StepsProps extends TdStepsProps, NativeProps {} @@ -16,51 +17,66 @@ const Steps: FC = (props) => { layout, readonly, theme, - separator, current, defaultCurrent, + sequence, + currentStatus, onChange: onCurrentChange, - options, - } = props; + } = useDefaultProps(props, stepsDefaultProps); - const { classPrefix } = useConfig(); - - const name = `${classPrefix}-steps`; + const stepsClass = usePrefixClass('steps'); const [value, onChange] = useDefault(current, defaultCurrent, onCurrentChange); - const stepItemList = useMemo(() => { - if (options) { - return options.map((item, index: number) => ); - } - return React.Children.map(children, (child: JSX.Element, index: number) => - React.cloneElement(child, { - index, + const [childrenNodes, setChildrenNodes] = useState([]); + + const stepsClassName = useMemo( + () => + classNames(stepsClass, `${stepsClass}--${layout}`, `${stepsClass}--${sequence}`, { + [`${stepsClass}--readonly`]: readonly, }), - ); - }, [children, options]); + [stepsClass, layout, sequence, readonly], + ); + + const relation = useCallback((ele: HTMLElement) => { + ele && setChildrenNodes((prev) => [...prev, ele]); + }, []); + + const removeRelation = useCallback((ele: HTMLElement) => { + setChildrenNodes((prev) => prev.filter((item) => item !== ele)); + }, []); + + const onClickItem = useCallback( + (cur, prev, context) => { + onChange(cur, prev, context); + }, + [onChange], + ); + + const memoProviderValues = useMemo( + () => ({ + childrenNodes, + current: value, + relation, + removeRelation, + onClickItem, + currentStatus, + layout, + readonly, + theme, + sequence, + }), + [childrenNodes, value, relation, removeRelation, onClickItem, currentStatus, layout, readonly, theme, sequence], + ); return withNativeProps( props, - -
- {stepItemList} -
-
, + +
{parseTNode(children)}
+
, ); }; Steps.displayName = 'Steps'; -Steps.defaultProps = stepsDefaultProps; export default Steps; diff --git a/src/steps/StepsContext.ts b/src/steps/StepsContext.ts deleted file mode 100644 index d1f13485..00000000 --- a/src/steps/StepsContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -import React, { MouseEvent } from 'react'; - -interface StepsContextProps { - value: string | number; - readonly: boolean; - theme: 'default' | 'dot'; - layout: 'horizontal' | 'vertical'; - onChange: (current: string | number, previous: string | number, context?: { e?: MouseEvent }) => void; -} - -const StepsContext = React.createContext({ - value: 0, - readonly: false, - onChange: null, - theme: 'default', - layout: 'horizontal', -}); - -export default StepsContext; diff --git a/src/steps/StepsContext.tsx b/src/steps/StepsContext.tsx new file mode 100644 index 00000000..c01aecfc --- /dev/null +++ b/src/steps/StepsContext.tsx @@ -0,0 +1,22 @@ +import React, { createContext, useMemo } from 'react'; +import { TdStepsProps } from './type'; + +interface StepsContextProps { + childrenNodes: HTMLElement[]; + current: TdStepsProps['current']; + relation: (ele: HTMLElement) => void; + removeRelation: (ele: HTMLElement) => void; + onClickItem: TdStepsProps['onChange']; + sequence: TdStepsProps['sequence']; + currentStatus: TdStepsProps['currentStatus']; + readonly: boolean; + theme: TdStepsProps['theme']; + layout: TdStepsProps['layout']; +} + +export const StepsContext = createContext(null); + +export function StepsProvider({ value, children }) { + const memoValue = useMemo(() => value, [value]); + return {children}; +} diff --git a/src/steps/__tests__/__snapshots__/demo.test.tsx.snap b/src/steps/__tests__/__snapshots__/demo.test.tsx.snap new file mode 100644 index 00000000..c62163a3 --- /dev/null +++ b/src/steps/__tests__/__snapshots__/demo.test.tsx.snap @@ -0,0 +1,1872 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Steps > Steps horizontalDemo demo 1`] = ` +
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps specialDemo demo 1`] = ` +
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps statusDemo demo 1`] = ` +
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps verticalDemo demo 1`] = ` +
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+`; diff --git a/src/steps/__tests__/demo.test.tsx b/src/steps/__tests__/demo.test.tsx new file mode 100644 index 00000000..426e1a58 --- /dev/null +++ b/src/steps/__tests__/demo.test.tsx @@ -0,0 +1,24 @@ +import { describe, expect, render, it } from '@test/utils'; +import React from 'react'; + +import horizontalDemo from '../_example/horizontal'; +import verticalDemo from '../_example/vertical'; +import statusDemo from '../_example/status'; +import specialDemo from '../_example/special'; + +const mapper = { + horizontalDemo, + verticalDemo, + statusDemo, + specialDemo, +}; + +describe('Steps', () => { + Object.keys(mapper).forEach((item) => { + it(`Steps ${item} demo`, () => { + const DemoComponent = mapper[item]; + const { container } = render(); + expect(container.firstChild).toMatchSnapshot(); + }); + }); +}); diff --git a/src/steps/__tests__/index.test.tsx b/src/steps/__tests__/index.test.tsx new file mode 100644 index 00000000..fc7ca631 --- /dev/null +++ b/src/steps/__tests__/index.test.tsx @@ -0,0 +1,270 @@ +import React from 'react'; +import { describe, expect, it, render, fireEvent, vi } from '@test/utils'; +import { Icon } from 'tdesign-icons-react'; +import { Steps, StepItem, StepStatus } from '../index'; +import { Image } from '../../image'; + +const prefix = 't'; +const steps = `${prefix}-steps`; +const stepItem = `${prefix}-step-item`; + +const items = [ + { + title: '步骤描述1', + content: '辅助信息文字最多两行1', + }, + { + title: '步骤描述2', + content: '辅助信息文字最多两行2', + }, + { + title: '步骤描述3', + content: '辅助信息文字最多两行3', + }, +]; +const itemStatus = [ + { + title: '步骤描述1', + content: '辅助信息文字最多两行1', + status: 'error', + }, + { + title: '步骤描述2', + content: '辅助信息文字最多两行2', + status: 'process', + }, +]; + +describe('Steps', () => { + describe('props', () => { + it('layout & theme', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + expect(container.querySelector(`.${steps}`).classList.contains(`${steps}--vertical`)).toBeTruthy(); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + expect($stepItems.length).toEqual(items.length); + $stepItems.forEach((item, index) => { + expect(item.querySelector(`.${stepItem}__dot`)).toBeTruthy(); + if (index === $stepItems.length - 1) { + expect(item.querySelector(`.${stepItem}__line`)).toBeNull(); + } else { + expect(item.querySelector(`.${stepItem}__line`)).toBeTruthy(); + } + }); + }); + + it('readonly', () => { + const onClick = vi.fn(); + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + fireEvent.click($stepItems[1]); + expect(onClick).toHaveBeenCalledTimes(0); + }); + + it('currentStatus', () => { + const current = 1; + const { container } = render( + + {items.map((item, index) => ( + } /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + const getStatus = (index) => { + if (index < current) { + return 'finish'; + } + if (index === current) { + return 'error'; + } + return 'default'; + }; + $stepItems.forEach((item, index) => { + expect(item.classList.contains(`${stepItem}--${getStatus(index)}`)); + }); + }); + + it('sequence', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item, index) => { + if (index === 0) { + expect(item.querySelector(`.${stepItem}__line`)).toBeNull(); + } else { + expect(item.querySelector(`.${stepItem}__line`)).toBeTruthy(); + } + }); + }); + + it('change steps', () => { + const stepItems = [...items]; + const { container, rerender } = render( + + {stepItems.map((item, index) => ( + + ))} + , + ); + stepItems.pop(); + rerender( + + {stepItems.map((item, index) => ( + + ))} + , + ); + expect(container.querySelectorAll(`.${stepItem}`).length).toEqual(stepItems.length); + }); + }); + + describe('events', () => { + it('onChange', () => { + const onClick = vi.fn(); + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + fireEvent.click($stepItems[1]); + expect(onClick).toHaveBeenCalledTimes(1); + expect(onClick).toHaveBeenCalledWith( + 1, + 0, + expect.objectContaining({ + e: expect.objectContaining({ + type: 'click', + }), + }), + ); + }); + }); +}); + +describe('StepItem', () => { + describe('props', () => { + it('title and content', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + + $stepItems.forEach((item, index) => { + expect(item.querySelector(`.${stepItem}__title`).textContent).toBe(items[index].title); + expect(item.querySelector(`.${stepItem}__description`).textContent).toBe(items[index].content); + }); + }); + + it('icon', () => { + const { container } = render( + + {items.map((item, index) => ( + } /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item) => { + expect(item.querySelector(`.${stepItem}__icon`)).toBeTruthy(); + expect(item.querySelector(`.${prefix}-icon-cart`)).toBeTruthy(); + }); + }); + + it('extra', () => { + const { container } = render( + + {items.map((item, index) => ( + + ) + } + /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + const $extra = $stepItems[1].querySelector(`.${stepItem}__extra`); + expect($extra).toBeTruthy(); + expect($extra.querySelector('img')).toBeTruthy(); + }); + + it('status', () => { + const current = 1; + const { container } = render( + + {itemStatus.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item, index) => { + expect(item.classList.contains(`${stepItem}--${itemStatus[index].status}`)); + }); + }); + + it('titleRight', () => { + const { container } = render( + + {items.map((item, index) => ( + } + /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item) => { + expect(item.querySelector(`.${prefix}-icon.${prefix}-icon-chevron-right`)).toBeTruthy(); + }); + const { container: container2 } = render( + + {items.map((item, index) => ( + } + /> + ))} + , + ); + const $stepItems2 = container2.querySelectorAll(`.${stepItem}`); + $stepItems2.forEach((item) => { + expect(item.querySelector(`.${prefix}-icon`)).toBeNull(); + }); + }); + }); +}); diff --git a/src/steps/_example/click.jsx b/src/steps/_example/click.jsx deleted file mode 100644 index 403b33ac..00000000 --- a/src/steps/_example/click.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Click() { - const [current1, setCurrent1] = useState(1); - const [current2] = useState(1); - const [current3] = useState(1); - const stepItemList = [ - { - title: '步骤描述', - content: '辅助信息文字最多两行', - }, - { - title: '步骤描述', - content: '辅助信息文字最多两行', - }, - ]; - return ( - <> - { - setCurrent1(value); - }} - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/src/steps/_example/content.jsx b/src/steps/_example/content.jsx deleted file mode 100644 index ea1733ae..00000000 --- a/src/steps/_example/content.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Content() { - const [current] = useState(1); - return ( - <> - - - 可自定义此处内容,可自定义此处内容,可自定义此处内容可自定义此处内容可自定义此处内容。 - -
- } - /> - - - - - ); -} diff --git a/src/steps/_example/horizontal.jsx b/src/steps/_example/horizontal.jsx deleted file mode 100644 index 1760f7c2..00000000 --- a/src/steps/_example/horizontal.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Horizontal() { - return ( - <> -
- - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - -
- - ); -} diff --git a/src/steps/_example/horizontal.tsx b/src/steps/_example/horizontal.tsx new file mode 100644 index 00000000..03f97cca --- /dev/null +++ b/src/steps/_example/horizontal.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { Steps, StepItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const options = { + first, + second, + third, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
水平带序号步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
水平带图标步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
水平简略步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ ); +} diff --git a/src/steps/_example/icon.jsx b/src/steps/_example/icon.jsx deleted file mode 100644 index b1361754..00000000 --- a/src/steps/_example/icon.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; -import { UserIcon, LocationIcon, TimeIcon } from 'tdesign-icons-react' - -export default function Icon() { - const [current, setCurrent] = useState(1); - return ( - <> - { - setCurrent(value); - }} - > - - - - } - /> - - - - } - /> - - - - } - /> - - { - setCurrent(value); - }} - > - - - - } - /> - - - - } - /> - - - - } - /> - - - ); -} diff --git a/src/steps/_example/index.jsx b/src/steps/_example/index.jsx deleted file mode 100644 index 8cff8ef1..00000000 --- a/src/steps/_example/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; -import TDemoHeader from '../../../site/mobile/components/DemoHeader'; -import Click from './click'; -import Icon from './icon'; -import Horizontal from './horizontal'; -import Content from './content'; - -import './style/index.less'; -import Vertical from './vertical'; -import VerticalReadonly from './vertical-readonly'; - -export default function StepsDemo() { - return ( -
- - -
- -
-
- -
- -
-
- - - - -
- -
-
- -
- -
-
- -
- -
-
-
- ); -} diff --git a/src/steps/_example/index.tsx b/src/steps/_example/index.tsx new file mode 100644 index 00000000..13172208 --- /dev/null +++ b/src/steps/_example/index.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import TDemoBlock from '../../../site/mobile/components/DemoBlock'; +import TDemoHeader from '../../../site/mobile/components/DemoHeader'; +import Horizontal from './horizontal'; + +import './style/index.less'; +import Vertical from './vertical'; +import Status from './status'; +import Special from './special'; + +export default function StepsDemo() { + return ( +
+ + + + + + + + + + + +
+ ); +} diff --git a/src/steps/_example/special.tsx b/src/steps/_example/special.tsx new file mode 100644 index 00000000..45b8d94d --- /dev/null +++ b/src/steps/_example/special.tsx @@ -0,0 +1,72 @@ +import React, { useState } from 'react'; +import { Steps, StepItem, Button } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(3); + const [second, setSecond] = useState(4); + const options = { + first, + second, + }; + + const [count1, setCount1] = useState(4); + const count = 4; + const onFirstChange = (current: number) => { + setCount1(current + 1); + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + + const toNext = () => { + setCount1((prev) => prev + 1); + setFirst(count1); + }; + + const getTitle = (type: 'first' | 'second', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
垂直自定义步骤条
+
+ + {Array.from({ length: count1 }).map((_, index) => ( + } + /> + ))} + + +
+
纯展示步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
+ ); +} diff --git a/src/steps/_example/status.tsx b/src/steps/_example/status.tsx new file mode 100644 index 00000000..786ae9ce --- /dev/null +++ b/src/steps/_example/status.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import { Steps, StepItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const options = { + first, + second, + third, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
选项卡状态
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ ); +} diff --git a/src/steps/_example/style/index.less b/src/steps/_example/style/index.less index d9b5deba..e8c56380 100644 --- a/src/steps/_example/style/index.less +++ b/src/steps/_example/style/index.less @@ -1,17 +1,10 @@ -.tdesign-mobile-block { - background-color: #ffffff; - padding: 40px 12px; - - & + & { - margin-top: 12px; - } - - .t-steps:not(:last-child) { - margin-bottom: 40px; - } - - &-icon { - width: 24px; - height: 24px; - } +.steps-horizontal-demo-block { + margin: 16px 0 24px; + padding: 16px 0; + background-color: var(--bg-color-demo, #fff); +} +.steps-vertical-demo-block { + margin: 16px 0 24px; + padding: 16px; + background-color: var(--bg-color-demo, #fff); } diff --git a/src/steps/_example/vertical-readonly.jsx b/src/steps/_example/vertical-readonly.jsx deleted file mode 100644 index 988236e9..00000000 --- a/src/steps/_example/vertical-readonly.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Vertical() { - const [current] = useState(1); - return ( - <> - - - - - - - - - - - - ); -} diff --git a/src/steps/_example/vertical.jsx b/src/steps/_example/vertical.jsx deleted file mode 100644 index 2c343cbd..00000000 --- a/src/steps/_example/vertical.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Vertical() { - const [current] = useState(1); - // 竖向简化只读步骤条 - return ( - - - - - - ); -} diff --git a/src/steps/_example/vertical.tsx b/src/steps/_example/vertical.tsx new file mode 100644 index 00000000..29cc1ac8 --- /dev/null +++ b/src/steps/_example/vertical.tsx @@ -0,0 +1,93 @@ +import React, { useState } from 'react'; +import { Steps, StepItem, Image } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const [four, setFour] = useState(1); + const options = { + first, + second, + third, + four, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + const onFourChange = (current: number) => { + setFour(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third' | 'four', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成步骤'; + } + }; + + return ( +
+
垂直带序号步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
垂直带图标步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
垂直简略步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
垂直带可自定义此处内容步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ) + } + /> + ))} + +
+
+ ); +} diff --git a/src/steps/defaultProps.ts b/src/steps/defaultProps.ts index 05ab6502..f4e602a9 100644 --- a/src/steps/defaultProps.ts +++ b/src/steps/defaultProps.ts @@ -5,10 +5,11 @@ import { TdStepsProps, TdStepItemProps } from './type'; export const stepsDefaultProps: TdStepsProps = { + currentStatus: 'process', layout: 'horizontal', readonly: false, - separator: 'line', + sequence: 'positive', theme: 'default', }; -export const stepItemDefaultProps: TdStepItemProps = { icon: true, status: 'default' }; +export const stepItemDefaultProps: TdStepItemProps = { content: '', status: 'default', title: '', titleRight: '' }; diff --git a/src/steps/index.tsx b/src/steps/index.tsx index 797cd5dd..b3df6df6 100644 --- a/src/steps/index.tsx +++ b/src/steps/index.tsx @@ -9,5 +9,6 @@ export * from './type'; export const Steps = _Steps; (Steps as any).StepItem = _StepItem; +export const StepItem = _StepItem; export default Steps; diff --git a/src/steps/steps.en-US.md b/src/steps/steps.en-US.md new file mode 100644 index 00000000..c2a24394 --- /dev/null +++ b/src/steps/steps.en-US.md @@ -0,0 +1,33 @@ +:: BASE_DOC :: + +## API + +### Steps Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +current | String / Number | - | \- | N +defaultCurrent | String / Number | - | uncontrolled property | N +currentStatus | String | process | options: default/process/finish/error | N +layout | String | horizontal | options: horizontal/vertical | N +readonly | Boolean | false | \- | N +sequence | String | positive | options: positive/reverse | N +theme | String | default | options: default/dot | N +onChange | Function | | Typescript:`(current: string \| number, previous: string \| number, context?: { e?: MouseEvent }) => void`
| N + + +### StepItem Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +children | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +content | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +extra | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TNode | - | Typescript:`boolean \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +status | String | default | options: default/process/finish/error。Typescript:`StepStatus` `type StepStatus = 'default' \| 'process' \| 'finish' \| 'error'`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N +title | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +titleRight | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N diff --git a/src/steps/steps.md b/src/steps/steps.md index 6775b070..79b77824 100644 --- a/src/steps/steps.md +++ b/src/steps/steps.md @@ -1,29 +1,33 @@ :: BASE_DOC :: ## API + ### Steps Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N current | String / Number | - | 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成 | N defaultCurrent | String / Number | - | 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成。非受控属性 | N +currentStatus | String | process | 用于控制 current 指向的步骤条的状态。可选项:default/process/finish/error | N layout | String | horizontal | 步骤条方向,有两种:横向和纵向。可选项:horizontal/vertical | N -options | Array | - | 步骤条数据列表(作用和 StepItem 效果一样)。TS 类型:`Array` | N readonly | Boolean | false | 只读状态 | N -separator | String | line | 步骤条分割符。可选项:line/dashed/arrow | N +sequence | String | positive | 步骤条顺序。可选项:positive/reverse | N theme | String | default | 步骤条风格。可选项:default/dot | N -onChange | Function | | TS 类型:`(current: string | number, previous: string | number, context?: { e?: MouseEvent }) => void`
当前步骤发生变化时触发 | N +onChange | Function | | TS 类型:`(current: string \| number, previous: string \| number, context?: { e?: MouseEvent }) => void`
当前步骤发生变化时触发 | N + ### StepItem Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -children | TNode | - | 步骤描述,同 content。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -content | TNode | '' | 步骤描述。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -icon | TNode | true | 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标。TS 类型:`boolean | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -status | String | default | 当前步骤的状态。可选项:default/process/finish/error。TS 类型:`StepStatus` `type StepStatus = 'default' | 'process' | 'finish' | 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N -title | TNode | '' | 标题。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +children | TNode | - | 步骤描述,同 content。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +content | TNode | '' | 步骤描述。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +extra | TNode | - | 显示在步骤描述下方的额外内容,比如:操作项。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TNode | - | 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标。TS 类型:`boolean \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +status | String | default | 当前步骤的状态:默认状态(未开始)、进行中状态、完成状态、错误状态。可选项:default/process/finish/error。TS 类型:`StepStatus` `type StepStatus = 'default' \| 'process' \| 'finish' \| 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N +title | TNode | '' | 标题。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +titleRight | TNode | '' | 标题右侧数据 仅支持 layout = 'vertical' 时。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N diff --git a/src/steps/style/index.js b/src/steps/style/index.js index 6156d9cf..5ce6b9cd 100644 --- a/src/steps/style/index.js +++ b/src/steps/style/index.js @@ -1 +1,2 @@ -import '../../_common/style/mobile/components/steps/_index.less'; +import '../../_common/style/mobile/components/steps/v2/_index.less'; +import '../../_common/style/mobile/components/step-item/v2/_index.less'; diff --git a/src/steps/type.ts b/src/steps/type.ts index e2641c22..68435e74 100644 --- a/src/steps/type.ts +++ b/src/steps/type.ts @@ -16,25 +16,26 @@ export interface TdStepsProps { * 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成,非受控属性 */ defaultCurrent?: string | number; + /** + * 用于控制 current 指向的步骤条的状态 + * @default process + */ + currentStatus?: 'default' | 'process' | 'finish' | 'error'; /** * 步骤条方向,有两种:横向和纵向 * @default horizontal */ layout?: 'horizontal' | 'vertical'; - /** - * 步骤条数据列表(作用和 StepItem 效果一样) - */ - options?: Array; /** * 只读状态 * @default false */ readonly?: boolean; /** - * 步骤条分割符 - * @default line + * 步骤条顺序 + * @default positive */ - separator?: 'line' | 'dashed' | 'arrow'; + sequence?: 'positive' | 'reverse'; /** * 步骤条风格 * @default default @@ -60,13 +61,16 @@ export interface TdStepItemProps { * @default '' */ content?: TNode; + /** + * 显示在步骤描述下方的额外内容,比如:操作项 + */ + extra?: TNode; /** * 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标 - * @default true */ icon?: TNode; /** - * 当前步骤的状态 + * 当前步骤的状态:默认状态(未开始)、进行中状态、完成状态、错误状态 * @default default */ status?: StepStatus; @@ -75,6 +79,11 @@ export interface TdStepItemProps { * @default '' */ title?: TNode; + /** + * 标题右侧数据 仅支持 layout = 'vertical' 时 + * @default '' + */ + titleRight?: TNode; } export type StepStatus = 'default' | 'process' | 'finish' | 'error'; diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index 400d9c55..d1fba912 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -41408,6 +41408,3818 @@ exports[`csr snapshot test > csr test src/stepper/_example/theme.tsx 1`] = `
`; +exports[`csr snapshot test > csr test src/steps/_example/horizontal.tsx 1`] = ` +
+
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/index.tsx 1`] = ` +
+
+
+

+ Steps 步骤条 +

+

+ 用于任务步骤展示或任务进度展示。 +

+
+
+
+

+ 01 组件类型 +

+
+
+
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+

+ 02 组件状态 +

+
+
+
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+

+ 03 特殊类型 +

+
+
+
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/special.tsx 1`] = ` +
+
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/status.tsx 1`] = ` +
+
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/vertical.tsx 1`] = ` +
+
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+`; + exports[`csr snapshot test > csr test src/sticky/_example/base.tsx 1`] = `
ssr test src/stepper/_example/status.tsx 1`] = `" ssr test src/stepper/_example/theme.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/steps/_example/horizontal.tsx 1`] = `"
水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/index.tsx 1`] = `"

Steps 步骤条

用于任务步骤展示或任务进度展示。

01 组件类型

水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容

02 组件状态

选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息

03 特殊类型

垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/special.tsx 1`] = `"
垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/status.tsx 1`] = `"
选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/vertical.tsx 1`] = `"
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
"`; + exports[`ssr snapshot test > ssr test src/sticky/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/sticky/_example/container.tsx 1`] = `"
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index b3964200..1df0fce7 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -344,6 +344,16 @@ exports[`ssr snapshot test > ssr test src/stepper/_example/status.tsx 1`] = `" ssr test src/stepper/_example/theme.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/steps/_example/horizontal.tsx 1`] = `"
水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/index.tsx 1`] = `"

Steps 步骤条

用于任务步骤展示或任务进度展示。

01 组件类型

水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容

02 组件状态

选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息

03 特殊类型

垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/special.tsx 1`] = `"
垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/status.tsx 1`] = `"
选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/vertical.tsx 1`] = `"
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
"`; + exports[`ssr snapshot test > ssr test src/sticky/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/sticky/_example/container.tsx 1`] = `"
"`;