dropdownItem.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import React from 'react';
  2. import cls from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import { cssClasses as css, strings } from '@douyinfe/semi-foundation/dropdown/constants';
  5. import DropdownContext from './context';
  6. import BaseComponent from '../_base/baseComponent';
  7. import { IconTick } from '@douyinfe/semi-icons';
  8. import { noop } from 'lodash';
  9. import type { BaseProps } from '../_base/baseComponent';
  10. import type { DropdownContextType } from './context';
  11. export type Type = 'primary' | 'secondary' | 'tertiary' | 'warning' | 'danger';
  12. export interface DropdownItemProps extends BaseProps {
  13. disabled?: boolean;
  14. selected?: boolean;
  15. onClick?: React.MouseEventHandler<HTMLLIElement>;
  16. onMouseEnter?: React.MouseEventHandler<HTMLLIElement>;
  17. onMouseLeave?: React.MouseEventHandler<HTMLLIElement>;
  18. onContextMenu?: React.MouseEventHandler<HTMLLIElement>;
  19. forwardRef?: (ele: HTMLLIElement) => void;
  20. type?: Type;
  21. active?: boolean;
  22. icon?: React.ReactNode;
  23. onKeyDown?: (e: React.KeyboardEvent) => void;
  24. showTick?: boolean;
  25. /** internal prop, please do not use */
  26. hover?: boolean
  27. }
  28. const prefixCls = css.PREFIX;
  29. class DropdownItem extends BaseComponent<DropdownItemProps> {
  30. static propTypes = {
  31. children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
  32. name: PropTypes.string,
  33. disabled: PropTypes.bool,
  34. selected: PropTypes.bool,
  35. onClick: PropTypes.func,
  36. onMouseEnter: PropTypes.func,
  37. onMouseLeave: PropTypes.func,
  38. onContextMenu: PropTypes.func,
  39. className: PropTypes.string,
  40. style: PropTypes.object,
  41. forwardRef: PropTypes.func,
  42. type: PropTypes.oneOf(strings.ITEM_TYPE),
  43. active: PropTypes.bool,
  44. icon: PropTypes.node,
  45. };
  46. static contextType = DropdownContext;
  47. static elementType: string;
  48. context: DropdownContextType;
  49. static defaultProps = {
  50. disabled: false,
  51. divided: false,
  52. selected: false,
  53. onMouseEnter: noop,
  54. onMouseLeave: noop,
  55. forwardRef: noop,
  56. };
  57. render() {
  58. const {
  59. children,
  60. disabled,
  61. className,
  62. forwardRef,
  63. style,
  64. type,
  65. active,
  66. icon,
  67. onKeyDown,
  68. showTick,
  69. hover
  70. } = this.props;
  71. const { showTick: contextShowTick } = this.context;
  72. const realShowTick = contextShowTick ?? showTick;
  73. const itemclass = cls(className, {
  74. [`${prefixCls}-item`]: true,
  75. [`${prefixCls}-item-disabled`]: disabled,
  76. [`${prefixCls}-item-hover`]: hover,
  77. [`${prefixCls}-item-withTick`]: realShowTick,
  78. [`${prefixCls}-item-${type}`]: type,
  79. [`${prefixCls}-item-active`]: active,
  80. });
  81. const events = {};
  82. if (!disabled) {
  83. ['onClick', 'onMouseEnter', 'onMouseLeave', 'onContextMenu'].forEach(eventName => {
  84. const isInAnotherDropdown = this.context.level !== 1;
  85. if (isInAnotherDropdown && eventName === "onClick") {
  86. events["onMouseDown"] = (e: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
  87. if (e.button === 0) {
  88. this.props[eventName]?.(e);
  89. }
  90. };
  91. } else {
  92. events[eventName] = this.props[eventName];
  93. }
  94. });
  95. }
  96. let tick = null;
  97. switch (true) {
  98. case realShowTick && active:
  99. tick = <IconTick/>;
  100. break;
  101. case realShowTick && !active:
  102. tick = <IconTick style={{ color: 'transparent' }}/>;
  103. break;
  104. default:
  105. tick = null;
  106. break;
  107. }
  108. let iconContent = null;
  109. if (icon) {
  110. iconContent = (
  111. <div className={`${prefixCls}-item-icon`}>
  112. {icon}
  113. </div>
  114. );
  115. }
  116. return (
  117. <li role="menuitem" tabIndex={-1} aria-disabled={disabled} {...events} onKeyDown={onKeyDown}
  118. ref={ref => forwardRef(ref)} className={itemclass} style={style} {...this.getDataAttr(this.props)}>
  119. {tick}
  120. {iconContent}
  121. {children}
  122. </li>
  123. );
  124. }
  125. }
  126. DropdownItem.elementType = 'Dropdown.Item';
  127. export default DropdownItem;