navSteps.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import React, { cloneElement, Children, useMemo } from 'react';
  2. import PropTypes from 'prop-types';
  3. import cls from 'classnames';
  4. import { stepsClasses as css } from '@douyinfe/semi-foundation/steps/constants';
  5. export type Size = 'default' | 'small';
  6. export interface NavStepsProps {
  7. prefixCls?: string;
  8. className?: string;
  9. style?: React.CSSProperties;
  10. current?: number;
  11. initial?: number;
  12. size?: Size;
  13. children?: React.ReactNode;
  14. onChange?: (current: number) => void;
  15. }
  16. const Steps = (props: NavStepsProps) => {
  17. const { size, current, initial, children, prefixCls, className, style, onChange } = props;
  18. const inner = useMemo(() => {
  19. const filteredChildren = Children.toArray(children).filter(c => Boolean(c));
  20. const total = filteredChildren.length;
  21. const content = Children.map(filteredChildren, (child: React.ReactElement, index) => {
  22. if (!child) {
  23. return null;
  24. }
  25. const childProps = {
  26. index,
  27. total,
  28. ...child.props,
  29. };
  30. childProps.active = index === current;
  31. childProps.onChange = () => {
  32. if (index !== current) {
  33. onChange(index + initial);
  34. }
  35. };
  36. return cloneElement(child, { ...childProps });
  37. });
  38. return content;
  39. }, [children, prefixCls, current, size]);
  40. const wrapperCls = cls(className, {
  41. [`${prefixCls}-nav`]: true,
  42. [`${prefixCls}-${size}`]: size !== 'default',
  43. });
  44. return (
  45. <div className={wrapperCls} style={style}>
  46. {inner}
  47. </div>
  48. );
  49. };
  50. Steps.propTypes = {
  51. prefixCls: PropTypes.string,
  52. className: PropTypes.string,
  53. style: PropTypes.object,
  54. current: PropTypes.number,
  55. initial: PropTypes.number,
  56. size: PropTypes.oneOf(['small', 'default']),
  57. };
  58. Steps.defaultProps = {
  59. prefixCls: css.PREFIX,
  60. current: 0,
  61. direction: 'horizontal',
  62. size: 'default',
  63. initial: 0,
  64. status: 'process',
  65. };
  66. export default Steps;