@spaced-out/ui-design-system
Version:
Sense UI components library
124 lines (114 loc) • 3.16 kB
Flow
// @flow strict
import * as React from 'react';
import classify from '../../../utils/classify';
import type {IconType} from '../../Icon';
import {Icon, ICON_SIZE, ICON_TYPE} from '../../Icon';
import css from '../Stepper.module.css';
type ClassNames = $ReadOnly<{
wrapper?: string,
stepCounter?: string,
content?: string,
}>;
export type StepProps = {
active?: boolean,
children: React.Node,
completed?: boolean,
disabled?: boolean,
expanded?: boolean,
index: number,
last?: boolean,
classNames?: ClassNames,
allowClick?: boolean,
onClick?: (idx: number, e?: ?SyntheticEvent<HTMLElement>) => mixed,
iconName?: string,
iconType?: IconType,
};
export const Step: React$AbstractComponent<StepProps, HTMLDivElement> =
React.forwardRef<StepProps, HTMLDivElement>(
(
{
active,
children,
completed = false,
disabled = false,
expanded = false,
index = 0,
last,
classNames,
onClick,
allowClick,
iconName,
iconType,
}: StepProps,
ref,
): React.Node => {
const childrenArray = React.Children.toArray(children).filter(Boolean);
const stepContent = childrenArray.map((stepContent) =>
React.cloneElement(stepContent, {
...stepContent.props,
active,
completed,
disabled,
}),
);
const handleClick = (e) => allowClick && onClick?.(index, e);
return (
<div
ref={ref}
className={classify(
css.stepWrapper,
{
[css.active]: active,
[css.completed]: completed,
[css.expanded]: expanded,
[css.last]: last,
[css.disabled]: disabled,
[css.clickable]: allowClick,
},
classNames?.wrapper,
)}
onClick={handleClick}
>
<div
className={classify(
css.stepWrapperCounter,
{
[css.selected]: active,
[css.completed]: completed,
[css.expanded]: expanded,
[css.last]: last,
[css.disabled]: disabled,
[css.withIcon]: !!iconName,
},
classNames?.stepCounter,
)}
>
{completed && !active ? (
<Icon
name="check"
type={ICON_TYPE.solid}
size={ICON_SIZE.small}
className={css.stepIcon}
/>
) : (
<React.Fragment>
{iconName ? (
<Icon
name={iconName}
className={css.stepIcon}
size={ICON_SIZE.small}
type={iconType}
/>
) : (
(index + 1).toString()
)}
</React.Fragment>
)}
</div>
<div className={classify(css.stepContent, classNames?.content)}>
{stepContent}
</div>
</div>
);
},
);