Button.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* eslint-disable react/destructuring-assignment */
  2. import React, { PureComponent } from 'react';
  3. import classNames from 'classnames';
  4. import PropTypes from 'prop-types';
  5. import { cssClasses, strings } from '@douyinfe/semi-foundation/button/constants';
  6. import '@douyinfe/semi-foundation/button/button.scss';
  7. import { noop } from '@douyinfe/semi-foundation/utils/function';
  8. const btnSizes = strings.sizes;
  9. const { htmlTypes, btnTypes } = strings;
  10. export type HtmlType = 'button' | 'reset' | 'submit';
  11. export type Size = 'default' | 'small' | 'large';
  12. export type Theme = 'solid' | 'borderless' | 'light';
  13. export type Type = 'primary' | 'secondary' | 'tertiary' | 'warning' | 'danger';
  14. export interface ButtonProps {
  15. id?: string;
  16. block?: boolean;
  17. circle?: boolean;
  18. disabled?: boolean;
  19. className?: string;
  20. icon?: React.ReactNode;
  21. iconPosition?: 'left' | 'right';
  22. loading?: boolean;
  23. htmlType?: HtmlType;
  24. size?: Size;
  25. style?: React.CSSProperties;
  26. theme?: Theme;
  27. type?: Type;
  28. prefixCls?: string;
  29. onClick?: React.MouseEventHandler<HTMLButtonElement>;
  30. onMouseDown?: React.MouseEventHandler<HTMLButtonElement>;
  31. onMouseEnter?: React.MouseEventHandler<HTMLButtonElement>;
  32. onMouseLeave?: React.MouseEventHandler<HTMLButtonElement>;
  33. }
  34. // TODO: icon configuration
  35. export default class Button extends PureComponent<ButtonProps> {
  36. static defaultProps = {
  37. disabled: false,
  38. size: 'default',
  39. type: 'primary',
  40. theme: 'light',
  41. block: false,
  42. htmlType: 'button',
  43. onMouseDown: noop,
  44. onClick: noop,
  45. onMouseEnter: noop,
  46. onMouseLeave: noop,
  47. prefixCls: cssClasses.PREFIX,
  48. };
  49. static propTypes = {
  50. children: PropTypes.node,
  51. disabled: PropTypes.bool,
  52. prefixCls: PropTypes.string,
  53. style: PropTypes.object,
  54. size: PropTypes.oneOf(btnSizes),
  55. type: PropTypes.oneOf(btnTypes),
  56. block: PropTypes.bool,
  57. onClick: PropTypes.func,
  58. onMouseDown: PropTypes.func,
  59. circle: PropTypes.bool,
  60. loading: PropTypes.bool,
  61. htmlType: PropTypes.oneOf(htmlTypes),
  62. theme: PropTypes.oneOf(strings.themes),
  63. className: PropTypes.string,
  64. onMouseEnter: PropTypes.func,
  65. onMouseLeave: PropTypes.func,
  66. };
  67. render() {
  68. const {
  69. children,
  70. block,
  71. htmlType,
  72. loading,
  73. circle,
  74. className,
  75. style,
  76. disabled,
  77. size,
  78. theme,
  79. type,
  80. prefixCls,
  81. iconPosition,
  82. ...attr
  83. } = this.props;
  84. const baseProps = {
  85. disabled,
  86. ...attr,
  87. className: classNames(
  88. prefixCls,
  89. {
  90. [`${prefixCls}-${type}`]: !disabled && type,
  91. [`${prefixCls}-disabled`]: disabled,
  92. [`${prefixCls}-size-large`]: size === 'large',
  93. [`${prefixCls}-size-small`]: size === 'small',
  94. // [`${prefixCls}-loading`]: loading,
  95. [`${prefixCls}-light`]: theme === 'light',
  96. [`${prefixCls}-block`]: block,
  97. [`${prefixCls}-circle`]: circle,
  98. [`${prefixCls}-borderless`]: theme === 'borderless',
  99. },
  100. className
  101. ),
  102. type: htmlType,
  103. };
  104. return (
  105. // eslint-disable-next-line react/button-has-type
  106. <button
  107. {...baseProps}
  108. onClick={this.props.onClick}
  109. onMouseDown={this.props.onMouseDown}
  110. style={style}
  111. >
  112. <span className={`${prefixCls}-content`} onClick={e => disabled && e.stopPropagation()}>
  113. {children}
  114. </span>
  115. </button>
  116. );
  117. }
  118. }