I’m not aware of anything, but I thought it was an interesting question so I put together a minimal demo. It has one additional dependency on fast-diff.
Demo: View in CodeSandbox
import * as Y from "yjs";
import { useState } from "react";
import diff from "fast-diff";
const doc = new Y.Doc();
const ytext = doc.getText();
/** A hook to read and set a YText value. */
function useText(ytext) {
const [text, setText] = useState(ytext.toString());
ytext.observe(() => {
setText(ytext.toString());
});
const setYText = (textNew) => {
const delta = diffToDelta(diff(text, textNew));
ytext.applyDelta(delta);
};
return [text, setYText];
}
/** Convert a fast-diff result to a YJS delta. */
function diffToDelta(diffResult) {
return diffResult.map(([op, value]) =>
op === diff.INSERT
? { insert: value }
: op === diff.EQUAL
? { retain: value.length }
: op === diff.DELETE
? { delete: value.length }
: null
);
}
export default function App() {
const [text, setText] = useText(ytext);
return (
<div>
<input
onInput={(e) => {
setText(e.target.value);
}}
/>
<p>Text: {text}</p>
</div>
);
}