navSteps.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import React, { cloneElement, Children, useMemo, isValidElement, ReactElement } 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. "aria-label"?: string;
  16. }
  17. const Steps = (props: NavStepsProps) => {
  18. const { size, current, initial, children, prefixCls, className, style, onChange } = props;
  19. const inner = useMemo(() => {
  20. const filteredChildren = Children.toArray(children).filter(c => isValidElement(c)) as Array<ReactElement>;
  21. const total = filteredChildren.length;
  22. const content = Children.map(filteredChildren, (child: React.ReactElement, index) => {
  23. if (!child) {
  24. return null;
  25. }
  26. const childProps = {
  27. index,
  28. total,
  29. ...child.props,
  30. };
  31. childProps.active = index === current;
  32. childProps.onChange = () => {
  33. if (index !== current) {
  34. onChange(index + initial);
  35. }
  36. };
  37. return cloneElement(child, { ...childProps });
  38. });
  39. return content;
  40. }, [children, prefixCls, current, size, initial, onChange]);
  41. const wrapperCls = cls(className, {
  42. [`${prefixCls}-nav`]: true,
  43. [`${prefixCls}-${size}`]: size !== 'default',
  44. });
  45. return (
  46. <div aria-label={props["aria-label"]} className={wrapperCls} style={style}>
  47. {inner}
  48. </div>
  49. );
  50. };
  51. Steps.propTypes = {
  52. prefixCls: PropTypes.string,
  53. className: PropTypes.string,
  54. style: PropTypes.object,
  55. current: PropTypes.number,
  56. initial: PropTypes.number,
  57. size: PropTypes.oneOf(['small', 'default']),
  58. };
  59. Steps.defaultProps = {
  60. prefixCls: css.PREFIX,
  61. current: 0,
  62. direction: 'horizontal',
  63. size: 'default',
  64. initial: 0,
  65. status: 'process',
  66. };
  67. export default Steps;