item.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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, { ListContextValue } 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. children?: React.ReactNode;
  15. style?: React.CSSProperties;
  16. onClick?: React.MouseEventHandler<HTMLLIElement>;
  17. onRightClick?: React.MouseEventHandler<HTMLLIElement>;
  18. onMouseLeave?: React.MouseEventHandler<HTMLLIElement>;
  19. onMouseEnter?: React.MouseEventHandler<HTMLLIElement>
  20. }
  21. const prefixCls = cssClasses.PREFIX;
  22. export default class ListItem extends PureComponent<ListItemProps> {
  23. static contextType = ListContext;
  24. static propTypes = {
  25. extra: PropTypes.node,
  26. header: PropTypes.node,
  27. main: PropTypes.node,
  28. align: PropTypes.oneOf(strings.ALIGN),
  29. className: PropTypes.string,
  30. children: PropTypes.node,
  31. style: PropTypes.object,
  32. onClick: PropTypes.func,
  33. onRightClick: PropTypes.func,
  34. onMouseEnter: PropTypes.func,
  35. onMouseLeave: PropTypes.func,
  36. };
  37. static defaultProps = {
  38. align: 'flex-start',
  39. onMouseEnter: noop,
  40. onMouseLeave: noop,
  41. };
  42. context: ListContextValue;
  43. wrapWithGrid(content: React.ReactNode) {
  44. const { grid } = this.context;
  45. const { gutter, justify, type, align, ...rest } = grid;
  46. return (
  47. <Col {...rest}>
  48. {content}
  49. </Col>
  50. );
  51. }
  52. render() {
  53. const {
  54. header,
  55. main,
  56. className,
  57. style,
  58. extra,
  59. children,
  60. align,
  61. onClick,
  62. onRightClick,
  63. onMouseEnter,
  64. onMouseLeave
  65. } = this.props;
  66. const { onRightClick: contextOnRightClick, onClick: contextOnClick, grid: contextGrid } = this.context;
  67. const handleContextMenu = onRightClick ? onRightClick : contextOnRightClick;
  68. const handleClick = onClick ? onClick : contextOnClick;
  69. const itemCls = cls(`${prefixCls}-item`, className);
  70. const bodyCls = cls(`${prefixCls}-item-body`,
  71. {
  72. [`${prefixCls}-item-body-${align}`]: align,
  73. }
  74. );
  75. let body;
  76. if (header || main) {
  77. body = (
  78. <div className={bodyCls}>
  79. {header ? <div className={`${prefixCls}-item-body-header`}>{header}</div> : null}
  80. {main ? <div className={`${prefixCls}-item-body-main`}>{main}</div> : null}
  81. </div>
  82. );
  83. }
  84. let content = (
  85. // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
  86. <li
  87. className={itemCls}
  88. style={style}
  89. onClick={handleClick}
  90. onContextMenu={handleContextMenu}
  91. onMouseEnter={onMouseEnter}
  92. onMouseLeave={onMouseLeave}
  93. >
  94. {body ? body : null}
  95. {children}
  96. {extra ? <div className={`${prefixCls}-item-extra`}>{extra}</div> : null}
  97. </li>
  98. );
  99. if (this.context && contextGrid) {
  100. content = this.wrapWithGrid(content);
  101. }
  102. return content;
  103. }
  104. }