fillStep.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import React from 'react';
  2. import { isFunction } from 'lodash';
  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. onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
  20. "role"?: React.AriaRole;
  21. "aria-label"?: React.AriaAttributes["aria-label"]
  22. }
  23. const FillStep = (props: FillStepProps) => {
  24. const { prefixCls, className, title, description, status, style, onClick, icon, onChange, stepNumber, onKeyDown } = props;
  25. const renderIcon = () => {
  26. let inner, progress;
  27. if ('icon' in props) {
  28. inner = icon;
  29. } else if ('status' in props) {
  30. switch (status) {
  31. case 'error':
  32. inner = <IconAlertCircle size="extra-large" />;
  33. break;
  34. case 'wait':
  35. inner = stepNumber;
  36. break;
  37. case 'process':
  38. inner = stepNumber;
  39. progress = true;
  40. break;
  41. case 'finish':
  42. inner = <IconTickCircle size="extra-large" />;
  43. break;
  44. case 'warning':
  45. inner = <IconAlertTriangle size="extra-large" />;
  46. break;
  47. default:
  48. inner = null;
  49. break;
  50. }
  51. }
  52. const cls = classnames({
  53. [`${prefixCls}-left`]: true,
  54. [`${prefixCls}-icon`]: 'icon' in props,
  55. [`${prefixCls}-plain`]: !('icon' in props),
  56. [`${prefixCls}-icon-process`]: progress,
  57. [`${prefixCls}-hover`]: onChange || onClick,
  58. });
  59. return inner ? <div className={cls}>{inner}</div> : null;
  60. };
  61. const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
  62. onClick?.(e);
  63. onChange?.();
  64. };
  65. const handleKeyDown = (e) => {
  66. if (e.key === 'Enter') {
  67. onKeyDown?.(e);
  68. onChange?.();
  69. }
  70. };
  71. return (
  72. <div
  73. role={props["role"]}
  74. aria-label={props["aria-label"]}
  75. aria-current="step"
  76. tabIndex={0}
  77. className={classnames({
  78. [prefixCls]: true,
  79. [`${prefixCls}-${status}`]: Boolean(status),
  80. [`${prefixCls}-${status}-hover`]: Boolean(status) && (onChange || onClick),
  81. [`${prefixCls}-${status}-active`]: Boolean(status) && (onChange || onClick),
  82. [`${prefixCls}-clickable`]: (onChange || onClick),
  83. }, className)}
  84. style={style}
  85. onClick={e => {
  86. handleClick(e);
  87. }}
  88. onKeyDown={handleKeyDown}
  89. >
  90. {renderIcon()}
  91. <div className={`${prefixCls}-content`}>
  92. <div className={`${prefixCls}-title`} title={typeof title === 'string' ? title : null}>
  93. <span className={`${prefixCls}-title-text`}>{title}</span>
  94. </div>
  95. <div
  96. className={`${prefixCls}-description`}
  97. title={typeof description === 'string' ? description : null}
  98. >
  99. {description}
  100. </div>
  101. </div>
  102. </div>
  103. );
  104. };
  105. FillStep.propTypes = {
  106. prefixCls: PropTypes.string,
  107. description: PropTypes.node,
  108. icon: PropTypes.node,
  109. status: PropTypes.oneOf(['wait', 'process', 'finish', 'error', 'warning']),
  110. title: PropTypes.node,
  111. className: PropTypes.string,
  112. style: PropTypes.object,
  113. onClick: PropTypes.func,
  114. };
  115. FillStep.defaultProps = {
  116. prefixCls: css.ITEM,
  117. status: 'wait',
  118. className: '',
  119. };
  120. export default FillStep;