Contenteditable fixes
This commit is contained in:
parent
4c57bef21e
commit
f5d1571e91
|
|
@ -59,10 +59,47 @@ export const ContentEditable = ({ value, onInput, ...props }: Props) => {
|
||||||
if (offset !== null) setCaretOffset(el, offset);
|
if (offset !== null) setCaretOffset(el, offset);
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
|
const handleKeyDown: JSX.KeyboardEventHandler<HTMLDivElement> = (e) => {
|
||||||
|
if (e.key !== 'Enter') return;
|
||||||
|
const prevTextContent = (e.target as HTMLDivElement).textContent;
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const sel = window.getSelection();
|
||||||
|
if (!sel || sel.rangeCount === 0) return;
|
||||||
|
|
||||||
|
const range = sel.getRangeAt(0);
|
||||||
|
range.deleteContents();
|
||||||
|
|
||||||
|
const newline = document.createTextNode('\n');
|
||||||
|
range.insertNode(newline);
|
||||||
|
range.setStartAfter(newline);
|
||||||
|
range.collapse(true);
|
||||||
|
|
||||||
|
const nextTextContent = (e.target as HTMLDivElement).textContent;
|
||||||
|
|
||||||
|
// A trailing \n needs a following character to render in pre-line.
|
||||||
|
// If nothing follows the inserted newline, add a sentinel \n so the
|
||||||
|
// new line is visible, then place the caret before it.
|
||||||
|
const atEnd = nextTextContent.startsWith(prevTextContent) && nextTextContent !== prevTextContent && nextTextContent.length === prevTextContent.length + 1 && nextTextContent.at(-1) === '\n';
|
||||||
|
if (atEnd) {
|
||||||
|
const sentinel = document.createTextNode('\n');
|
||||||
|
range.insertNode(sentinel);
|
||||||
|
range.setStartBefore(sentinel);
|
||||||
|
range.collapse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
|
||||||
|
ref.current?.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
contentEditable
|
contentEditable
|
||||||
|
style="white-space: pre"
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
onInput={onInput}
|
onInput={onInput}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue