-
Notifications
You must be signed in to change notification settings - Fork 240
/
CollaborativeEditor.tsx
84 lines (74 loc) · 2.28 KB
/
CollaborativeEditor.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"use client";
import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Collaboration from "@tiptap/extension-collaboration";
import CollaborationCursor from "@tiptap/extension-collaboration-cursor";
import * as Y from "yjs";
import LiveblocksProvider from "@liveblocks/yjs";
import { useRoom, useSelf } from "@/liveblocks.config";
import { useEffect, useState } from "react";
import { Toolbar } from "./Toolbar";
import styles from "./CollaborativeEditor.module.css";
import { Avatars } from "@/components/Avatars";
// Collaborative text editor with simple rich text, live cursors, and live avatars
export function CollaborativeEditor() {
const room = useRoom();
const [doc, setDoc] = useState<Y.Doc>();
const [provider, setProvider] = useState<any>();
// Set up Liveblocks Yjs provider
useEffect(() => {
const yDoc = new Y.Doc();
const yProvider = new LiveblocksProvider(room, yDoc);
setDoc(yDoc);
setProvider(yProvider);
return () => {
yDoc?.destroy();
yProvider?.destroy();
};
}, [room]);
if (!doc || !provider) {
return null;
}
return <TiptapEditor doc={doc} provider={provider} />;
}
type EditorProps = {
doc: Y.Doc;
provider: any;
};
function TiptapEditor({ doc, provider }: EditorProps) {
// Get user info from Liveblocks authentication endpoint
const userInfo = useSelf((me) => me.info);
// Set up editor with plugins, and place user info into Yjs awareness and cursors
const editor = useEditor({
editorProps: {
attributes: {
// Add styles to editor element
class: styles.editor,
},
},
extensions: [
StarterKit.configure({
// The Collaboration extension comes with its own history handling
history: false,
}),
// Register the document with Tiptap
Collaboration.configure({
document: doc,
}),
// Attach provider and user info
CollaborationCursor.configure({
provider: provider,
user: userInfo,
}),
],
});
return (
<div className={styles.container}>
<div className={styles.editorHeader}>
<Toolbar editor={editor} />
<Avatars />
</div>
<EditorContent editor={editor} className={styles.editorContainer} />
</div>
);
}