organic_ast_explorer/src/Editor.tsx

56 lines
1.4 KiB
TypeScript

import React, { useEffect, useRef } from "react";
import { Highlight } from "./highlight";
import { buildShadow } from "./shadow";
import styles from "./Editor.module.css";
interface EditorProps {
value: string;
setValue: Function;
highlights: Highlight[];
clearHighlights: Function;
}
function Editor({
value,
setValue,
highlights,
clearHighlights,
}: EditorProps): React.ReactNode {
function handleChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
setValue(event.target.value);
clearHighlights();
}
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const shadowRef = useRef<HTMLDivElement>(null);
function onTextAreaScroll() {
if (shadowRef.current !== null && textAreaRef.current !== null) {
const textAreaScrollTop = textAreaRef.current.scrollTop;
shadowRef.current.scrollTop = textAreaScrollTop;
}
}
useEffect(() => {
// Make sure the text area and shadow div start out in sync.
onTextAreaScroll();
}, []);
return (
<div className={styles.EditorTextWrapper}>
<textarea
ref={textAreaRef}
onChange={handleChange}
className={styles.EditorTextArea}
value={value}
onScroll={onTextAreaScroll}
spellCheck={false}
/>
<div ref={shadowRef} className={styles.EditorUnderlay}>
{buildShadow(highlights, value)}
<br />
</div>
</div>
);
}
export default Editor;