UNPKG

@tiptap/extension-collaboration-cursor

Version:

collaboration cursor extension for tiptap

1 lines 8.54 kB
{"version":3,"file":"index.cjs","sources":["../src/collaboration-cursor.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { DecorationAttrs } from '@tiptap/pm/view'\nimport { defaultSelectionBuilder, yCursorPlugin } from 'y-prosemirror'\n\ntype CollaborationCursorStorage = {\n users: { clientId: number, [key: string]: any }[],\n}\n\nexport interface CollaborationCursorOptions {\n /**\n * The Hocuspocus provider instance. This can also be a TiptapCloudProvider instance.\n * @type {HocuspocusProvider | TiptapCloudProvider}\n * @example new HocuspocusProvider()\n */\n provider: any,\n\n /**\n * The user details object – feel free to add properties to this object as needed\n * @example { name: 'John Doe', color: '#305500' }\n */\n user: Record<string, any>,\n\n /**\n * A function that returns a DOM element for the cursor.\n * @param user The user details object\n * @example\n * render: user => {\n * const cursor = document.createElement('span')\n * cursor.classList.add('collaboration-cursor__caret')\n * cursor.setAttribute('style', `border-color: ${user.color}`)\n *\n * const label = document.createElement('div')\n * label.classList.add('collaboration-cursor__label')\n * label.setAttribute('style', `background-color: ${user.color}`)\n * label.insertBefore(document.createTextNode(user.name), null)\n *\n * cursor.insertBefore(label, null)\n * return cursor\n * }\n */\n render (user: Record<string, any>): HTMLElement,\n\n /**\n * A function that returns a ProseMirror DecorationAttrs object for the selection.\n * @param user The user details object\n * @example\n * selectionRender: user => {\n * return {\n * nodeName: 'span',\n * class: 'collaboration-cursor__selection',\n * style: `background-color: ${user.color}`,\n * 'data-user': user.name,\n * }\n */\n selectionRender (user: Record<string, any>): DecorationAttrs\n\n /**\n * @deprecated The \"onUpdate\" option is deprecated. Please use `editor.storage.collaborationCursor.users` instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor\n */\n onUpdate: (users: { clientId: number, [key: string]: any }[]) => null,\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n collaborationCursor: {\n /**\n * Update details of the current user\n * @example editor.commands.updateUser({ name: 'John Doe', color: '#305500' })\n */\n updateUser: (attributes: Record<string, any>) => ReturnType,\n /**\n * Update details of the current user\n *\n * @deprecated The \"user\" command is deprecated. Please use \"updateUser\" instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor\n */\n user: (attributes: Record<string, any>) => ReturnType,\n }\n }\n}\n\nconst awarenessStatesToArray = (states: Map<number, Record<string, any>>) => {\n return Array.from(states.entries()).map(([key, value]) => {\n return {\n clientId: key,\n ...value.user,\n }\n })\n}\n\nconst defaultOnUpdate = () => null\n\n/**\n * This extension allows you to add collaboration cursors to your editor.\n * @see https://tiptap.dev/api/extensions/collaboration-cursor\n */\nexport const CollaborationCursor = Extension.create<CollaborationCursorOptions, CollaborationCursorStorage>({\n name: 'collaborationCursor',\n\n priority: 999,\n\n addOptions() {\n return {\n provider: null,\n user: {\n name: null,\n color: null,\n },\n render: user => {\n const cursor = document.createElement('span')\n\n cursor.classList.add('collaboration-cursor__caret')\n cursor.setAttribute('style', `border-color: ${user.color}`)\n\n const label = document.createElement('div')\n\n label.classList.add('collaboration-cursor__label')\n label.setAttribute('style', `background-color: ${user.color}`)\n label.insertBefore(document.createTextNode(user.name), null)\n cursor.insertBefore(label, null)\n\n return cursor\n },\n selectionRender: defaultSelectionBuilder,\n onUpdate: defaultOnUpdate,\n }\n },\n\n onCreate() {\n if (this.options.onUpdate !== defaultOnUpdate) {\n console.warn('[tiptap warn]: DEPRECATED: The \"onUpdate\" option is deprecated. Please use `editor.storage.collaborationCursor.users` instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor')\n }\n if (!this.options.provider) {\n throw new Error('The \"provider\" option is required for the CollaborationCursor extension')\n }\n },\n\n addStorage() {\n return {\n users: [],\n }\n },\n\n addCommands() {\n return {\n updateUser: attributes => () => {\n this.options.user = attributes\n\n this.options.provider.awareness.setLocalStateField('user', this.options.user)\n\n return true\n },\n user: attributes => ({ editor }) => {\n console.warn('[tiptap warn]: DEPRECATED: The \"user\" command is deprecated. Please use \"updateUser\" instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor')\n\n return editor.commands.updateUser(attributes)\n },\n }\n },\n\n addProseMirrorPlugins() {\n return [\n yCursorPlugin(\n (() => {\n this.options.provider.awareness.setLocalStateField('user', this.options.user)\n\n this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states)\n\n this.options.provider.awareness.on('update', () => {\n this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states)\n })\n\n return this.options.provider.awareness\n })(),\n // @ts-ignore\n {\n cursorBuilder: this.options.render,\n selectionBuilder: this.options.selectionRender,\n },\n ),\n ]\n },\n})\n"],"names":["Extension","defaultSelectionBuilder","yCursorPlugin"],"mappings":"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"}