From 75fb37d1018705ee313c52948fb130d8ba002a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Trzci=C5=84ski?= Date: Mon, 23 Sep 2024 14:51:20 +0200 Subject: [PATCH] [#66130] scroll editor on preview click --- src/MystEditor.js | 9 ++++++++- src/extensions/syncDualPane.js | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/MystEditor.js b/src/MystEditor.js index 48c7b47..5d11467 100644 --- a/src/MystEditor.js +++ b/src/MystEditor.js @@ -12,6 +12,7 @@ import useCollaboration from "./hooks/useCollaboration"; import useComments from "./hooks/useComments"; import ResolvedComments from "./components/Resolved"; import { handlePreviewFold } from "./hooks/markdownFoldButtons"; +import { handlePreviewClickToScroll } from "./extensions/syncDualPane"; if (!window.myst_editor?.isFresh) { resetCache(); @@ -224,7 +225,13 @@ const MystEditor = ({ /> <${FlexWrapper} id="preview-wrapper" - ><${Preview} ref=${preview} mode=${mode} onClick=${(ev) => handlePreviewFold(ev, text.lineMap)} + ><${Preview} + ref=${preview} + mode=${mode} + onClick=${(ev) => { + handlePreviewFold(ev, text.lineMap); + handlePreviewClickToScroll(ev, text.lineMap, preview); + }} ><${PreviewFocusHighlight} className="cm-previewFocus" /> ${mode === "Diff" && html`<${FlexWrapper}><${Diff} root=${parent} oldText=${initialText} text=${text} />`} diff --git a/src/extensions/syncDualPane.js b/src/extensions/syncDualPane.js index 12b5ca7..db1bf3c 100644 --- a/src/extensions/syncDualPane.js +++ b/src/extensions/syncDualPane.js @@ -1,9 +1,10 @@ import { EditorView } from "codemirror"; import { markdownUpdatedStateEffect } from "../hooks/useText"; -import { findNearestElementForLine } from "../hooks/markdownSourceMap"; +import { findNearestElementForLine, getLineById } from "../hooks/markdownSourceMap"; +import { EditorSelection } from "@codemirror/state"; const previewTopPadding = 20; -const debounceTimeout = 50; +const debounceTimeout = 100; export const syncPreviewWithCursor = (lineMap, preview) => { let timeout; @@ -50,3 +51,30 @@ function scrollPreviewElemIntoView({ view, matchingLine, matchingElem, behavior const top = matchingRect.top + preview.scrollTop - elemScrollOffset - previewRect.top + editor.scrollTop; preview.scrollTo({ top, behavior }); } + +export function handlePreviewClickToScroll(/** @type {{ target: HTMLElement }} */ ev, lineMap, preview) { + const id = ev.target.getAttribute("data-line-id"); + if (!id) return; + + const lineNumber = getLineById(lineMap.current, id); + const line = window.myst_editor.main_editor.state.doc.line(lineNumber); + const lineBlock = window.myst_editor.main_editor.lineBlockAt(line.from); + const targetRect = ev.target.getBoundingClientRect(); + const previewRect = preview.current.getBoundingClientRect(); + const editor = window.myst_editor.main_editor.dom.parentElement; + + const editorScrollOffset = targetRect.top; + const top = lineBlock.top - editorScrollOffset + previewRect.top + previewTopPadding; + editor.scrollTo({ + top, + behavior: "smooth", + }); + function setCursor() { + window.myst_editor.main_editor.dispatch({ + selection: EditorSelection.create([EditorSelection.range(line.to, line.to)]), + }); + window.myst_editor.main_editor.focus(); + editor.removeEventListener("scrollend", setCursor); + } + editor.addEventListener("scrollend", setCursor); +}