| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 | import React from 'react';import { isFunction } from 'lodash';import PropTypes from 'prop-types';import classnames from 'classnames';import { stepsClasses as css } from '@douyinfe/semi-foundation/steps/constants';import { IconTickCircle, IconAlertCircle, IconAlertTriangle } from '@douyinfe/semi-icons';export type Status = 'wait' | 'process' | 'finish' | 'error' | 'warning';export type Size = 'default' | 'small';export interface BasicStepProps {    description?: React.ReactNode;    icon?: React.ReactNode;    status?: Status;    title?: React.ReactNode;    className?: string;    style?: React.CSSProperties;    active?: boolean;    prefixCls?: string;    stepNumber?: string;    size?: Size;    done?: boolean;    onChange?: () => void;    onClick?: React.MouseEventHandler<HTMLDivElement>;    onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;    "role"?: React.AriaRole;    "aria-label"?: React.AriaAttributes["aria-label"];}export enum stepSizeMapIconSize {    small = 'large',    default = 'extra-large'}const BasicStep = (props: BasicStepProps) => {    const {        prefixCls,        className,        size,        title,        description,        status,        style,        active,        done,        icon,        stepNumber,        onClick,        onChange,        onKeyDown,    } = props;    const renderIcon = () => {        let inner, progress;        if ('icon' in props) {            if (React.isValidElement(icon)) {                inner = icon;            }        } else if ('status' in props) {            switch (status) {                case 'error':                    inner = <IconAlertCircle size={stepSizeMapIconSize[size]} />;                    break;                case 'wait':                    inner = <span className={`${prefixCls}-number-icon`}>{stepNumber}</span>;                    break;                case 'process':                    inner = <span className={`${prefixCls}-number-icon`}>{stepNumber}</span>;                    progress = true;                    break;                case 'finish':                    inner = <IconTickCircle size={stepSizeMapIconSize[size]} />;                    break;                case 'warning':                    inner = <IconAlertTriangle size={stepSizeMapIconSize[size]} />;                    break;                default:                    inner = null;                    break;            }        }        const cls = classnames({            [`${prefixCls}-icon`]: true,            [`${prefixCls}-custom-icon`]: 'icon' in props,            [`${prefixCls}-icon-process`]: progress,        });        return inner ? <span className={cls}>{inner}</span> : null;    };    const classString = classnames(prefixCls, `${prefixCls}-${status}`, {        [`${prefixCls}-active`]: active,        [`${prefixCls}-done`]: done    }, className);    const handleClick = (e: React.MouseEvent) => {        if (isFunction(onClick)) {            onClick(e);        }        onChange();    };    const handleKeyDown = (e) => {        if (e.key === 'Enter') {            if (isFunction(onKeyDown)) {                onKeyDown(e);            }            onChange();        }    };    return (        <div role={props["role"]} aria-label={props["aria-label"]} tabIndex={0} aria-current="step" className={classString} style={style} onClick={e => handleClick(e)} onKeyDown={handleKeyDown}>            <div className={`${prefixCls}-container`}>                <div className={`${prefixCls}-left`}>{renderIcon()}</div>                <div className={`${prefixCls}-content`}>                    <div className={`${prefixCls}-title`}>                        <div className={`${prefixCls}-title-text`}>{title}</div>                    </div>                    {description && <div className={`${prefixCls}-description`}>{description}</div>}                </div>            </div>        </div>    );};BasicStep.propTypes = {    prefixCls: PropTypes.string,    description: PropTypes.node,    icon: PropTypes.node,    status: PropTypes.oneOf(['wait', 'process', 'finish', 'error', 'warning']),    title: PropTypes.node,    className: PropTypes.string,    style: PropTypes.object,    onClick: PropTypes.func,    active: PropTypes.bool,    done: PropTypes.bool,};BasicStep.defaultProps = {    prefixCls: css.ITEM,    active: false,    done: false,    status: 'wait',    className: '',};export default BasicStep;
 |