automagically scroll to the selected line on load

This commit is contained in:
Luck
2021-08-20 22:56:15 +01:00
parent a613659371
commit 34655d04bc

View File

@@ -5,7 +5,7 @@ import EditorPrismStyle from './EditorPrismStyle';
import { getHighlighter } from '../util/highlighting'; import { getHighlighter } from '../util/highlighting';
export default function EditorTextArea({ code, setCode, language, fontSize }) { export default function EditorTextArea({ code, setCode, language, fontSize }) {
const [isSelected, toggleSelected] = useSelectedLine(); const [isSelected, isSelectionMiddle, toggleSelected] = useSelectedLine();
const highlight = getHighlighter(language); const highlight = getHighlighter(language);
function highlightWithLineNumbers(input, grammar) { function highlightWithLineNumbers(input, grammar) {
@@ -16,6 +16,7 @@ export default function EditorTextArea({ code, setCode, language, fontSize }) {
<LineNumber <LineNumber
lineNo={i + 1} lineNo={i + 1}
selected={isSelected(i + 1)} selected={isSelected(i + 1)}
shouldScroll={isSelectionMiddle(i + 1)}
toggleSelected={toggleSelected} toggleSelected={toggleSelected}
/> />
<span dangerouslySetInnerHTML={{ __html: line }} /> <span dangerouslySetInnerHTML={{ __html: line }} />
@@ -54,15 +55,21 @@ export default function EditorTextArea({ code, setCode, language, fontSize }) {
); );
} }
const LineNumber = ({ lineNo, selected, toggleSelected }) => { const LineNumber = ({ lineNo, selected, shouldScroll, toggleSelected }) => {
const autoScroll = useAutoScroll(shouldScroll);
function click(e) { function click(e) {
toggleSelected(lineNo, e.shiftKey); toggleSelected(lineNo, e.shiftKey);
} }
return selected ? ( return selected ? (
<HighlightedLineNumber onClick={click}>{lineNo}</HighlightedLineNumber> <HighlightedLineNumber ref={autoScroll} onClick={click}>
{lineNo}
</HighlightedLineNumber>
) : ( ) : (
<PlainLineNumber onClick={click}>{lineNo}</PlainLineNumber> <PlainLineNumber ref={autoScroll} onClick={click}>
{lineNo}
</PlainLineNumber>
); );
}; };
@@ -150,7 +157,40 @@ function useSelectedLine() {
return lineNo >= Math.min(...selected) && lineNo <= Math.max(...selected); return lineNo >= Math.min(...selected) && lineNo <= Math.max(...selected);
} }
return [isSelected, toggleSelected]; // is a line in the middle of the selection
function isSelectionMiddle(lineNo) {
if (selected[0] === -1) {
return false;
}
if (selected[1] === -1) {
return selected[0] === lineNo;
}
return (
lineNo === Math.floor((Math.min(...selected) + Math.max(...selected)) / 2)
);
}
return [isSelected, isSelectionMiddle, toggleSelected];
}
function useAutoScroll(shouldScroll) {
const [firstRender, setFirstRender] = useState(true);
const ref = useRef(null);
useEffect(() => {
// only attempt to autoscroll if this is the first render.
if (!firstRender) {
return;
}
setFirstRender(false);
if (shouldScroll) {
ref.current.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}, [shouldScroll, firstRender]);
return ref;
} }
const KEYCODE_ENTER = 13; const KEYCODE_ENTER = 13;