item.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import React, { PureComponent } from 'react';
  2. import cls from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import { cssClasses, strings } from '@douyinfe/semi-foundation/list/constants';
  5. import { noop } from 'lodash';
  6. import { Col } from '../grid';
  7. import ListContext from './list-context';
  8. export interface ListItemProps {
  9. extra?: React.ReactNode;
  10. header?: React.ReactNode;
  11. main?: React.ReactNode;
  12. align?: 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
  13. className?: string;
  14. style?: React.CSSProperties;
  15. onClick?: React.MouseEventHandler<HTMLLIElement>;
  16. onRightClick?: React.MouseEventHandler<HTMLLIElement>;
  17. onMouseLeave?: React.MouseEventHandler<HTMLLIElement>;
  18. onMouseEnter?: React.MouseEventHandler<HTMLLIElement>;
  19. }
  20. const prefixCls = cssClasses.PREFIX;
  21. export default class ListItem extends PureComponent<ListItemProps> {
  22. static contextType = ListContext;
  23. static propTypes = {
  24. extra: PropTypes.node,
  25. header: PropTypes.node,
  26. main: PropTypes.node,
  27. align: PropTypes.oneOf(strings.ALIGN),
  28. className: PropTypes.string,
  29. style: PropTypes.object,
  30. onClick: PropTypes.func,
  31. onRightClick: PropTypes.func,
  32. onMouseEnter: PropTypes.func,
  33. onMouseLeave: PropTypes.func,
  34. };
  35. static defaultProps = {
  36. align: 'flex-start',
  37. onMouseEnter: noop,
  38. onMouseLeave: noop,
  39. };
  40. wrapWithGrid(content: React.ReactNode) {
  41. const { grid } = this.context;
  42. const { gutter, justify, type, align, ...rest } = grid;
  43. return (
  44. <Col {...rest}>
  45. {content}
  46. </Col>
  47. );
  48. }
  49. render() {
  50. const {
  51. header,
  52. main,
  53. className,
  54. style,
  55. extra,
  56. children,
  57. align,
  58. onClick,
  59. onRightClick,
  60. onMouseEnter,
  61. onMouseLeave
  62. } = this.props;
  63. const { onRightClick: contextOnRightClick, onClick: contextOnClick, grid: contextGrid } = this.context;
  64. const handleContextMenu = onRightClick ? onRightClick : contextOnRightClick;
  65. const handleClick = onClick ? onClick : contextOnClick;
  66. const itemCls = cls(`${prefixCls}-item`, className);
  67. const bodyCls = cls(`${prefixCls}-item-body`,
  68. {
  69. [`${prefixCls}-item-body-${align}`]: align,
  70. }
  71. );
  72. let body;
  73. if (header || main) {
  74. body = (
  75. <div className={bodyCls}>
  76. {header ? <div className={`${prefixCls}-item-body-header`}>{header}</div> : null}
  77. {main ? <div className={`${prefixCls}-item-body-main`}>{main}</div> : null}
  78. </div>
  79. );
  80. }
  81. let content = (
  82. <li
  83. className={itemCls}
  84. style={style}
  85. onClick={handleClick}
  86. onContextMenu={handleContextMenu}
  87. onMouseEnter={onMouseEnter}
  88. onMouseLeave={onMouseLeave}
  89. >
  90. {body ? body : null}
  91. {children}
  92. {extra ? <div className={`${prefixCls}-item-extra`}>{extra}</div> : null}
  93. </li>
  94. );
  95. if (this.context && contextGrid) {
  96. content = this.wrapWithGrid(content);
  97. }
  98. return content;
  99. }
  100. }