y-draft-js
v1.8.0
Published
Draft-js editor bindings for Yjs
Downloads
13
Readme
y-draft-js
Draft.js editor bindings for Yjs, a modern, fast, and powerful JavaScript library for collaborative editing.
Awareness has saved SelectionState.
usage
- install
npm install y-draft-js
- bindYdoc
const ydoc = new Y.Doc();
const provider = new WebsocketProvider(
'ws://localhost:1234', // your websockt url
id,
ydoc,
{
connect: false,
}
);
- bind Draft editor & connect to ydoc
import { DraftBinding } from 'y-draft-js';
const draftBind = new DraftBinding({
ydoc,
rawPath: 'raw', // your draft-js raw path(or [], exp: ['content', 'raw'])
editor: editorRef.current, // draft-js editor ref , or plugin editor ref, or null(You can bind the editor asynchronously, exp: draftBind.bindEditor(editorRef.current))
provider,
});
provider.connect();
- destroy the binding on departure
draftBind.destroy();
awareness
All clients are stored in the provider.awareness
.
provider.awareness.getStates().forEach(state => {
console.log(state.selection); // selection state by all clients
});
undoManager
draftBind.undo
and draftBind.redo
can be used to undo and redo. if you want to jump to the specified step, you can set allowUndo = false
in editorState
const newEditorState = EditorState.push(
editorState,
newContentState,
'insert-characters'
);
newEditorState.allowUndo = false; // not allow undo [y-draft-js]
this.setState({ editorState: newEditorState });
exp:
handleKeyCommand = (command, editorState) => {
if(command === 'y-draft-undo') {
this.draftBind?.undo();
return 'handled';
}
if(command === 'y-draft-redo') {
this.draftBind?.redo();
return 'handled';
}
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this._onChange(newState);
return true;
}
return false;
};
myKeyBindingFn(e) {
const cmd = getDefaultKeyBinding(e);
if (cmd === 'undo') return 'y-draft-undo';
if (cmd === 'redo') return 'y-draft-redo';
if (cmd) return cmd;
}
<Editor
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.myKeyBindingFn}
onChange={this._onChange}
ref={ref => (this.editorRef = ref)}
/>
API
Because
raw
is not suitable for diff calculation save, so it did a layer of RAW conversion, conversion methods will be introduced
- getRawBySharedData
const raw = getRawBySharedData(path, ymap); // get raw data by ymap path
- toRawSharedData
ymap.set('content', toRawSharedData(raw)); // set raw data to ymap path
- getTargetByPath
const target = getTargetByPath(path, ymap); // get target by ymap path
- onTargetSync
const cancel = onTargetSync(path, ydoc, callback); // The callback is triggered when the listening target has a value or target is replaced (This is useful when you are not sure if the data under the destination path exists)
// cancel the listener when component unmount
cancel();
- toSyncElement
ymap.set('content', toSyncElement(data)); // set data to ydoc (Depth conversion of this data,if the data contains raw, it will be converted to ydoc raw)
develop
- start websoket-server
npm run start:server
- start demo
npm run dev