index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import React, { ReactNode } from 'react';
  2. import classNames from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import HotKeysFoudation, { HotKeysAdapter } from '@douyinfe/semi-foundation/hotKeys/foundation';
  5. import { cssClasses, Keys } from '@douyinfe/semi-foundation/hotKeys/constants';
  6. import BaseComponent from '../_base/baseComponent';
  7. import { noop } from 'lodash';
  8. import '@douyinfe/semi-foundation/hotKeys/hotKeys.scss';
  9. const prefixCls = cssClasses.PREFIX;
  10. export { Keys };
  11. export interface HotKeysProps {
  12. hotKeys?: KeyboardEvent["key"][];
  13. content?: string[];
  14. onClick?: () => void;
  15. clickable?: boolean;
  16. disabled?: boolean;
  17. render?: () => ReactNode | ReactNode;
  18. getListenerTarget?: () => HTMLElement;
  19. className?: string;
  20. style?: React.CSSProperties
  21. }
  22. export interface HotKeysState {
  23. disabled: boolean
  24. }
  25. class HotKeys extends BaseComponent<HotKeysProps, HotKeysState> {
  26. static propTypes = {
  27. hotKeys: PropTypes.arrayOf(PropTypes.string),
  28. content: PropTypes.arrayOf(PropTypes.string),
  29. onClick: PropTypes.func,
  30. clickable: PropTypes.bool,
  31. disabled: PropTypes.bool,
  32. render: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
  33. getListenerTarget: PropTypes.func,
  34. className: PropTypes.string,
  35. style: PropTypes.object,
  36. };
  37. static defaultProps: Partial<HotKeysProps> = {
  38. hotKeys: null,
  39. content: null,
  40. onClick: noop,
  41. clickable: false,
  42. disabled: false,
  43. render: undefined,
  44. getListenerTarget: () => document.body,
  45. className: '',
  46. style: null,
  47. };
  48. constructor(props: HotKeysProps) {
  49. super(props);
  50. this.state = {
  51. disabled: false
  52. };
  53. this.foundation = new HotKeysFoudation(this.adapter);
  54. }
  55. componentDidMount() {
  56. this.foundation.init();
  57. }
  58. componentDidUpdate(_prevProps: HotKeysProps) {
  59. }
  60. componentWillUnmount() {
  61. this.foundation.destroy();
  62. }
  63. get adapter(): HotKeysAdapter<HotKeysProps, HotKeysState> {
  64. return {
  65. ...super.adapter,
  66. notifyClick: () => {
  67. if (this.props.onClick) {
  68. this.props.onClick();
  69. }
  70. },
  71. getListenerTarget: () => {
  72. if (this.props.getListenerTarget) {
  73. return this.props.getListenerTarget();
  74. }
  75. return document.body;
  76. },
  77. };
  78. }
  79. render() {
  80. const { hotKeys, content, onClick, clickable, disabled, render, getListenerTarget, className, style, ...rest } = this.props;
  81. if (typeof render !== 'undefined') {
  82. if (render === null || (typeof render === 'function' && render() === null)) {
  83. return null;
  84. }
  85. return (
  86. <div
  87. onClick={clickable ? onClick : noop}
  88. className={classNames(prefixCls, className)}
  89. style={style}>
  90. { typeof render === 'function' ? render() : render }
  91. </div>
  92. );
  93. }
  94. const renderContent = content ?? hotKeys;
  95. return (
  96. <div
  97. onClick={clickable ? onClick : noop}
  98. className={classNames(prefixCls, className)}
  99. style={style}
  100. >
  101. {renderContent.map((key: KeyboardEvent["key"], index) => {
  102. return index === 0 ?
  103. (<span key={index}>
  104. <span className={prefixCls + '-content'}>{key}</span>
  105. </span>)
  106. :
  107. (<span key={index}>
  108. <span className={prefixCls + '-split'}>+</span>
  109. <span className={prefixCls + '-content'}>{key}</span>
  110. </span>);
  111. })}
  112. </div>
  113. );
  114. }
  115. }
  116. export default HotKeys;