Skip to content

Commit 887650f

Browse files
committed
Tiptap and document debounce interval
1 parent aa993e1 commit 887650f

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

README.md

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ synced to the cloud. The data lives in your Convex database, and can be stored
1010
alongside the rest of your app's data.
1111

1212
Just configure your editor features, add this component to your Convex backend,
13-
and use the `useTipTapSync` React hook.
13+
and use the `useTiptapSync` React hook.
1414

1515
This is a [Convex Component](https://convex.dev/components) that syncs a
1616
[ProseMirror](https://prosemirror.net/) document between clients via a
17-
[TipTap](https://tiptap.dev/) extension.
17+
[Tiptap](https://tiptap.dev/) extension.
1818

1919
Example usage, see [below](#usage) for more details:
2020

2121
```tsx
2222
function CollaborativeEditor() {
23-
const sync = useTipTapSync(api.prosemirrorSync, "some-id");
23+
const sync = useTiptapSync(api.prosemirrorSync, "some-id");
2424
return sync.isLoading ? (
2525
<p>Loading...</p>
2626
) : sync.initialContent !== null ? (
@@ -40,7 +40,7 @@ Features:
4040

4141
- Safely merges changes between clients via operational transformations (OT).
4242
- Simple React hook to fetch the initial document and keep it in sync via a
43-
TipTap extension.
43+
Tiptap extension.
4444
- Server-side entrypoints for authorizing reads, writes, and snapshots.
4545
- Create a new document, online or offline.
4646
- Debounced snapshots allow new clients to avoid reading the full history.
@@ -64,7 +64,7 @@ Future that could be added later:
6464
- Warning when closing tab with unsynced changes (works by default?).
6565
- Vacuuming controls for old deltas & snapshots.
6666
- Add a BlockNote convenience wrapper.
67-
- Convert it to a ProseMirror plugin instead of a TipTap extension, so raw
67+
- Convert it to a ProseMirror plugin instead of a Tiptap extension, so raw
6868
ProseMirror usecases can also use it.
6969
- Handling edge cases, such as old clients with local changes on top of an older
7070
version of the document where the steps necessary for them to rebase their
@@ -126,7 +126,7 @@ export default app;
126126
## Usage
127127

128128
To use the component, you expose the API in a file in your `convex/` folder, and
129-
use the `useTipTapSync` hook in your React components, passing in a reference to
129+
use the `useTiptapSync` hook in your React components, passing in a reference to
130130
the API you defined. For this example, we'll create the API in
131131
`convex/example.ts`.
132132

@@ -147,21 +147,21 @@ export const {
147147
});
148148
```
149149

150-
In your React components, you can use the `useTipTapSync` hook to fetch the
151-
initial document and keep it in sync via a TipTap extension. **Note**: This
150+
In your React components, you can use the `useTiptapSync` hook to fetch the
151+
initial document and keep it in sync via a Tiptap extension. **Note**: This
152152
requires a
153153
[`ConvexProvider`](https://docs.convex.dev/quickstart/react#:~:text=Connect%20the%20app%20to%20your%20backend)
154154
to be in the component tree.
155155

156156
```tsx
157157
// src/MyComponent.tsx
158-
import { useTipTapSync } from "@convex-dev/prosemirror-sync/tiptap";
158+
import { useTiptapSync } from "@convex-dev/prosemirror-sync/tiptap";
159159
import { EditorContent, EditorProvider } from "@tiptap/react";
160160
import StarterKit from "@tiptap/starter-kit";
161161
import { api } from "../convex/_generated/api";
162162

163163
function MyComponent() {
164-
const sync = useTipTapSync(api.example, "some-id");
164+
const sync = useTiptapSync(api.example, "some-id");
165165
return sync.isLoading ? (
166166
<p>Loading...</p>
167167
) : sync.initialContent !== null ? (
@@ -184,9 +184,28 @@ See a working example in [example.ts](./example/convex/example.ts) and
184184

185185
## Notes
186186

187+
### Configuring the snapshot debounce interval
188+
189+
The snapshot debounce interval is set to one second by default.
190+
You can specify a different interval with the `snapshotDebounceMs` option when
191+
calling `useTiptapSync`.
192+
193+
A snapshot won't be sent until both of these are true:
194+
195+
- The document has been idle for the debounce interval.
196+
- The current user was the last to make a change.
197+
198+
There can be races, but since each client will submit the snapshot for their
199+
own change, they won't conflict with each other and are safe to apply.
200+
187201
### Creating a new document
188202

189-
You can create a new document from the client by calling `sync.create(content)`.
203+
You can create a new document from the client by calling `sync.create(content)`, or on the server by calling `prosemirrorSync.create(ctx, id, content)`.
204+
205+
The content should be a JSON object matching the
206+
[Schema](https://tiptap.dev/docs/editor/core-concepts/schema).
207+
208+
For client-side document creation:
190209

191210
- While it's safest to wait until the server confirms the document doesn't exist
192211
yet (`!sync.isLoading`), you can choose to call it while offline with a newly
@@ -195,7 +214,7 @@ You can create a new document from the client by calling `sync.create(content)`.
195214
initial version and all local changes as steps.
196215
- If multiple clients create the same document, it will fail if they submit
197216
different initial content.
198-
- Note: if you don't open that document (`useTipTapSync`) while online, it won't
217+
- Note: if you don't open that document (`useTiptapSync`) while online, it won't
199218
sync.
200219

201220
<!-- END: Include on https://convex.dev/components -->

example/src/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Typography from "@tiptap/extension-typography";
77
import Underline from "@tiptap/extension-underline";
88
import { api } from "../convex/_generated/api";
99
import { JSONContent } from "@tiptap/core";
10-
import { useTipTapSync } from "@convex-dev/prosemirror-sync/tiptap";
10+
import { useTiptapSync } from "@convex-dev/prosemirror-sync/tiptap";
1111

1212
const extensions = [
1313
StarterKit,
@@ -22,7 +22,7 @@ const extensions = [
2222
const EMPTY_DOC: JSONContent = { type: "doc", content: [] };
2323

2424
function App(props: { id: string }) {
25-
const sync = useTipTapSync(api.example, props.id);
25+
const sync = useTiptapSync(api.example, props.id);
2626
if (!sync.isLoading && sync.initialContent === null) {
2727
sync.create(EMPTY_DOC);
2828
}
@@ -33,7 +33,7 @@ function App(props: { id: string }) {
3333
This demonstrates syncing a ProseMirror document using Convex to provide
3434
real-time collaborative editing.
3535
<br />
36-
It uses TipTap for the in-browser editing and support for inline
36+
It uses Tiptap for the in-browser editing and support for inline
3737
Markdown formatting, similar to Notion.
3838
<br />
3939
Share this URL to edit the same document, or test co-editing by opening
@@ -55,7 +55,7 @@ function App(props: { id: string }) {
5555
</div>
5656
<footer>
5757
<p className="read-the-docs">
58-
Powered by TipTap (ProseMirror) + Convex + Vite + React + TypeScript
58+
Powered by Tiptap (ProseMirror) + Convex + Vite + React + TypeScript
5959
</p>
6060
<a
6161
href="https://github.com/get-convex/prosemirror-sync"

src/tiptap/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type UseSyncOptions = {
2121
snapshotDebounceMs?: number;
2222
};
2323

24-
export function useTipTapSync(
24+
export function useTiptapSync(
2525
syncApi: SyncApi,
2626
id: string,
2727
opts?: UseSyncOptions

0 commit comments

Comments
 (0)