fillStep.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import React from 'react';
  2. import { isFunction } from 'lodash-es';
  3. import PropTypes from 'prop-types';
  4. import classnames from 'classnames';
  5. import { stepsClasses as css } from '@douyinfe/semi-foundation/steps/constants';
  6. import { IconTickCircle, IconAlertCircle, IconAlertTriangle } from '@douyinfe/semi-icons';
  7. export type Status = 'wait' | 'process' | 'finish' | 'error' | 'warning';
  8. export interface FillStepProps {
  9. description?: React.ReactNode;
  10. icon?: React.ReactNode;
  11. status?: Status;
  12. title?: React.ReactNode;
  13. className?: string;
  14. style?: React.CSSProperties;
  15. prefixCls?: string;
  16. stepNumber?: string;
  17. onChange?: () => void;
  18. onClick?: React.MouseEventHandler<HTMLDivElement>;
  19. }
  20. const FillStep = (props: FillStepProps) => {
  21. const { prefixCls, className, title, description, status, style, onClick, icon, onChange, stepNumber } = props;
  22. const renderIcon = () => {
  23. let inner, progress;
  24. if ('icon' in props) {
  25. inner = icon;
  26. } else if ('status' in props) {
  27. switch (status) {
  28. case 'error':
  29. inner = <IconAlertCircle size="extra-large" />;
  30. break;
  31. case 'wait':
  32. inner = stepNumber;
  33. break;
  34. case 'process':
  35. inner = stepNumber;
  36. progress = true;
  37. break;
  38. case 'finish':
  39. inner = <IconTickCircle size="extra-large" />;
  40. break;
  41. case 'warning':
  42. inner = <IconAlertTriangle size="extra-large" />;
  43. break;
  44. default:
  45. inner = null;
  46. break;
  47. }
  48. }
  49. const cls = classnames({
  50. [`${prefixCls }-left`]: true,
  51. [`${prefixCls }-icon`]: 'icon' in props,
  52. [`${prefixCls }-plain`]: !('icon' in props),
  53. [`${prefixCls }-icon-process`]: progress,
  54. });
  55. return inner ? <div className={cls}>{inner}</div> : null;
  56. };
  57. const handleClick = (e: React.MouseEvent) => {
  58. if (isFunction(onClick)) {
  59. onClick(e);
  60. }
  61. onChange();
  62. };
  63. return (
  64. <div
  65. className={classnames({
  66. [className]: Boolean(className),
  67. [prefixCls]: true,
  68. [`${prefixCls}-${status}`]: Boolean(status),
  69. [`${prefixCls }-clickable`]: onClick,
  70. })}
  71. style={style}
  72. onClick={e => {
  73. handleClick(e);
  74. }}
  75. >
  76. {renderIcon()}
  77. <div className={`${prefixCls }-content`}>
  78. <div className={`${prefixCls }-title`} title={typeof title === 'string' ? title : null}>
  79. <span className={`${prefixCls }-title-text`}>{title}</span>
  80. </div>
  81. <div
  82. className={`${prefixCls }-description`}
  83. title={typeof description === 'string' ? description : null}
  84. >
  85. {description}
  86. </div>
  87. </div>
  88. </div>
  89. );
  90. };
  91. FillStep.propTypes = {
  92. prefixCls: PropTypes.string,
  93. description: PropTypes.node,
  94. icon: PropTypes.node,
  95. status: PropTypes.oneOf(['wait', 'process', 'finish', 'error', 'warning']),
  96. title: PropTypes.node,
  97. className: PropTypes.string,
  98. style: PropTypes.object,
  99. onClick: PropTypes.func,
  100. };
  101. FillStep.defaultProps = {
  102. prefixCls: css.ITEM,
  103. status: 'wait',
  104. className: '',
  105. };
  106. export default FillStep;