Commit 73c30107 authored by Steven's avatar Steven

refactor: simplify editor scroll logic

- Extract `scrollToCaret` helper to deduplicate scroll logic
- Unify precise scroll behavior for both manual triggers and auto-scroll
parent 4e34ef22
...@@ -52,6 +52,26 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward ...@@ -52,6 +52,26 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward
} }
}, [handleContentChangeCallback, updateEditorHeight]); }, [handleContentChangeCallback, updateEditorHeight]);
const scrollToCaret = useCallback((options: { force?: boolean } = {}) => {
const editor = editorRef.current;
if (!editor) return;
const { force = false } = options;
const caret = getCaretCoordinates(editor, editor.selectionEnd);
if (force) {
editor.scrollTop = Math.max(0, caret.top - editor.clientHeight / 2);
return;
}
const lineHeight = parseFloat(getComputedStyle(editor).lineHeight) || 24;
const viewportBottom = editor.scrollTop + editor.clientHeight;
// Scroll if cursor is near or beyond bottom edge (within 2 lines)
if (caret.top + lineHeight * 2 > viewportBottom) {
editor.scrollTop = Math.max(0, caret.top - editor.clientHeight / 2);
}
}, []);
useEffect(() => { useEffect(() => {
if (editorRef.current && initialContent) { if (editorRef.current && initialContent) {
editorRef.current.value = initialContent; editorRef.current.value = initialContent;
...@@ -75,12 +95,7 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward ...@@ -75,12 +95,7 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward
getEditor: () => editorRef.current, getEditor: () => editorRef.current,
focus: () => editorRef.current?.focus(), focus: () => editorRef.current?.focus(),
scrollToCursor: () => { scrollToCursor: () => {
const editor = editorRef.current; scrollToCaret({ force: true });
if (!editor) return;
const caret = getCaretCoordinates(editor, editor.selectionEnd);
// Scroll to center cursor vertically
editor.scrollTop = Math.max(0, caret.top - editor.clientHeight / 2);
}, },
insertText: (content = "", prefix = "", suffix = "") => { insertText: (content = "", prefix = "", suffix = "") => {
const editor = editorRef.current; const editor = editorRef.current;
...@@ -143,7 +158,7 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward ...@@ -143,7 +158,7 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward
updateContent(); updateContent();
}, },
}), }),
[updateContent], [updateContent, scrollToCaret],
); );
useImperativeHandle(ref, () => editorActions, [editorActions]); useImperativeHandle(ref, () => editorActions, [editorActions]);
...@@ -155,18 +170,9 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward ...@@ -155,18 +170,9 @@ const Editor = forwardRef(function Editor(props: EditorProps, ref: React.Forward
// Auto-scroll to keep cursor visible when typing // Auto-scroll to keep cursor visible when typing
// See: https://github.com/usememos/memos/issues/5469 // See: https://github.com/usememos/memos/issues/5469
const editor = editorRef.current; scrollToCaret();
const caret = getCaretCoordinates(editor, editor.selectionEnd);
const lineHeight = parseFloat(getComputedStyle(editor).lineHeight) || 24;
// Scroll if cursor is near or beyond bottom edge (within 2 lines)
const viewportBottom = editor.scrollTop + editor.clientHeight;
if (caret.top + lineHeight * 2 > viewportBottom) {
// Scroll to center cursor vertically
editor.scrollTop = Math.max(0, caret.top - editor.clientHeight / 2);
}
} }
}, [handleContentChangeCallback, updateEditorHeight]); }, [handleContentChangeCallback, updateEditorHeight, scrollToCaret]);
// Auto-complete markdown lists when pressing Enter // Auto-complete markdown lists when pressing Enter
useListCompletion({ useListCompletion({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment