import { useState, useEffect, useRef, memo } from 'react' import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed' import classNames from 'classnames' import OutlineList from './outline-list' import { OutlineItemToggleButton } from '@/features/outline/components/outline-item-toggle-button' import { OutlineItemData } from '@/features/ide-react/types/outline' const OutlineItem = memo(function OutlineItem({ outlineItem, jumpToLine, highlightedLine, matchesHighlightedLine, containsHighlightedLine, }: { outlineItem: OutlineItemData jumpToLine: (line: number, syncToPdf: boolean) => void highlightedLine?: number | null matchesHighlightedLine?: boolean containsHighlightedLine?: boolean }) { const [expanded, setExpanded] = useState(true) const titleElementRef = useRef(null) const isHighlightedRef = useRef(false) const mainItemClasses = classNames('outline-item', { 'outline-item-no-children': !outlineItem.children, }) const hasHighlightedChild = !expanded && containsHighlightedLine const isHighlighted = matchesHighlightedLine || hasHighlightedChild const itemLinkClasses = classNames('outline-item-link', { 'outline-item-link-highlight': isHighlighted, }) function handleOutlineItemLinkClick(event: React.MouseEvent) { const syncToPdf = event.detail === 2 // double-click = sync to PDF jumpToLine(outlineItem.line, syncToPdf) } useEffect(() => { const wasHighlighted = isHighlightedRef.current isHighlightedRef.current = !!isHighlighted if (!wasHighlighted && isHighlighted && titleElementRef.current) { scrollIntoViewIfNeeded(titleElementRef.current, { scrollMode: 'if-needed', block: 'center', }) } }, [isHighlighted, titleElementRef, isHighlightedRef]) // don't set the aria-expanded attribute when there are no children const ariaExpandedValue = outlineItem.children ? expanded : undefined return (
  • {!!outlineItem.children && ( )}
    {expanded && outlineItem.children ? ( // highlightedLine is only provided to this list if the list contains // the highlighted line. This means that whenever the list does not // contain the highlighted line, the props provided to it are the same // and the component can be memoized. ) : null}
  • ) }) export default OutlineItem