ModuleItem.jsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import {Component} from 'react';
  2. import cls from 'classnames';
  3. import escapeRegExp from 'escape-string-regexp';
  4. import {filesize} from 'filesize';
  5. import escape from 'lodash.escape';
  6. import s from './ModuleItem.css';
  7. export default class ModuleItem extends Component {
  8. state = {
  9. visible: true,
  10. };
  11. get itemType() {
  12. const {module} = this.props;
  13. if (!module.path) {
  14. return 'chunk';
  15. }
  16. return module.groups ? 'folder' : 'module';
  17. }
  18. get titleHtml() {
  19. let html;
  20. const {module} = this.props;
  21. const title = module.path || module.label;
  22. const term = this.props.highlightedText;
  23. if (term) {
  24. const regexp =
  25. term instanceof RegExp
  26. ? new RegExp(term.source, 'igu')
  27. : new RegExp(`(?:${escapeRegExp(term)})+`, 'iu');
  28. let match;
  29. let lastMatch;
  30. do {
  31. lastMatch = match;
  32. match = regexp.exec(title);
  33. } while (match);
  34. if (lastMatch) {
  35. html =
  36. escape(title.slice(0, lastMatch.index)) +
  37. `<strong>${escape(lastMatch[0])}</strong>` +
  38. escape(title.slice(lastMatch.index + lastMatch[0].length));
  39. }
  40. }
  41. if (!html) {
  42. html = escape(title);
  43. }
  44. return html;
  45. }
  46. get invisibleHint() {
  47. const itemType = this.itemType.charAt(0).toUpperCase() + this.itemType.slice(1);
  48. return `${itemType} is not rendered in the treemap because it's too small.`;
  49. }
  50. get isVisible() {
  51. const {isVisible} = this.props;
  52. return isVisible ? isVisible(this.props.module) : true;
  53. }
  54. handleClick = () => this.props.onClick(this.props.module);
  55. handleMouseEnter = () => {
  56. if (this.props.isVisible) {
  57. this.setState({visible: this.isVisible});
  58. }
  59. };
  60. render() {
  61. const {module, showSize} = this.props;
  62. const invisible = !this.state.visible;
  63. const classes = cls(s.container, s[this.itemType], {
  64. [s.invisible]: invisible,
  65. });
  66. return (
  67. <div
  68. className={classes}
  69. title={invisible ? this.invisibleHint : null}
  70. onClick={this.handleClick}
  71. onMouseEnter={this.handleMouseEnter}
  72. onMouseLeave={this.handleMouseLeave}
  73. >
  74. <span dangerouslySetInnerHTML={{__html: this.titleHtml}} />
  75. {showSize && [
  76. ' (',
  77. <strong key={module[showSize]}>{filesize(module[showSize])}</strong>,
  78. ')',
  79. ]}
  80. </div>
  81. );
  82. }
  83. }