Skip to content

Commit

Permalink
Fix scroll on enter (#220)
Browse files Browse the repository at this point in the history
Co-authored-by: Michał Skałka <[email protected]>
  • Loading branch information
BartoszGrajdek and Skalakid authored Mar 12, 2024
1 parent a98b8de commit 7e2002f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
10 changes: 1 addition & 9 deletions src/MarkdownTextInput.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {StyleSheet} from 'react-native';
import * as ParseUtils from './web/parserUtils';
import * as CursorUtils from './web/cursorUtils';
import * as StyleUtils from './styleUtils';
import * as BrowserUtils from './web/browserUtils';
import type * as MarkdownTextInputDecoratorViewNativeComponent from './MarkdownTextInputDecoratorViewNativeComponent';
import './web/MarkdownTextInput.css';
import InputHistory from './web/InputHistory';
Expand Down Expand Up @@ -381,14 +380,7 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
// We need to change normal behavior of "Enter" key to insert a line breaks, to prevent wrapping contentEditable text in <div> tags.
// Thanks to that in every situation we have proper amount of new lines in our parsed text. Without it pressing enter in empty lines will add 2 more new lines.
document.execCommand('insertLineBreak');

const range = window.getSelection();
if (range && !BrowserUtils.isFirefox) {
const scrollMarkerNode = document.createElement('div');
range.getRangeAt(0).insertNode(scrollMarkerNode);
scrollMarkerNode.scrollIntoView();
scrollMarkerNode.remove();
}
CursorUtils.scrollCursorIntoView(divRef.current as HTMLInputElement);
}

if (!e.shiftKey && ((shouldBlurOnSubmit && hostNode !== null) || !multiline)) {
Expand Down
33 changes: 32 additions & 1 deletion src/web/cursorUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as BrowserUtils from './browserUtils';

function findTextNodes(textNodes: Text[], node: ChildNode) {
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push(node as Text);
Expand Down Expand Up @@ -51,6 +53,8 @@ function setCursorPosition(target: HTMLElement, start: number, end: number | nul
selection.removeAllRanges();
selection.addRange(range);
}

scrollCursorIntoView(target as HTMLInputElement);
}

function moveCursorToEnd(target: HTMLElement) {
Expand Down Expand Up @@ -85,4 +89,31 @@ function removeSelection() {
}
}

export {getCurrentCursorPosition, moveCursorToEnd, setCursorPosition, removeSelection};
function scrollCursorIntoView(target: HTMLInputElement) {
if (target.selectionStart === null || !target.value || BrowserUtils.isFirefox) {
return;
}

const selection = window.getSelection();
if (!selection) {
return;
}

const caretRect = selection.getRangeAt(0).getClientRects()[0];
const editableRect = target.getBoundingClientRect();

// Adjust for padding and border
const paddingTop = parseFloat(window.getComputedStyle(target).paddingTop);
const borderTop = parseFloat(window.getComputedStyle(target).borderTopWidth);

if (caretRect && !(caretRect.top >= editableRect.top + paddingTop + borderTop && caretRect.bottom <= editableRect.bottom - 2 * (paddingTop - borderTop))) {
const topToCaret = caretRect.top - editableRect.top;
const inputHeight = editableRect.height;
// Chrome Rects don't include padding & border, so we're adding them manually
const inputOffset = caretRect.height - inputHeight + paddingTop + borderTop + (BrowserUtils.isChromium ? 0 : 4 * (paddingTop + borderTop));

target.scrollTo(0, topToCaret + target.scrollTop + inputOffset);
}
}

export {getCurrentCursorPosition, moveCursorToEnd, setCursorPosition, removeSelection, scrollCursorIntoView};

0 comments on commit 7e2002f

Please sign in to comment.