import { FC, useCallback, useState } from 'react' import { AnyOperation } from '../../../../../types/change' import { useCodeMirrorStateContext, useCodeMirrorViewContext, } from '@/features/source-editor/components/codemirror-editor' import { isSelectionWithinOp } from '../utils/is-selection-within-op' import { EditorSelection } from '@codemirror/state' import { EditorView } from '@codemirror/view' import classNames from 'classnames' import { highlightRanges } from '@/features/source-editor/extensions/ranges' export const ReviewPanelEntry: FC<{ position: number op: AnyOperation top?: number className?: string selectLineOnFocus?: boolean }> = ({ children, position, top, op, className, selectLineOnFocus }) => { const state = useCodeMirrorStateContext() const view = useCodeMirrorViewContext() const [focused, setFocused] = useState(false) const highlighted = isSelectionWithinOp(op, state.selection.main) const focusHandler = useCallback(() => { setTimeout(() => { // without setTimeout, error "EditorView.update are not allowed while an update is in progress" can occur // this can be avoided by using onClick rather than onFocus but it will then not pick up or events for focusing entries if (selectLineOnFocus) { view.dispatch({ selection: EditorSelection.cursor(position), effects: EditorView.scrollIntoView(position, { y: 'center' }), }) } }, 0) setFocused(true) }, [view, position, selectLineOnFocus]) return (
setFocused(false)} onMouseEnter={() => view.dispatch(highlightRanges(op))} onMouseLeave={() => view.dispatch(highlightRanges())} role="button" tabIndex={position + 1} className={classNames( 'review-panel-entry', { 'review-panel-entry-focused': focused, 'review-panel-entry-highlighted': highlighted, }, className )} data-top={top} data-pos={position} style={{ position: top === undefined ? 'relative' : 'absolute', visibility: top === undefined ? 'visible' : 'hidden', transition: 'top .3s, left .1s, right .1s', }} > {children}
) }