1
0

errorMessage.tsx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* eslint-disable prefer-template */
  2. import React, { PureComponent } from 'react';
  3. import classNames from 'classnames';
  4. import PropTypes from 'prop-types';
  5. import { cssClasses } from '@douyinfe/semi-foundation/form/constants';
  6. import { IconAlertTriangle, IconAlertCircle } from '@douyinfe/semi-icons';
  7. const prefix = cssClasses.PREFIX;
  8. export type ReactFieldError = boolean | string | Array<any> | React.ReactNode | undefined;
  9. export interface ErrorMessageProps {
  10. error?: ReactFieldError;
  11. className?: string;
  12. style?: React.CSSProperties;
  13. showValidateIcon?: boolean;
  14. validateStatus?: string;
  15. helpText?: React.ReactNode;
  16. isInInputGroup?: boolean;
  17. errorMessageId?: string;
  18. helpTextId?: string;
  19. }
  20. export default class ErrorMessage extends PureComponent<ErrorMessageProps> {
  21. static propTypes = {
  22. error: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.array, PropTypes.node]),
  23. className: PropTypes.string,
  24. style: PropTypes.object,
  25. validateStatus: PropTypes.string,
  26. showValidateIcon: PropTypes.bool,
  27. helpText: PropTypes.node,
  28. isInInputGroup: PropTypes.bool,
  29. // internal props
  30. errorMessageId: PropTypes.string,
  31. helpTextId: PropTypes.string,
  32. };
  33. generatorText(error: ReactFieldError) {
  34. const { helpTextId, errorMessageId } = this.props;
  35. const propsError = this.props.error;
  36. let id = errorMessageId;
  37. if (!propsError) {
  38. id = helpTextId;
  39. }
  40. if (typeof error === 'string') {
  41. return <span id={id}>{error}</span>;
  42. } else if (Array.isArray(error)) {
  43. const err = error.filter(e => e);
  44. return err.length ? <span id={id}>{err.join(', ')}</span> : null;
  45. } else if (React.isValidElement(error)) {
  46. return error;
  47. }
  48. return null;
  49. }
  50. render() {
  51. const { error, className, style, validateStatus, helpText, showValidateIcon, isInInputGroup } = this.props;
  52. const cls = classNames(
  53. {
  54. [prefix + '-field-error-message']: Boolean(error),
  55. [prefix + '-field-help-text']: Boolean(helpText),
  56. },
  57. className
  58. );
  59. if (!error && !helpText) {
  60. return null;
  61. }
  62. const iconMap = {
  63. warning: <IconAlertTriangle />,
  64. error: <IconAlertCircle />,
  65. };
  66. const text = error ? this.generatorText(error) : this.generatorText(helpText);
  67. const iconCls = `${prefix }-field-validate-status-icon`;
  68. let icon = null;
  69. if (isInInputGroup) {
  70. icon = <IconAlertCircle className={iconCls} />;
  71. } else {
  72. if (iconMap[validateStatus]) {
  73. icon = React.cloneElement(iconMap[validateStatus], { className: iconCls });
  74. }
  75. }
  76. return (
  77. <div className={cls} style={style}>
  78. {showValidateIcon && text ? icon : null}
  79. {text}
  80. </div>
  81. );
  82. }
  83. }