mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-12 21:00:02 +08:00
react docs
This commit is contained in:
parent
89bce5e650
commit
4ad21341f2
52
demos/src/Tutorials/1-3-yjs_lexical/Lexical-React/Note.tsx
Normal file
52
demos/src/Tutorials/1-3-yjs_lexical/Lexical-React/Note.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import './styles.css'
|
||||
|
||||
import { TiptapCollabProvider } from '@hocuspocus/provider'
|
||||
import { CollaborationPlugin } from '@lexical/react/LexicalCollaborationPlugin'
|
||||
import { InitialConfigType, LexicalComposer } from '@lexical/react/LexicalComposer'
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
|
||||
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary'
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
|
||||
import React from 'react'
|
||||
import * as Y from 'yjs'
|
||||
|
||||
import { TNote } from './types'
|
||||
|
||||
export default ({ note }: { note: TNote }) => {
|
||||
const initialConfig: InitialConfigType = {
|
||||
onError(error: Error): void {
|
||||
throw error
|
||||
},
|
||||
namespace: 'myeditor',
|
||||
editable: true,
|
||||
}
|
||||
|
||||
return (
|
||||
<LexicalComposer initialConfig={initialConfig}>
|
||||
<RichTextPlugin
|
||||
contentEditable={<ContentEditable/>}
|
||||
placeholder={<p>{note.defaultContent}</p>}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<CollaborationPlugin
|
||||
id={note.id}
|
||||
key={note.id}
|
||||
// @ts-ignore
|
||||
providerFactory={(id, yjsDocMap) => {
|
||||
const doc = new Y.Doc()
|
||||
|
||||
yjsDocMap.set(id, doc)
|
||||
|
||||
const provider = new TiptapCollabProvider({
|
||||
name: note.id, // any identifier - all connections sharing the same identifier will be synced
|
||||
appId: '7j9y6m10', // replace with YOUR_APP_ID
|
||||
token: 'notoken', // replace with your JWT
|
||||
document: doc,
|
||||
})
|
||||
|
||||
return provider
|
||||
}}
|
||||
shouldBootstrap={true}
|
||||
/>
|
||||
</LexicalComposer>
|
||||
)
|
||||
}
|
26
demos/src/Tutorials/1-3-yjs_lexical/Lexical-React/index.tsx
Normal file
26
demos/src/Tutorials/1-3-yjs_lexical/Lexical-React/index.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import './styles.css'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import Note from './Note'
|
||||
import { TNote } from './types'
|
||||
|
||||
const notes: TNote[] = [
|
||||
{
|
||||
id: 'note-1',
|
||||
defaultContent: 'some random note text',
|
||||
},
|
||||
{
|
||||
id: 'note-2',
|
||||
defaultContent: 'some really random note text',
|
||||
},
|
||||
]
|
||||
|
||||
export default () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{notes.map(note => <Note note={note} key={note.id}/>)}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
@ -0,0 +1,4 @@
|
||||
export type TNote = {
|
||||
id: string;
|
||||
defaultContent: string;
|
||||
};
|
@ -23,7 +23,7 @@ export default ({ note }: { note: TNote }) => {
|
||||
return () => {
|
||||
provider.destroy()
|
||||
}
|
||||
}, [])
|
||||
}, [note.id])
|
||||
|
||||
const editor = useEditor({
|
||||
// make sure that you don't use `content` property anymore!
|
||||
|
@ -17,6 +17,11 @@ import { defineConfig } from 'vite'
|
||||
const getPackageDependencies = () => {
|
||||
const paths: Array<{ find: string, replacement: any }> = []
|
||||
|
||||
paths.push({
|
||||
find: 'yjs',
|
||||
replacement: resolve('../node_modules/yjs/src/index.js'),
|
||||
})
|
||||
|
||||
fg.sync('../packages/*', { onlyDirectories: true })
|
||||
.map(name => name.replace('../packages/', ''))
|
||||
.forEach(name => {
|
||||
|
@ -2,12 +2,101 @@
|
||||
tableOfContents: true
|
||||
---
|
||||
|
||||
"Embed real-time collaboration into your app in under one minute, and everything is in sync." ([Live-Demo](/collab))- If that sounds interesting to you, we might have something :)
|
||||
|
||||
# Tiptap Collab
|
||||
|
||||
Tiptap Collab is our hosted solution of Hocuspocus for those who don't want to maintain their own deployment.
|
||||
|
||||
TODO: Maybe remove Cloud from hocuspocus docs, or keep the link but redirect to tiptap.dev/cloud?
|
||||
Tiptap Collab is our hosted solution of Hocuspocus (The plug’n’play collaborative editing backend) making it a blast to add real-time collaboration to any app.
|
||||
|
||||
:::warning Pro Feature
|
||||
To get started, you need a Tiptap Pro account ([sign up / login here](https://tiptap.dev/pro)).
|
||||
:::
|
||||
|
||||
[](https://tiptap.dev/images/docs/server/cloud/dashboard.png)
|
||||
|
||||
Note that you need `@hocuspocus/provider` [~v2.0.0](https://github.com/ueberdosis/hocuspocus/releases/tag/v2.0.0)
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
Tiptap Collab makes your app collaborative by syncing your Y.Doc across users using websockets. If you are already using yjs in your app, getting started is as simple as shown below.
|
||||
|
||||
If you are not, you might want to start in our [Tutorials](/tutorials) section.
|
||||
|
||||
```typescript
|
||||
import { TiptapCollabProvider } from '@hocuspocus/provider'
|
||||
import * as Y from 'yjs'
|
||||
|
||||
const provider = new TiptapCollabProvider({
|
||||
appId: 'your_app_id', // get this at collab.tiptap.dev
|
||||
name: 'your_document_name', // e.g. a uuid uuidv4();
|
||||
token: 'your_JWT', // see "Authentication" below
|
||||
doc: new Y.Doc() // pass your existing doc, or leave this out and use provider.document
|
||||
});
|
||||
|
||||
// That's it! Your Y.Doc will now be synced to any other user currently connected
|
||||
```
|
||||
|
||||
### Upgrade from self-hosted deployments
|
||||
|
||||
If you are upgrading from a self-hosted deployment, on the frontend you just need to replace `HocuspocusProvider` with the new `TiptapCollabProvider`. The API is the same, it's just a wrapper that handles hostnames / auth.
|
||||
|
||||
## Examples
|
||||
|
||||
##### replit / Sandbox: Fully functional prototype
|
||||
|
||||
[](https://tiptap.dev/images/docs/server/cloud/tiptapcollab-demo.png)
|
||||
|
||||
We have created a simple client / server setup using replit, which you can review and fork here:
|
||||
|
||||
[Github](https://github.com/janthurau/TiptapCollab) or [Replit (Live-Demo)](https://replit.com/@ueberdosis/TiptapCollab?v=1)
|
||||
|
||||
The example load multiple documents over the same websocket (multiplexing), and shows how to realize per-document authentication using JWT.
|
||||
|
||||
##### Authentication
|
||||
|
||||
Authentication is done using JWT. You can see your secret in the admin interface and use it to generate tokens for your clients. If you want to generate a JWT and add some attributes for testing, you can use http://jwtbuilder.jamiekurtz.com/ . You can leave all fields default, just replace the "key" with the secret from your settings.
|
||||
|
||||
In Node.js, you can generate a JWT like this:
|
||||
|
||||
```typescript
|
||||
import jsonwebtoken from 'jsonwebtoken'
|
||||
|
||||
const data = {
|
||||
// use this list to limit the number of documents that can be accessed by this client.
|
||||
// empty array means no access at all
|
||||
// not sending this property means access to all documents
|
||||
// we are supporting a wildcard at the end of the string (only there)
|
||||
allowedDocumentNames: ['document-1', 'document-2', 'my-user-uuid/*', 'my-organization-uuid/*']
|
||||
}
|
||||
|
||||
const jwt = jsonwebtoken.sign(data, 'your_secret')
|
||||
// this JWT should be sent in the `token` field of the provider. Never expose 'your_secret' to a frontend!
|
||||
```
|
||||
|
||||
#### Getting the JSON document
|
||||
|
||||
If you want to access the JSON representation (we're currently exporting the `default` fragment of the YDoc), you can add a webhook in the admin interface. We are calling it when storing to our database, so it's debounced by 2 seconds (max 10 seconds).
|
||||
|
||||
All requests contain a header `X-Hocuspocus-Signature-256` which signs the entire message using 'your_secret' (find it in the settings). The payload looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"appName": '', // name of your app
|
||||
"name": '', // name of the document
|
||||
"time": // current time as ISOString (new Date()).toISOString())
|
||||
"tiptapData": {}, // JSON output from Tiptap (see https://tiptap.dev/guide/output#option-1-json): TiptapTransformer.fromYdoc()
|
||||
"ydocState"?: {}, // optionally contains the entire yDoc as base64. Contact us to enable this property!
|
||||
"clientsCount": 100 // number of currently connected clients
|
||||
}
|
||||
```
|
||||
|
||||
### Screenshots
|
||||
|
||||
[](https://tiptap.dev/images/docs/server/cloud/documents.png)
|
||||
|
||||
[](https://tiptap.dev/images/docs/server/cloud/settings.png)
|
||||
|
||||
### Need anything else?
|
||||
|
||||
Contact us on [Discord](https://tiptap.dev/discord) or send an email to [humans@tiptap.dev](mailto:humans@tiptap.dev).
|
||||
|
@ -2,4 +2,4 @@
|
||||
tableOfContents: true
|
||||
---
|
||||
|
||||
# Introduction
|
||||
# Tutorials
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
**Welcome** to the first of a series of tutorials about collaboration in Tiptap (or Lexical, Quill, Slate, and others that have a [Yjs editor binding](https://docs.yjs.dev/ecosystem/editor-bindings)) using Tiptap Collab. This series will start covering the basics, and expand to more specific use cases in the next posts. For today, we’ll start moving from a simple textarea box to a fully collaborative editor instance.
|
||||
|
||||
_For simplicity, I'm always referring to Tiptap from here, but you can switch each code sample to Lexical, Quill or Slate._
|
||||
|
||||
Imagine that you are building a simple sticky note app, where a user can create notes.
|
||||
|
||||
So let's say you have a few textareas. Depending on your framework (Vue, React, ..), the code probably looks similar to this:
|
||||
@ -21,9 +19,6 @@ You begin by importing the necessary Tiptap components and creating a new editor
|
||||
```bash
|
||||
npm install @tiptap/vue-3 @tiptap/pm @tiptap/starter-kit
|
||||
# for React: npm install @tiptap/react @tiptap/pm @tiptap/starter-kit
|
||||
# for Lexical: npm install lexical @lexical/react
|
||||
# for Quill: npm install quill
|
||||
# for Slate: npm install slate slate-react react react-dom
|
||||
```
|
||||
|
||||
<tiptap-demo name="Tutorials/1-2-tiptap"></tiptap-demo>
|
||||
@ -39,9 +34,6 @@ To add the Collaboration extension to your editor instance, you first need to in
|
||||
|
||||
```bash
|
||||
npm install @tiptap/extension-collaboration yjs
|
||||
# for Lexical: npm install yjs
|
||||
# for Quill: npm install y-quill yjs
|
||||
# for Slate: npm install @slate-yjs/react yjs
|
||||
```
|
||||
|
||||
Then, you can import the `Collaboration` extension and add it to your editor extensions:
|
||||
|
Loading…
Reference in New Issue
Block a user