This commit is contained in:
2025-08-10 17:32:57 -07:00
parent 17c80bab96
commit 19e7675c52
+19 -18
View File
@@ -5,8 +5,8 @@ import * as Y from 'yjs';
const app = document.querySelector<HTMLDivElement>('#app')!; const app = document.querySelector<HTMLDivElement>('#app')!;
app.innerHTML = ` app.innerHTML = `
<h1>Story Editor</h1> <h1>Synced editors</h1>
<p>Your TypeScript + Vite app is ready!</p> <p>Network delay (simulated) of 2.5 to 5 seconds.</p>
<textarea id="ta1" rows=10 cols=80></textarea> <textarea id="ta1" rows=10 cols=80></textarea>
<br> <br>
<br> <br>
@@ -19,24 +19,27 @@ const ta2 = document.getElementById('ta2') as HTMLTextAreaElement;
function bind(text: Y.Text, el: HTMLTextAreaElement) { function bind(text: Y.Text, el: HTMLTextAreaElement) {
el.value = text.toString(); el.value = text.toString();
const getRelative = () => [ // When the selection changes, persist its relative location
Y.createRelativePositionFromTypeIndex(text, el.selectionStart), let savedSelection: Y.RelativePosition[];
Y.createRelativePositionFromTypeIndex(text, el.selectionEnd), const saveSelection = () =>
]; (savedSelection = [el.selectionStart, el.selectionEnd].map((i) =>
let [selectionStart, selectionEnd] = getRelative(); Y.createRelativePositionFromTypeIndex(text, i)
const getAbsolute = () => [ ));
Y.createAbsolutePositionFromRelativePosition(selectionStart, text.doc!), saveSelection();
Y.createAbsolutePositionFromRelativePosition(selectionEnd, text.doc!),
];
const saveSelection = () => {
[selectionStart, selectionEnd] = getRelative();
};
el.addEventListener('selectionchange', saveSelection); el.addEventListener('selectionchange', saveSelection);
el.addEventListener('click', saveSelection); el.addEventListener('click', saveSelection);
el.addEventListener('keyup', saveSelection); el.addEventListener('keyup', saveSelection);
el.addEventListener('mouseup', saveSelection); el.addEventListener('mouseup', saveSelection);
// When the doc/textarea updates, set selection to the equivalent of what it was before
const restoreSelection = () => {
const [newStart, newEnd] = savedSelection.map(
(x) => Y.createAbsolutePositionFromRelativePosition(x, text.doc!)?.index
);
el.selectionStart = newStart ?? el.selectionStart;
el.selectionEnd = newEnd ?? el.selectionEnd;
};
const handleInput = () => { const handleInput = () => {
let prev = text.toString(); let prev = text.toString();
let curr = el.value; let curr = el.value;
@@ -65,9 +68,7 @@ function bind(text: Y.Text, el: HTMLTextAreaElement) {
text.doc!.on('update', () => { text.doc!.on('update', () => {
el.value = text.toString(); el.value = text.toString();
const [newStart, newEnd] = getAbsolute().map((x) => x?.index); restoreSelection();
el.selectionStart = newStart ?? el.selectionStart;
el.selectionEnd = newEnd ?? el.selectionEnd;
}); });
} }