Skip to content

Commit d8eecb1

Browse files
committed
feat: de-couple yjs from blocknote/core
1 parent 1a65508 commit d8eecb1

49 files changed

Lines changed: 516 additions & 508 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/content/docs/features/collaboration/comments.mdx

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,28 @@ To enable comments in your editor, you need to:
1616
- Optionally provide a schema for comments and comment editors to use. If left undefined, they will use the [default comment editor schema](https://github.com/TypeCellOS/BlockNote/blob/main/packages/react/src/components/Comments/defaultCommentEditorSchema.ts). See [here](/docs/features/custom-schemas) to find out more about custom schemas.
1717

1818
```tsx
19-
const editor = useCreateBlockNote({
20-
extensions: [
21-
CommentsExtension({
22-
// See below.
23-
threadStore: ...,
24-
// Return user information for the given userIds (see below).
25-
resolveUsers: async (userIds: string[]) => { ... },
26-
// Optional, can be left undefined
27-
schema: BlockNoteSchema.create(...)
28-
}),
19+
import { withCollaboration } from "@blocknote/core/yjs";
20+
21+
const editor = useCreateBlockNote(
22+
withCollaboration({
23+
extensions: [
24+
CommentsExtension({
25+
// See below.
26+
threadStore: ...,
27+
// Return user information for the given userIds (see below).
28+
resolveUsers: async (userIds: string[]) => { ... },
29+
// Optional, can be left undefined
30+
schema: BlockNoteSchema.create(...)
31+
}),
32+
...
33+
],
34+
collaboration: {
35+
// See real-time collaboration docs
36+
...
37+
},
2938
...
30-
],
31-
collaboration: {
32-
// See real-time collaboration docs
33-
...
34-
},
35-
...
36-
});
39+
}),
40+
);
3741
```
3842

3943
**Demo**
@@ -50,7 +54,7 @@ BlockNote comes with several built-in ThreadStore implementations:
5054
The `YjsThreadStore` provides direct Yjs-based storage for comments, storing thread data directly in the Yjs document. This implementation is ideal for simple collaborative setups where all users have write access to the document.
5155

5256
```tsx
53-
import { YjsThreadStore } from "@blocknote/core/comments";
57+
import { YjsThreadStore } from "@blocknote/core/yjs";
5458

5559
const threadStore = new YjsThreadStore(
5660
userId, // The active user's ID
@@ -68,10 +72,8 @@ The `RESTYjsThreadStore` combines Yjs storage with a REST API backend, providing
6872
In this implementation, data is written to the Yjs document via a REST API which can handle access control. Data is still retrieved from the Yjs document directly (after it's been updated by the REST API), this way all comment information automatically syncs between clients using the existing collaboration provider.
6973

7074
```tsx
71-
import {
72-
RESTYjsThreadStore,
73-
DefaultThreadStoreAuth,
74-
} from "@blocknote/core/comments";
75+
import { DefaultThreadStoreAuth } from "@blocknote/core/comments";
76+
import { RESTYjsThreadStore } from "@blocknote/core/yjs";
7577

7678
const threadStore = new RESTYjsThreadStore(
7779
"https://api.example.com/comments", // Base URL for the REST API

docs/content/docs/features/collaboration/index.mdx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,41 @@ Let's see how you can add Multiplayer capabilities to your BlockNote setup, and
2020

2121
_Try the live demo on the [homepage](https://www.blocknotejs.org)_
2222

23-
BlockNote uses [Yjs](https://github.com/yjs/yjs) for this, and you can set it up with the `collaboration` option:
23+
BlockNote uses [Yjs](https://github.com/yjs/yjs) for this, and you can set it up with the `withCollaboration` helper:
2424

2525
```typescript
2626
import * as Y from "yjs";
2727
import { WebrtcProvider } from "y-webrtc";
28+
import { withCollaboration } from "@blocknote/core/yjs";
2829
// ...
2930

3031
const doc = new Y.Doc();
3132

3233
const provider = new WebrtcProvider("my-document-id", doc); // setup a yjs provider (explained below)
33-
const editor = useCreateBlockNote({
34-
// ...
35-
collaboration: {
36-
// The Yjs Provider responsible for transporting updates:
37-
provider,
38-
// Where to store BlockNote data in the Y.Doc:
39-
fragment: doc.getXmlFragment("document-store"),
40-
// Information (name and color) for this user:
41-
user: {
42-
name: "My Username",
43-
color: "#ff0000",
34+
const editor = useCreateBlockNote(
35+
withCollaboration({
36+
// ...
37+
collaboration: {
38+
// The Yjs Provider responsible for transporting updates:
39+
provider,
40+
// Where to store BlockNote data in the Y.Doc:
41+
fragment: doc.getXmlFragment("document-store"),
42+
// Information (name and color) for this user:
43+
user: {
44+
name: "My Username",
45+
color: "#ff0000",
46+
},
47+
// When to show user labels on the collaboration cursor. Set by default to
48+
// "activity" (show when the cursor moves), but can also be set to "always".
49+
showCursorLabels: "activity",
4450
},
45-
// When to show user labels on the collaboration cursor. Set by default to
46-
// "activity" (show when the cursor moves), but can also be set to "always".
47-
showCursorLabels: "activity",
48-
},
49-
// ...
50-
});
51+
// ...
52+
}),
53+
);
5154
```
5255

56+
The `withCollaboration` function accepts all the regular editor options along with a `collaboration` property, and configures your editor for real-time collaboration.
57+
5358
## Yjs Providers
5459

5560
When a user edits the document, an incremental change (or "update") is captured and can be shared between users of your app. You can share these updates by setting up a _Yjs Provider_. In the snipped above, we use [y-webrtc](https://github.com/yjs/y-webrtc) which shares updates over WebRTC (and BroadcastChannel), but you might be interested in different providers for production-ready use cases.

examples/07-collaboration/01-partykit/src/App.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BlockNoteView } from "@blocknote/mantine";
44
import "@blocknote/mantine/style.css";
55
import YPartyKitProvider from "y-partykit/provider";
66
import * as Y from "yjs";
7+
import { withCollaboration } from "@blocknote/core/yjs";
78

89
// Sets up Yjs document and PartyKit Yjs provider.
910
const doc = new Y.Doc();
@@ -15,19 +16,21 @@ const provider = new YPartyKitProvider(
1516
);
1617

1718
export default function App() {
18-
const editor = useCreateBlockNote({
19-
collaboration: {
20-
// The Yjs Provider responsible for transporting updates:
21-
provider,
22-
// Where to store BlockNote data in the Y.Doc:
23-
fragment: doc.getXmlFragment("document-store"),
24-
// Information (name and color) for this user:
25-
user: {
26-
name: "My Username",
27-
color: "#ff0000",
19+
const editor = useCreateBlockNote(
20+
withCollaboration({
21+
collaboration: {
22+
// The Yjs Provider responsible for transporting updates:
23+
provider,
24+
// Where to store BlockNote data in the Y.Doc:
25+
fragment: doc.getXmlFragment("document-store"),
26+
// Information (name and color) for this user:
27+
user: {
28+
name: "My Username",
29+
color: "#ff0000",
30+
},
2831
},
29-
},
30-
});
32+
}),
33+
);
3134

3235
// Renders the editor instance.
3336
return <BlockNoteView editor={editor} />;

examples/07-collaboration/03-y-sweet/src/App.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useYDoc, useYjsProvider, YDocProvider } from "@y-sweet/react";
44
import { useCreateBlockNote } from "@blocknote/react";
55
import { BlockNoteView } from "@blocknote/mantine";
6+
import { withCollaboration } from "@blocknote/core/yjs";
67

78
import "@blocknote/mantine/style.css";
89

@@ -23,13 +24,15 @@ function Document() {
2324
const provider = useYjsProvider();
2425
const doc = useYDoc();
2526

26-
const editor = useCreateBlockNote({
27-
collaboration: {
28-
provider,
29-
fragment: doc.getXmlFragment("blocknote"),
30-
user: { color: "#ff0000", name: "My Username" },
31-
},
32-
});
27+
const editor = useCreateBlockNote(
28+
withCollaboration({
29+
collaboration: {
30+
provider,
31+
fragment: doc.getXmlFragment("blocknote"),
32+
user: { color: "#ff0000", name: "My Username" },
33+
},
34+
}),
35+
);
3336

3437
return <BlockNoteView editor={editor} />;
3538
}

examples/07-collaboration/05-comments/src/App.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import {
44
CommentsExtension,
55
DefaultThreadStoreAuth,
6-
YjsThreadStore,
76
} from "@blocknote/core/comments";
7+
import { withCollaboration, YjsThreadStore } from "@blocknote/core/yjs";
8+
89
import { BlockNoteView } from "@blocknote/mantine";
910
import "@blocknote/mantine/style.css";
1011
import { useCreateBlockNote } from "@blocknote/react";
@@ -74,14 +75,14 @@ function Document() {
7475

7576
// setup the editor with comments and collaboration
7677
const editor = useCreateBlockNote(
77-
{
78+
withCollaboration({
7879
collaboration: {
7980
provider,
8081
fragment: doc.getXmlFragment("blocknote"),
8182
user: { color: getRandomColor(), name: activeUser.username },
8283
},
8384
extensions: [CommentsExtension({ threadStore, resolveUsers })],
84-
},
85+
}),
8586
[activeUser, threadStore],
8687
);
8788

examples/07-collaboration/06-comments-with-sidebar/src/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import {
44
DefaultThreadStoreAuth,
5-
YjsThreadStore,
65
CommentsExtension,
76
} from "@blocknote/core/comments";
7+
import { withCollaboration, YjsThreadStore } from "@blocknote/core/yjs";
88
import { BlockNoteView } from "@blocknote/mantine";
99
import "@blocknote/mantine/style.css";
1010
import {
@@ -77,14 +77,14 @@ export default function App() {
7777

7878
// setup the editor with comments and collaboration
7979
const editor = useCreateBlockNote(
80-
{
80+
withCollaboration({
8181
collaboration: {
8282
provider,
8383
fragment: doc.getXmlFragment("blocknote"),
8484
user: { color: getRandomColor(), name: activeUser.username },
8585
},
8686
extensions: [CommentsExtension({ threadStore, resolveUsers })],
87-
},
87+
}),
8888
[activeUser, threadStore],
8989
);
9090

examples/07-collaboration/07-ghost-writer/src/App.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import "@blocknote/core/fonts/inter.css";
22
import "@blocknote/mantine/style.css";
33
import { BlockNoteView } from "@blocknote/mantine";
44
import { useCreateBlockNote } from "@blocknote/react";
5+
import { withCollaboration } from "@blocknote/core/yjs";
56

67
import YPartyKitProvider from "y-partykit/provider";
78
import * as Y from "yjs";
@@ -38,21 +39,23 @@ const ghostContent =
3839
export default function App() {
3940
const [numGhostWriters, setNumGhostWriters] = useState(1);
4041
const [isPaused, setIsPaused] = useState(false);
41-
const editor = useCreateBlockNote({
42-
collaboration: {
43-
// The Yjs Provider responsible for transporting updates:
44-
provider,
45-
// Where to store BlockNote data in the Y.Doc:
46-
fragment: doc.getXmlFragment("document-store"),
47-
// Information (name and color) for this user:
48-
user: {
49-
name: isGhostWriting
50-
? `Ghost Writer #${ghostWriterIndex}`
51-
: "My Username",
52-
color: isGhostWriting ? "#CCCCCC" : "#00ff00",
42+
const editor = useCreateBlockNote(
43+
withCollaboration({
44+
collaboration: {
45+
// The Yjs Provider responsible for transporting updates:
46+
provider,
47+
// Where to store BlockNote data in the Y.Doc:
48+
fragment: doc.getXmlFragment("document-store"),
49+
// Information (name and color) for this user:
50+
user: {
51+
name: isGhostWriting
52+
? `Ghost Writer #${ghostWriterIndex}`
53+
: "My Username",
54+
color: isGhostWriting ? "#CCCCCC" : "#00ff00",
55+
},
5356
},
54-
},
55-
});
57+
}),
58+
);
5659

5760
useEffect(() => {
5861
if (!isGhostWriting || isPaused) {
@@ -101,7 +104,8 @@ export default function App() {
101104
`${window.location.origin}${window.location.pathname}?room=${roomName}&index=-1`,
102105
"_blank",
103106
);
104-
}}>
107+
}}
108+
>
105109
Ghost Writer in a new window
106110
</button>
107111
</>

examples/07-collaboration/08-forking/src/App.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import "@blocknote/core/fonts/inter.css";
2-
import {} from "@blocknote/core";
3-
import { ForkYDocExtension } from "@blocknote/core/extensions";
2+
import { ForkYDocExtension, withCollaboration } from "@blocknote/core/yjs";
43
import {
54
useCreateBlockNote,
65
useExtension,
@@ -21,19 +20,21 @@ const provider = new YPartyKitProvider(
2120
);
2221

2322
export default function App() {
24-
const editor = useCreateBlockNote({
25-
collaboration: {
26-
// The Yjs Provider responsible for transporting updates:
27-
provider,
28-
// Where to store BlockNote data in the Y.Doc:
29-
fragment: doc.getXmlFragment("document-store"),
30-
// Information (name and color) for this user:
31-
user: {
32-
name: "My Username",
33-
color: "#ff0000",
23+
const editor = useCreateBlockNote(
24+
withCollaboration({
25+
collaboration: {
26+
// The Yjs Provider responsible for transporting updates:
27+
provider,
28+
// Where to store BlockNote data in the Y.Doc:
29+
fragment: doc.getXmlFragment("document-store"),
30+
// Information (name and color) for this user:
31+
user: {
32+
name: "My Username",
33+
color: "#ff0000",
34+
},
3435
},
35-
},
36-
});
36+
}),
37+
);
3738
const forkYDocPlugin = useExtension(ForkYDocExtension, { editor });
3839
const isForked = useExtensionState(ForkYDocExtension, {
3940
editor,

examples/07-collaboration/09-comments-testing/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import {
44
CommentsExtension,
55
DefaultThreadStoreAuth,
6-
YjsThreadStore,
76
} from "@blocknote/core/comments";
7+
import { YjsThreadStore } from "@blocknote/core/yjs";
88
import { BlockNoteView } from "@blocknote/mantine";
99
import "@blocknote/mantine/style.css";
1010
import { useCreateBlockNote } from "@blocknote/react";

0 commit comments

Comments
 (0)