|
1 | 1 | import { AnyExtension, Extension, extensions } from "@tiptap/core";
|
2 |
| -import { Awareness } from "y-protocols/awareness"; |
3 |
| - |
4 |
| -import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js"; |
5 |
| - |
6 |
| -import Collaboration from "@tiptap/extension-collaboration"; |
7 |
| -import CollaborationCursor from "@tiptap/extension-collaboration-cursor"; |
8 | 2 | import { Gapcursor } from "@tiptap/extension-gapcursor";
|
9 | 3 | import { HardBreak } from "@tiptap/extension-hard-break";
|
10 | 4 | import { History } from "@tiptap/extension-history";
|
11 | 5 | import { Link } from "@tiptap/extension-link";
|
12 | 6 | import { Text } from "@tiptap/extension-text";
|
13 | 7 | import { Plugin } from "prosemirror-state";
|
14 | 8 | import * as Y from "yjs";
|
| 9 | + |
| 10 | +import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js"; |
15 | 11 | import { createDropFileExtension } from "../api/clipboard/fromClipboard/fileDropExtension.js";
|
16 | 12 | import { createPasteFromClipboardExtension } from "../api/clipboard/fromClipboard/pasteExtension.js";
|
17 | 13 | import { createCopyToClipboardExtension } from "../api/clipboard/toClipboard/copyExtension.js";
|
@@ -44,6 +40,7 @@ import {
|
44 | 40 | StyleSchema,
|
45 | 41 | StyleSpecs,
|
46 | 42 | } from "../schema/index.js";
|
| 43 | +import { createCollaborationExtensions } from "../extensions/Collaboration/createCollaborationExtensions.js"; |
47 | 44 |
|
48 | 45 | type ExtensionOptions<
|
49 | 46 | BSchema extends BlockSchema,
|
@@ -247,128 +244,7 @@ const getTipTapExtensions = <
|
247 | 244 | ];
|
248 | 245 |
|
249 | 246 | if (opts.collaboration) {
|
250 |
| - tiptapExtensions.push( |
251 |
| - Collaboration.configure({ |
252 |
| - fragment: opts.collaboration.fragment, |
253 |
| - }) |
254 |
| - ); |
255 |
| - |
256 |
| - const awareness = opts.collaboration?.provider.awareness as Awareness; |
257 |
| - |
258 |
| - if (awareness) { |
259 |
| - const cursors = new Map< |
260 |
| - number, |
261 |
| - { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined } |
262 |
| - >(); |
263 |
| - |
264 |
| - if (opts.collaboration.showCursorLabels !== "always") { |
265 |
| - awareness.on( |
266 |
| - "change", |
267 |
| - ({ |
268 |
| - updated, |
269 |
| - }: { |
270 |
| - added: Array<number>; |
271 |
| - updated: Array<number>; |
272 |
| - removed: Array<number>; |
273 |
| - }) => { |
274 |
| - for (const clientID of updated) { |
275 |
| - const cursor = cursors.get(clientID); |
276 |
| - |
277 |
| - if (cursor) { |
278 |
| - cursor.element.setAttribute("data-active", ""); |
279 |
| - |
280 |
| - if (cursor.hideTimeout) { |
281 |
| - clearTimeout(cursor.hideTimeout); |
282 |
| - } |
283 |
| - |
284 |
| - cursors.set(clientID, { |
285 |
| - element: cursor.element, |
286 |
| - hideTimeout: setTimeout(() => { |
287 |
| - cursor.element.removeAttribute("data-active"); |
288 |
| - }, 2000), |
289 |
| - }); |
290 |
| - } |
291 |
| - } |
292 |
| - } |
293 |
| - ); |
294 |
| - } |
295 |
| - |
296 |
| - const createCursor = (clientID: number, name: string, color: string) => { |
297 |
| - const cursorElement = document.createElement("span"); |
298 |
| - |
299 |
| - cursorElement.classList.add("collaboration-cursor__caret"); |
300 |
| - cursorElement.setAttribute("style", `border-color: ${color}`); |
301 |
| - if (opts.collaboration?.showCursorLabels === "always") { |
302 |
| - cursorElement.setAttribute("data-active", ""); |
303 |
| - } |
304 |
| - |
305 |
| - const labelElement = document.createElement("span"); |
306 |
| - |
307 |
| - labelElement.classList.add("collaboration-cursor__label"); |
308 |
| - labelElement.setAttribute("style", `background-color: ${color}`); |
309 |
| - labelElement.insertBefore(document.createTextNode(name), null); |
310 |
| - |
311 |
| - cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space |
312 |
| - cursorElement.insertBefore(labelElement, null); |
313 |
| - cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space |
314 |
| - |
315 |
| - cursors.set(clientID, { |
316 |
| - element: cursorElement, |
317 |
| - hideTimeout: undefined, |
318 |
| - }); |
319 |
| - |
320 |
| - if (opts.collaboration?.showCursorLabels !== "always") { |
321 |
| - cursorElement.addEventListener("mouseenter", () => { |
322 |
| - const cursor = cursors.get(clientID)!; |
323 |
| - cursor.element.setAttribute("data-active", ""); |
324 |
| - |
325 |
| - if (cursor.hideTimeout) { |
326 |
| - clearTimeout(cursor.hideTimeout); |
327 |
| - cursors.set(clientID, { |
328 |
| - element: cursor.element, |
329 |
| - hideTimeout: undefined, |
330 |
| - }); |
331 |
| - } |
332 |
| - }); |
333 |
| - |
334 |
| - cursorElement.addEventListener("mouseleave", () => { |
335 |
| - const cursor = cursors.get(clientID)!; |
336 |
| - |
337 |
| - cursors.set(clientID, { |
338 |
| - element: cursor.element, |
339 |
| - hideTimeout: setTimeout(() => { |
340 |
| - cursor.element.removeAttribute("data-active"); |
341 |
| - }, 2000), |
342 |
| - }); |
343 |
| - }); |
344 |
| - } |
345 |
| - |
346 |
| - return cursors.get(clientID)!; |
347 |
| - }; |
348 |
| - |
349 |
| - const defaultRender = (user: { color: string; name: string }) => { |
350 |
| - const clientState = [...awareness.getStates().entries()].find( |
351 |
| - (state) => state[1].user === user |
352 |
| - ); |
353 |
| - |
354 |
| - if (!clientState) { |
355 |
| - throw new Error("Could not find client state for user"); |
356 |
| - } |
357 |
| - |
358 |
| - const clientID = clientState[0]; |
359 |
| - |
360 |
| - return ( |
361 |
| - cursors.get(clientID) || createCursor(clientID, user.name, user.color) |
362 |
| - ).element; |
363 |
| - }; |
364 |
| - tiptapExtensions.push( |
365 |
| - CollaborationCursor.configure({ |
366 |
| - user: opts.collaboration.user, |
367 |
| - render: opts.collaboration.renderCursor || defaultRender, |
368 |
| - provider: opts.collaboration.provider, |
369 |
| - }) |
370 |
| - ); |
371 |
| - } |
| 247 | + tiptapExtensions.push(...createCollaborationExtensions(opts.collaboration)); |
372 | 248 | } else {
|
373 | 249 | // disable history extension when collaboration is enabled as Yjs takes care of undo / redo
|
374 | 250 | tiptapExtensions.push(History);
|
|
0 commit comments