Skip to content

Commit

Permalink
chore: Component to FC (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
JarvisArt authored Nov 5, 2022
1 parent e021a01 commit c0bc1b3
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 187 deletions.
156 changes: 73 additions & 83 deletions src/Step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,41 @@ export interface StepProps {
render?: (stepItem: React.ReactNode) => React.ReactNode;
}

export default class Step extends React.Component<StepProps> {
onClick: React.MouseEventHandler<HTMLDivElement> = (...args) => {
const { onClick, onStepClick, stepIndex } = this.props;
function Step(props: StepProps) {
const {
className,
prefixCls,
style,
active,
status,
iconPrefix,
icon,
wrapperStyle,
stepNumber,
disabled,
description,
title,
subTitle,
progressDot,
stepIcon,
tailContent,
icons,
stepIndex,
onStepClick,
onClick,
render,
...restProps
} = props;

const onInternalClick: React.MouseEventHandler<HTMLDivElement> = (...args) => {
if (onClick) {
onClick(...args);
}

onStepClick(stepIndex);
};

renderIconNode() {
const {
prefixCls,
progressDot,
stepIcon,
stepNumber,
status,
title,
description,
icon,
iconPrefix,
icons,
} = this.props;
const renderIconNode = () => {
let iconNode;
const iconClassName = classNames(`${prefixCls}-icon`, `${iconPrefix}icon`, {
[`${iconPrefix}icon-${icon}`]: icon && isString(icon),
Expand Down Expand Up @@ -103,79 +115,57 @@ export default class Step extends React.Component<StepProps> {
}

return iconNode;
}
};

render() {
const {
className,
prefixCls,
style,
active,
status = 'wait',
iconPrefix,
icon,
wrapperStyle,
stepNumber,
disabled,
description,
title,
subTitle,
progressDot,
stepIcon,
tailContent,
icons,
stepIndex,
onStepClick,
onClick,
render,
...restProps
} = this.props;

const classString = classNames(`${prefixCls}-item`, `${prefixCls}-item-${status}`, className, {
[`${prefixCls}-item-custom`]: icon,
[`${prefixCls}-item-active`]: active,
[`${prefixCls}-item-disabled`]: disabled === true,
});
const stepItemStyle = { ...style };

const accessibilityProps: {
role?: string;
tabIndex?: number;
onClick?: React.MouseEventHandler<HTMLDivElement>;
} = {};
if (onStepClick && !disabled) {
accessibilityProps.role = 'button';
accessibilityProps.tabIndex = 0;
accessibilityProps.onClick = this.onClick;
}
const mergedStatus = status || 'wait';

const classString = classNames(`${prefixCls}-item`, `${prefixCls}-item-${mergedStatus}`, className, {
[`${prefixCls}-item-custom`]: icon,
[`${prefixCls}-item-active`]: active,
[`${prefixCls}-item-disabled`]: disabled === true,
});
const stepItemStyle = { ...style };

let stepNode: React.ReactNode = (
<div {...restProps} className={classString} style={stepItemStyle}>
<div onClick={onClick} {...accessibilityProps} className={`${prefixCls}-item-container`}>
<div className={`${prefixCls}-item-tail`}>{tailContent}</div>
<div className={`${prefixCls}-item-icon`}>{this.renderIconNode()}</div>
<div className={`${prefixCls}-item-content`}>
<div className={`${prefixCls}-item-title`}>
{title}
{subTitle && (
<div
title={typeof subTitle === 'string' ? subTitle : undefined}
className={`${prefixCls}-item-subtitle`}
>
{subTitle}
</div>
)}
</div>
{description && <div className={`${prefixCls}-item-description`}>{description}</div>}
const accessibilityProps: {
role?: string;
tabIndex?: number;
onClick?: React.MouseEventHandler<HTMLDivElement>;
} = {};
if (onStepClick && !disabled) {
accessibilityProps.role = 'button';
accessibilityProps.tabIndex = 0;
accessibilityProps.onClick = onInternalClick;
}

let stepNode: React.ReactNode = (
<div {...restProps} className={classString} style={stepItemStyle}>
<div onClick={onClick} {...accessibilityProps} className={`${prefixCls}-item-container`}>
<div className={`${prefixCls}-item-tail`}>{tailContent}</div>
<div className={`${prefixCls}-item-icon`}>{renderIconNode()}</div>
<div className={`${prefixCls}-item-content`}>
<div className={`${prefixCls}-item-title`}>
{title}
{subTitle && (
<div
title={typeof subTitle === 'string' ? subTitle : undefined}
className={`${prefixCls}-item-subtitle`}
>
{subTitle}
</div>
)}
</div>
{description && <div className={`${prefixCls}-item-description`}>{description}</div>}
</div>
</div>
);
</div>
);

if (render) {
stepNode = render(stepNode) || null;
}

return stepNode as React.ReactElement;
if (render) {
stepNode = render(stepNode) || null;
}

return stepNode as React.ReactElement;
}

export default Step;
195 changes: 91 additions & 104 deletions src/Steps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,117 +44,104 @@ export interface StepsProps {
onChange?: (current: number) => void;
}

export default class Steps extends React.Component<StepsProps> {
static Step = Step;

static defaultProps = {
type: 'default',
prefixCls: 'rc-steps',
iconPrefix: 'rc',
direction: 'horizontal',
labelPlacement: 'horizontal',
initial: 0,
current: 0,
status: 'process',
size: '',
progressDot: false,
};
function Steps(props: StepsProps) {
const {
prefixCls = 'rc-steps',
style = {},
className,
children,
direction = 'horizontal',
type = 'default',
labelPlacement = 'horizontal',
iconPrefix = 'rc',
status = 'process',
size,
current = 0,
progressDot = false,
stepIcon,
initial = 0,
icons,
onChange,
itemRender,
items = [],
...restProps
} = props;

const isNav = type === 'navigation';
const isInline = type === 'inline';

// inline type requires fixed progressDot direction size.
const mergedProgressDot = isInline || progressDot;
const mergedDirection = isInline ? 'horizontal' : direction;
const mergedSize = isInline ? undefined : size;

const adjustedLabelPlacement = mergedProgressDot ? 'vertical' : labelPlacement;
const classString = classNames(prefixCls, `${prefixCls}-${mergedDirection}`, className, {
[`${prefixCls}-${mergedSize}`]: mergedSize,
[`${prefixCls}-label-${adjustedLabelPlacement}`]: mergedDirection === 'horizontal',
[`${prefixCls}-dot`]: !!mergedProgressDot,
[`${prefixCls}-navigation`]: isNav,
[`${prefixCls}-inline`]: isInline,
});

onStepClick = (next: number) => {
const { onChange, current } = this.props;
const onStepClick = (next: number) => {
if (onChange && current !== next) {
onChange(next);
}
};

render() {
const {
prefixCls,
style = {},
className,
children,
direction,
type,
labelPlacement,
iconPrefix,
status,
size,
current,
progressDot,
stepIcon,
initial,
icons,
onChange,
itemRender,
items = [],
...restProps
} = this.props;
const isNav = type === 'navigation';
const isInline = type === 'inline';

// inline type requires fixed progressDot direction size.
const mergedProgressDot = isInline || progressDot;
const mergedDirection = isInline ? 'horizontal' : direction;
const mergedSize = isInline ? undefined : size;

const adjustedLabelPlacement = mergedProgressDot ? 'vertical' : labelPlacement;
const classString = classNames(prefixCls, `${prefixCls}-${mergedDirection}`, className, {
[`${prefixCls}-${mergedSize}`]: mergedSize,
[`${prefixCls}-label-${adjustedLabelPlacement}`]: mergedDirection === 'horizontal',
[`${prefixCls}-dot`]: !!mergedProgressDot,
[`${prefixCls}-navigation`]: isNav,
[`${prefixCls}-inline`]: isInline,
});
const renderStep = (item: StepProps, index: number) => {
const mergedItem = { ...item };
const stepNumber = initial + index;
// fix tail color
if (status === 'error' && index === current - 1) {
mergedItem.className = `${prefixCls}-next-error`;
}

if (!mergedItem.status) {
if (stepNumber === current) {
mergedItem.status = status;
} else if (stepNumber < current) {
mergedItem.status = 'finish';
} else {
mergedItem.status = 'wait';
}
}

if (isInline) {
mergedItem.icon = undefined;
mergedItem.subTitle = undefined;
}

if (!mergedItem.render && itemRender) {
mergedItem.render = (stepItem) => itemRender(mergedItem, stepItem);
}

return (
<div className={classString} style={style} {...restProps}>
{items
.filter((item) => item)
.map((item, index) => {
const mergedItem = { ...item };
const stepNumber = initial + index;
// fix tail color
if (status === 'error' && index === current - 1) {
mergedItem.className = `${prefixCls}-next-error`;
}

if (!mergedItem.status) {
if (stepNumber === current) {
mergedItem.status = status;
} else if (stepNumber < current) {
mergedItem.status = 'finish';
} else {
mergedItem.status = 'wait';
}
}

if (isInline) {
mergedItem.icon = undefined;
mergedItem.subTitle = undefined;
}

if (!mergedItem.render && itemRender) {
mergedItem.render = (stepItem) => itemRender(mergedItem, stepItem);
}

return (
<Step
{...mergedItem}
active={stepNumber === current}
stepNumber={stepNumber + 1}
stepIndex={stepNumber}
key={stepNumber}
prefixCls={prefixCls}
iconPrefix={iconPrefix}
wrapperStyle={style}
progressDot={mergedProgressDot}
stepIcon={stepIcon}
icons={icons}
onStepClick={onChange && this.onStepClick}
/>
);
})}
</div>
<Step
{...mergedItem}
active={stepNumber === current}
stepNumber={stepNumber + 1}
stepIndex={stepNumber}
key={stepNumber}
prefixCls={prefixCls}
iconPrefix={iconPrefix}
wrapperStyle={style}
progressDot={mergedProgressDot}
stepIcon={stepIcon}
icons={icons}
onStepClick={onChange && onStepClick}
/>
);
}
};

return (
<div className={classString} style={style} {...restProps}>
{items.filter((item) => item).map(renderStep)}
</div>
);
}

Steps.Step = Step;

export default Steps;

0 comments on commit c0bc1b3

Please sign in to comment.