outline-list.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import PropTypes from 'prop-types'
  2. import classNames from 'classnames'
  3. import OutlineItem from './outline-item'
  4. import { memo } from 'react'
  5. function getChildrenLines(children) {
  6. return (children || [])
  7. .map(child => {
  8. return getChildrenLines(child.children).concat(child.line)
  9. })
  10. .flat()
  11. }
  12. const OutlineList = memo(function OutlineList({
  13. outline,
  14. jumpToLine,
  15. isRoot,
  16. highlightedLine,
  17. containsHighlightedLine,
  18. }) {
  19. const listClasses = classNames('outline-item-list', {
  20. 'outline-item-list-root': isRoot,
  21. })
  22. return (
  23. <ul className={listClasses} role={isRoot ? 'tree' : 'group'}>
  24. {outline.map((outlineItem, idx) => {
  25. const matchesHighlightedLine =
  26. containsHighlightedLine && highlightedLine === outlineItem.line
  27. const itemContainsHighlightedLine =
  28. containsHighlightedLine &&
  29. getChildrenLines(outlineItem.children).includes(highlightedLine)
  30. // highlightedLine is only provided to the item if the item matches or
  31. // contains the highlighted line. This means that whenever the item does
  32. // not contain the highlighted line, the props provided to it are the
  33. // same and the component can be memoized.
  34. return (
  35. <OutlineItem
  36. key={`${outlineItem.level}-${idx}`}
  37. outlineItem={outlineItem}
  38. jumpToLine={jumpToLine}
  39. highlightedLine={
  40. matchesHighlightedLine || itemContainsHighlightedLine
  41. ? highlightedLine
  42. : null
  43. }
  44. matchesHighlightedLine={matchesHighlightedLine}
  45. containsHighlightedLine={itemContainsHighlightedLine}
  46. />
  47. )
  48. })}
  49. </ul>
  50. )
  51. })
  52. OutlineList.propTypes = {
  53. outline: PropTypes.array.isRequired,
  54. jumpToLine: PropTypes.func.isRequired,
  55. isRoot: PropTypes.bool,
  56. highlightedLine: PropTypes.number,
  57. containsHighlightedLine: PropTypes.bool,
  58. }
  59. export default OutlineList