Skip to content

Commit bd85a1c

Browse files
authored
feat(bundle): scroll to top of screen when scrolling to line in markup mode (#350)
1 parent 0d4d63b commit bd85a1c

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

src/bundle/Editor.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {ReactNode} from 'react';
22

33
import type {Extension as CodemirrorExtension} from '@codemirror/state';
4+
import {EditorView as CMEditorView} from '@codemirror/view';
45
import {TextSelection} from 'prosemirror-state';
56
import {EditorView as PMEditorView} from 'prosemirror-view';
67

@@ -477,12 +478,33 @@ export class EditorImpl extends SafeEventEmitter<EventMapInt> implements EditorI
477478
cmLine = Math.max(cmLine, 1);
478479
cmLine = Math.min(cmLine, view.state.doc.lines);
479480

481+
const yMargin = getTopOffset();
482+
const anchor = view.state.doc.line(cmLine).from;
480483
view.dispatch({
481484
scrollIntoView: true,
482-
selection: {anchor: view.state.doc.line(cmLine).from},
485+
selection: {anchor},
486+
effects: [
487+
CMEditorView.scrollIntoView(anchor, {y: 'start', x: 'start', yMargin}),
488+
],
483489
});
484490

485491
break;
492+
493+
// eslint-disable-next-line no-inner-declarations
494+
function getTopOffset() {
495+
const TOOLBAR_HEIGHT = 36; //px
496+
const TOOLBAR_BOTTOM_OFFSET = 8; // px
497+
const TOOLBAR_TOP_ADDITIONAL_OFFSET = 8; // px
498+
const TOOLBAR_TOP_OFFSET_VAR = '--g-md-toolbar-sticky-offset';
499+
500+
const topOffsetValue = window
501+
.getComputedStyle(view.dom)
502+
.getPropertyValue(TOOLBAR_TOP_OFFSET_VAR);
503+
const toolbarTopOffset =
504+
calculateCSSNumberValue(topOffsetValue) + TOOLBAR_TOP_ADDITIONAL_OFFSET;
505+
506+
return toolbarTopOffset + TOOLBAR_HEIGHT + TOOLBAR_BOTTOM_OFFSET;
507+
}
486508
}
487509
case 'wysiwyg': {
488510
const node = this.wysiwygEditor.dom.querySelector(`[data-line="${line}"]`);
@@ -512,3 +534,17 @@ export class EditorImpl extends SafeEventEmitter<EventMapInt> implements EditorI
512534
return serializedEditorMarkup?.trim() !== wysiwygValue.trim();
513535
}
514536
}
537+
538+
function calculateCSSNumberValue(cssValue: string): number {
539+
const tmp = document.createElement('div');
540+
tmp.style.position = 'absolute';
541+
tmp.style.top = '-99999px';
542+
tmp.style.left = '-99999px';
543+
tmp.style.width = `calc(${cssValue})`;
544+
545+
document.body.appendChild(tmp);
546+
const value = tmp.getBoundingClientRect().width;
547+
tmp.remove();
548+
549+
return value;
550+
}

0 commit comments

Comments
 (0)