item.tsx 3.7 KB

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