@liveblocks/react-tiptap 3.19.4-test1 → 3.19.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LiveblocksExtension.cjs +5 -51
- package/dist/LiveblocksExtension.cjs.map +1 -1
- package/dist/LiveblocksExtension.js +5 -51
- package/dist/LiveblocksExtension.js.map +1 -1
- package/dist/ai/AiExtension.cjs +1 -2
- package/dist/ai/AiExtension.cjs.map +1 -1
- package/dist/ai/AiExtension.js +1 -2
- package/dist/ai/AiExtension.js.map +1 -1
- package/dist/comments/CommentsExtension.cjs +1 -7
- package/dist/comments/CommentsExtension.cjs.map +1 -1
- package/dist/comments/CommentsExtension.js +1 -7
- package/dist/comments/CommentsExtension.js.map +1 -1
- package/dist/index.d.cts +0 -5
- package/dist/index.d.ts +0 -5
- package/dist/mentions/MentionExtension.cjs +1 -4
- package/dist/mentions/MentionExtension.cjs.map +1 -1
- package/dist/mentions/MentionExtension.js +1 -4
- package/dist/mentions/MentionExtension.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +6 -6
- package/src/styles/index.css +4 -12
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/collaboration-liveblocks/cursors.cjs +0 -267
- package/dist/collaboration-liveblocks/cursors.cjs.map +0 -1
- package/dist/collaboration-liveblocks/cursors.js +0 -264
- package/dist/collaboration-liveblocks/cursors.js.map +0 -1
- package/dist/collaboration-liveblocks/mapping.cjs +0 -218
- package/dist/collaboration-liveblocks/mapping.cjs.map +0 -1
- package/dist/collaboration-liveblocks/mapping.js +0 -207
- package/dist/collaboration-liveblocks/mapping.js.map +0 -1
- package/dist/collaboration-liveblocks/plugin.cjs +0 -250
- package/dist/collaboration-liveblocks/plugin.cjs.map +0 -1
- package/dist/collaboration-liveblocks/plugin.js +0 -247
- package/dist/collaboration-liveblocks/plugin.js.map +0 -1
- package/dist/collaboration-liveblocks/remote.cjs +0 -196
- package/dist/collaboration-liveblocks/remote.cjs.map +0 -1
- package/dist/collaboration-liveblocks/remote.js +0 -193
- package/dist/collaboration-liveblocks/remote.js.map +0 -1
- package/dist/collaboration-liveblocks/schema.cjs +0 -150
- package/dist/collaboration-liveblocks/schema.cjs.map +0 -1
- package/dist/collaboration-liveblocks/schema.js +0 -135
- package/dist/collaboration-liveblocks/schema.js.map +0 -1
- package/dist/collaboration-liveblocks/steps.cjs +0 -359
- package/dist/collaboration-liveblocks/steps.cjs.map +0 -1
- package/dist/collaboration-liveblocks/steps.js +0 -356
- package/dist/collaboration-liveblocks/steps.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentsExtension.js","sources":["../../src/comments/CommentsExtension.ts"],"sourcesContent":["import { shallow } from \"@liveblocks/core\";\nimport { type Editor, Extension, Mark, mergeAttributes } from \"@tiptap/core\";\nimport type {\n Mark as ProseMirrorMark,\n MarkType,\n Node,\n ResolvedPos,\n} from \"@tiptap/pm/model\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"../collaboration-liveblocks/plugin\";\nimport type { CommentsExtensionStorage, ThreadPluginState } from \"../types\";\nimport {\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n ThreadPluginActions,\n THREADS_ACTIVE_SELECTION_PLUGIN,\n THREADS_PLUGIN_KEY,\n} from \"../types\";\nimport { areSetsEqual } from \"../utils\";\n\ntype ThreadPluginAction = {\n name: ThreadPluginActions;\n data: string[];\n};\n\nexport const FILTERED_THREADS_PLUGIN_KEY = new PluginKey<{\n filteredThreads?: Set<string>;\n}>();\n\nfunction getFilteredThreads(state: EditorState): Set<string> | undefined {\n return FILTERED_THREADS_PLUGIN_KEY.getState(state)?.filteredThreads;\n}\n\nfunction getVisibleThreadIdsFromMarks(\n marks: readonly ProseMirrorMark[],\n markType: MarkType,\n filteredThreads: Set<string> | undefined\n): string[] {\n const ids = new Set<string>();\n for (const mark of marks) {\n if (mark.type !== markType || mark.attrs.orphan) continue;\n const threadId = mark.attrs.threadId as string | undefined;\n if (!threadId) continue;\n if (filteredThreads && !filteredThreads.has(threadId)) continue;\n ids.add(threadId);\n }\n return [...ids];\n}\n\nfunction getVisibleThreadIdsAtPos(\n state: EditorState,\n $pos: ResolvedPos,\n markType: MarkType\n): string[] {\n return getVisibleThreadIdsFromMarks(\n $pos.marks(),\n markType,\n getFilteredThreads(state)\n );\n}\n\nfunction dispatchSetActiveThreadIds(view: EditorView, ids: string[]): void {\n view.dispatch(\n view.state.tr.setMeta(THREADS_PLUGIN_KEY, {\n name: ThreadPluginActions.SET_ACTIVE_THREAD_IDS,\n data: ids,\n } satisfies ThreadPluginAction)\n );\n}\n\nconst Comment = Mark.create({\n name: LIVEBLOCKS_COMMENT_MARK_TYPE,\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n parseHTML: () => {\n return [\n {\n tag: \"span\",\n getAttrs: (node) =>\n node.getAttribute(\"data-lb-thread-id\") !== null && null,\n },\n ];\n },\n addAttributes() {\n // Return an object with attribute configuration\n return {\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-lb-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-lb-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n const filteredThreads = this.editor\n ? FILTERED_THREADS_PLUGIN_KEY.getState(this.editor.state)?.filteredThreads\n : undefined;\n const threadId = (HTMLAttributes as { [\"data-lb-thread-id\"]: string })[\n \"data-lb-thread-id\"\n ];\n if (filteredThreads && !filteredThreads.has(threadId)) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n \"data-hidden\": \"\",\n }),\n ];\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n }),\n ];\n },\n\n /**\n * This plugin tracks the (first) position of each thread mark in the doc and creates a decoration for the selected thread\n */\n addProseMirrorPlugins() {\n const updateState = (\n doc: Node,\n activeThreadIds: string[],\n { scroll }: { scroll: boolean }\n ): ThreadPluginState => {\n const threadPositions = new Map<string, { from: number; to: number }>();\n const decorations: Decoration[] = [];\n const activeSet = new Set(activeThreadIds);\n\n doc.descendants((node, pos) => {\n for (const mark of node.marks) {\n if (mark.type !== this.type) continue;\n\n const threadId = (mark.attrs as { threadId?: string }).threadId;\n if (!threadId) continue;\n\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so we always store the largest \"to\" found.\n // AnchoredThreads component uses \"from\" as the position, so we always store the smallest \"from\" found.\n const current = threadPositions.get(threadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(threadId, {\n from: Math.min(from, current.from),\n to: Math.max(to, current.to),\n });\n\n if (activeSet.has(threadId)) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"lb-root lb-tiptap-thread-mark-selected\",\n })\n );\n }\n }\n });\n\n // Only scroll when the active selection explicitly changes.\n if (scroll && activeThreadIds.length > 0) {\n const [scrollTargetId] = activeThreadIds;\n const element = this.editor.view.dom.querySelector(\n `.lb-tiptap-thread-mark[data-lb-thread-id=\"${scrollTargetId}\"]`\n );\n element?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }\n\n return {\n decorations: DecorationSet.create(doc, decorations),\n activeThreadIds,\n threadPositions,\n };\n };\n\n // Recursively walks a Fragment and removes only this extension's comment mark from every node it finds.\n const stripCommentMarks = (slice: Slice): Slice => {\n const stripFragment = (fragment: Fragment): Fragment => {\n let changed = false;\n const nodes: Node[] = [];\n\n fragment.forEach((node) => {\n // Filter out this extension's comment mark from the node's marks so that it is not copied to the clipboard\n const nextMarks = node.marks.filter(\n (mark) => mark.type !== this.type\n );\n const marksChanged = nextMarks.length !== node.marks.length;\n\n // Recursively strip comment marks from child content (e.g. inline content inside paragraphs, list items)\n const nextContent =\n node.content.childCount > 0\n ? stripFragment(node.content)\n : node.content;\n const contentChanged = nextContent !== node.content;\n\n if (marksChanged || contentChanged) {\n changed = true;\n nodes.push(\n node.isText\n ? node.mark(nextMarks)\n : node.type.create(node.attrs, nextContent, nextMarks)\n );\n } else {\n nodes.push(node);\n }\n });\n\n return changed ? Fragment.fromArray(nodes) : fragment;\n };\n\n const content = stripFragment(slice.content);\n return content === slice.content\n ? slice\n : new Slice(content, slice.openStart, slice.openEnd);\n };\n\n return [\n new Plugin({\n key: new PluginKey(\"lb-comment-clipboard\"),\n props: {\n transformCopied: (slice) => stripCommentMarks(slice),\n transformPasted: (slice) => stripCommentMarks(slice),\n },\n }),\n new Plugin({\n key: THREADS_PLUGIN_KEY,\n state: {\n init(): ThreadPluginState {\n return {\n threadPositions: new Map(),\n activeThreadIds: [],\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(THREADS_PLUGIN_KEY) as\n | ThreadPluginAction\n | undefined;\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n if (!action) {\n return updateState(tr.doc, state.activeThreadIds, {\n scroll: false,\n });\n }\n\n if (action.name === ThreadPluginActions.SET_ACTIVE_THREAD_IDS) {\n const idsChanged = !shallow(action.data, state.activeThreadIds);\n if (!tr.docChanged && !idsChanged) {\n return state;\n }\n return updateState(tr.doc, action.data, { scroll: idsChanged });\n }\n\n return state;\n },\n },\n props: {\n decorations: (state) => {\n return (\n THREADS_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n handleClick: (view, pos, event) => {\n if (event.button !== 0) return;\n\n const $pos = view.state.doc.resolve(pos);\n const ids = getVisibleThreadIdsAtPos(view.state, $pos, this.type);\n dispatchSetActiveThreadIds(view, ids);\n },\n },\n }),\n ];\n },\n});\n\nexport const CommentsExtension = Extension.create<\n { filteredThreads?: Set<string> },\n CommentsExtensionStorage\n>({\n name: \"liveblocksComments\",\n priority: 95,\n addExtensions() {\n return [Comment];\n },\n\n addStorage() {\n return {\n pendingComment: false,\n };\n },\n\n addCommands() {\n return {\n addPendingComment: () => () => {\n if (this.editor.state.selection.empty) {\n return false;\n }\n // Unselect any open threads.\n dispatchSetActiveThreadIds(this.editor.view, []);\n this.storage.pendingComment = true;\n return true;\n },\n closePendingComment: () => () => {\n this.storage.pendingComment = false;\n return true;\n },\n selectThread: (id: string | null) => () => {\n // If the target thread is filtered out, clear the active selection\n // instead of selecting an invisible thread.\n const filtered = getFilteredThreads(this.editor.state);\n const nextIds =\n id === null || (filtered && !filtered.has(id)) ? [] : [id];\n\n dispatchSetActiveThreadIds(this.editor.view, nextIds);\n return true;\n },\n addComment:\n (id: string) =>\n ({ commands }) => {\n if (\n !this.storage.pendingComment ||\n this.editor.state.selection.empty\n ) {\n return false;\n }\n commands.setMark(LIVEBLOCKS_COMMENT_MARK_TYPE, { threadId: id });\n this.storage.pendingComment = false;\n return true;\n },\n };\n },\n onSelectionUpdate(\n this: { storage: CommentsExtensionStorage; editor: Editor },\n { transaction }: { transaction: Transaction }\n ) {\n const yjsMeta: unknown = transaction.getMeta(ySyncPluginKey);\n const liveblocksMeta: unknown = transaction.getMeta(\n LIVEBLOCKS_COLLABORATION_PLUGIN_KEY\n );\n const isRemoteCollaborationUpdate = yjsMeta || liveblocksMeta;\n\n // Close any pending composer when the user moves the selection locally\n // (but ignore remote collaboration-driven selection changes).\n if (this.storage.pendingComment && !isRemoteCollaborationUpdate) {\n this.storage.pendingComment = false;\n }\n\n if (this.storage.pendingComment) return;\n\n const { state } = this.editor;\n const markType = state.schema.marks[LIVEBLOCKS_COMMENT_MARK_TYPE];\n if (!markType) return;\n\n const ids = getVisibleThreadIdsAtPos(\n state,\n state.selection.$from,\n markType\n );\n const current = THREADS_PLUGIN_KEY.getState(state)?.activeThreadIds ?? [];\n if (shallow(ids, current)) return;\n\n dispatchSetActiveThreadIds(this.editor.view, ids);\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: THREADS_ACTIVE_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n if (!this.storage.pendingComment) {\n return DecorationSet.create(doc, []);\n }\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n new Plugin({\n key: FILTERED_THREADS_PLUGIN_KEY,\n state: {\n init: () => ({\n filteredThreads: this.options.filteredThreads,\n }),\n apply(tr, value) {\n const meta = tr.getMeta(FILTERED_THREADS_PLUGIN_KEY) as\n | { filteredThreads?: Set<string> }\n | undefined;\n if (meta?.filteredThreads) {\n return { filteredThreads: meta.filteredThreads };\n }\n return value;\n },\n },\n view: (view) => {\n const syncDom = () => {\n const filteredThreads = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n\n // Toggle attribute for all comment-mark spans\n const els = view.dom.querySelectorAll<HTMLElement>(\n \"span.lb-tiptap-thread-mark[data-lb-thread-id]\"\n );\n els.forEach((el) => {\n const id = el.getAttribute(\"data-lb-thread-id\");\n if (!id) return;\n if (!filteredThreads || filteredThreads.has(id)) {\n el.removeAttribute(\"data-hidden\");\n } else {\n el.setAttribute(\"data-hidden\", \"\");\n }\n });\n };\n\n queueMicrotask(syncDom);\n\n return {\n update: (view, prevState) => {\n const curr = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n const prev =\n FILTERED_THREADS_PLUGIN_KEY.getState(\n prevState\n )?.filteredThreads;\n\n if (\n !areSetsEqual(prev, curr) ||\n view.state.doc !== prevState.doc\n ) {\n syncDom();\n\n const active =\n THREADS_PLUGIN_KEY.getState(view.state)?.activeThreadIds ??\n [];\n\n if (active.length && curr) {\n const next = active.filter((id) => curr.has(id));\n if (next.length !== active.length) {\n dispatchSetActiveThreadIds(view, next);\n }\n }\n }\n },\n };\n },\n }),\n ];\n },\n});\n"],"names":["view"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentsExtension.js","sources":["../../src/comments/CommentsExtension.ts"],"sourcesContent":["import { shallow } from \"@liveblocks/core\";\nimport { type Editor, Extension, Mark, mergeAttributes } from \"@tiptap/core\";\nimport type {\n Mark as ProseMirrorMark,\n MarkType,\n Node,\n ResolvedPos,\n} from \"@tiptap/pm/model\";\nimport { Fragment, Slice } from \"@tiptap/pm/model\";\nimport type { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport type { CommentsExtensionStorage, ThreadPluginState } from \"../types\";\nimport {\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n ThreadPluginActions,\n THREADS_ACTIVE_SELECTION_PLUGIN,\n THREADS_PLUGIN_KEY,\n} from \"../types\";\nimport { areSetsEqual } from \"../utils\";\n\ntype ThreadPluginAction = {\n name: ThreadPluginActions;\n data: string[];\n};\n\nexport const FILTERED_THREADS_PLUGIN_KEY = new PluginKey<{\n filteredThreads?: Set<string>;\n}>();\n\nfunction getFilteredThreads(state: EditorState): Set<string> | undefined {\n return FILTERED_THREADS_PLUGIN_KEY.getState(state)?.filteredThreads;\n}\n\nfunction getVisibleThreadIdsFromMarks(\n marks: readonly ProseMirrorMark[],\n markType: MarkType,\n filteredThreads: Set<string> | undefined\n): string[] {\n const ids = new Set<string>();\n for (const mark of marks) {\n if (mark.type !== markType || mark.attrs.orphan) continue;\n const threadId = mark.attrs.threadId as string | undefined;\n if (!threadId) continue;\n if (filteredThreads && !filteredThreads.has(threadId)) continue;\n ids.add(threadId);\n }\n return [...ids];\n}\n\nfunction getVisibleThreadIdsAtPos(\n state: EditorState,\n $pos: ResolvedPos,\n markType: MarkType\n): string[] {\n return getVisibleThreadIdsFromMarks(\n $pos.marks(),\n markType,\n getFilteredThreads(state)\n );\n}\n\nfunction dispatchSetActiveThreadIds(view: EditorView, ids: string[]): void {\n view.dispatch(\n view.state.tr.setMeta(THREADS_PLUGIN_KEY, {\n name: ThreadPluginActions.SET_ACTIVE_THREAD_IDS,\n data: ids,\n } satisfies ThreadPluginAction)\n );\n}\n\nconst Comment = Mark.create({\n name: LIVEBLOCKS_COMMENT_MARK_TYPE,\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n parseHTML: () => {\n return [\n {\n tag: \"span\",\n getAttrs: (node) =>\n node.getAttribute(\"data-lb-thread-id\") !== null && null,\n },\n ];\n },\n addAttributes() {\n // Return an object with attribute configuration\n return {\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-lb-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-lb-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n const filteredThreads = this.editor\n ? FILTERED_THREADS_PLUGIN_KEY.getState(this.editor.state)?.filteredThreads\n : undefined;\n const threadId = (HTMLAttributes as { [\"data-lb-thread-id\"]: string })[\n \"data-lb-thread-id\"\n ];\n if (filteredThreads && !filteredThreads.has(threadId)) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n \"data-hidden\": \"\",\n }),\n ];\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"lb-root lb-tiptap-thread-mark\",\n }),\n ];\n },\n\n /**\n * This plugin tracks the (first) position of each thread mark in the doc and creates a decoration for the selected thread\n */\n addProseMirrorPlugins() {\n const updateState = (\n doc: Node,\n activeThreadIds: string[],\n { scroll }: { scroll: boolean }\n ): ThreadPluginState => {\n const threadPositions = new Map<string, { from: number; to: number }>();\n const decorations: Decoration[] = [];\n const activeSet = new Set(activeThreadIds);\n\n doc.descendants((node, pos) => {\n for (const mark of node.marks) {\n if (mark.type !== this.type) continue;\n\n const threadId = (mark.attrs as { threadId?: string }).threadId;\n if (!threadId) continue;\n\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so we always store the largest \"to\" found.\n // AnchoredThreads component uses \"from\" as the position, so we always store the smallest \"from\" found.\n const current = threadPositions.get(threadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(threadId, {\n from: Math.min(from, current.from),\n to: Math.max(to, current.to),\n });\n\n if (activeSet.has(threadId)) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"lb-root lb-tiptap-thread-mark-selected\",\n })\n );\n }\n }\n });\n\n // Only scroll when the active selection explicitly changes.\n if (scroll && activeThreadIds.length > 0) {\n const [scrollTargetId] = activeThreadIds;\n const element = this.editor.view.dom.querySelector(\n `.lb-tiptap-thread-mark[data-lb-thread-id=\"${scrollTargetId}\"]`\n );\n element?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }\n\n return {\n decorations: DecorationSet.create(doc, decorations),\n activeThreadIds,\n threadPositions,\n };\n };\n\n // Recursively walks a Fragment and removes only this extension's comment mark from every node it finds.\n const stripCommentMarks = (slice: Slice): Slice => {\n const stripFragment = (fragment: Fragment): Fragment => {\n let changed = false;\n const nodes: Node[] = [];\n\n fragment.forEach((node) => {\n // Filter out this extension's comment mark from the node's marks so that it is not copied to the clipboard\n const nextMarks = node.marks.filter(\n (mark) => mark.type !== this.type\n );\n const marksChanged = nextMarks.length !== node.marks.length;\n\n // Recursively strip comment marks from child content (e.g. inline content inside paragraphs, list items)\n const nextContent =\n node.content.childCount > 0\n ? stripFragment(node.content)\n : node.content;\n const contentChanged = nextContent !== node.content;\n\n if (marksChanged || contentChanged) {\n changed = true;\n nodes.push(\n node.isText\n ? node.mark(nextMarks)\n : node.type.create(node.attrs, nextContent, nextMarks)\n );\n } else {\n nodes.push(node);\n }\n });\n\n return changed ? Fragment.fromArray(nodes) : fragment;\n };\n\n const content = stripFragment(slice.content);\n return content === slice.content\n ? slice\n : new Slice(content, slice.openStart, slice.openEnd);\n };\n\n return [\n new Plugin({\n key: new PluginKey(\"lb-comment-clipboard\"),\n props: {\n transformCopied: (slice) => stripCommentMarks(slice),\n transformPasted: (slice) => stripCommentMarks(slice),\n },\n }),\n new Plugin({\n key: THREADS_PLUGIN_KEY,\n state: {\n init(): ThreadPluginState {\n return {\n threadPositions: new Map(),\n activeThreadIds: [],\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(THREADS_PLUGIN_KEY) as\n | ThreadPluginAction\n | undefined;\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n if (!action) {\n return updateState(tr.doc, state.activeThreadIds, {\n scroll: false,\n });\n }\n\n if (action.name === ThreadPluginActions.SET_ACTIVE_THREAD_IDS) {\n const idsChanged = !shallow(action.data, state.activeThreadIds);\n if (!tr.docChanged && !idsChanged) {\n return state;\n }\n return updateState(tr.doc, action.data, { scroll: idsChanged });\n }\n\n return state;\n },\n },\n props: {\n decorations: (state) => {\n return (\n THREADS_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n handleClick: (view, pos, event) => {\n if (event.button !== 0) return;\n\n const $pos = view.state.doc.resolve(pos);\n const ids = getVisibleThreadIdsAtPos(view.state, $pos, this.type);\n dispatchSetActiveThreadIds(view, ids);\n },\n },\n }),\n ];\n },\n});\n\nexport const CommentsExtension = Extension.create<\n { filteredThreads?: Set<string> },\n CommentsExtensionStorage\n>({\n name: \"liveblocksComments\",\n priority: 95,\n addExtensions() {\n return [Comment];\n },\n\n addStorage() {\n return {\n pendingComment: false,\n };\n },\n\n addCommands() {\n return {\n addPendingComment: () => () => {\n if (this.editor.state.selection.empty) {\n return false;\n }\n // Unselect any open threads.\n dispatchSetActiveThreadIds(this.editor.view, []);\n this.storage.pendingComment = true;\n return true;\n },\n closePendingComment: () => () => {\n this.storage.pendingComment = false;\n return true;\n },\n selectThread: (id: string | null) => () => {\n // If the target thread is filtered out, clear the active selection\n // instead of selecting an invisible thread.\n const filtered = getFilteredThreads(this.editor.state);\n const nextIds =\n id === null || (filtered && !filtered.has(id)) ? [] : [id];\n\n dispatchSetActiveThreadIds(this.editor.view, nextIds);\n return true;\n },\n addComment:\n (id: string) =>\n ({ commands }) => {\n if (\n !this.storage.pendingComment ||\n this.editor.state.selection.empty\n ) {\n return false;\n }\n commands.setMark(LIVEBLOCKS_COMMENT_MARK_TYPE, { threadId: id });\n this.storage.pendingComment = false;\n return true;\n },\n };\n },\n onSelectionUpdate(\n this: { storage: CommentsExtensionStorage; editor: Editor },\n { transaction }: { transaction: Transaction }\n ) {\n // Close any pending composer when the user moves the selection locally\n // (but ignore remote Yjs-driven selection changes).\n if (this.storage.pendingComment && !transaction.getMeta(ySyncPluginKey)) {\n this.storage.pendingComment = false;\n }\n\n if (this.storage.pendingComment) return;\n\n const { state } = this.editor;\n const markType = state.schema.marks[LIVEBLOCKS_COMMENT_MARK_TYPE];\n if (!markType) return;\n\n const ids = getVisibleThreadIdsAtPos(\n state,\n state.selection.$from,\n markType\n );\n const current = THREADS_PLUGIN_KEY.getState(state)?.activeThreadIds ?? [];\n if (shallow(ids, current)) return;\n\n dispatchSetActiveThreadIds(this.editor.view, ids);\n },\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: THREADS_ACTIVE_SELECTION_PLUGIN,\n props: {\n decorations: ({ doc, selection }) => {\n if (!this.storage.pendingComment) {\n return DecorationSet.create(doc, []);\n }\n const { from, to } = selection;\n const decorations: Decoration[] = [\n Decoration.inline(from, to, {\n class: \"lb-root lb-selection lb-tiptap-active-selection\",\n }),\n ];\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n new Plugin({\n key: FILTERED_THREADS_PLUGIN_KEY,\n state: {\n init: () => ({\n filteredThreads: this.options.filteredThreads,\n }),\n apply(tr, value) {\n const meta = tr.getMeta(FILTERED_THREADS_PLUGIN_KEY) as\n | { filteredThreads?: Set<string> }\n | undefined;\n if (meta?.filteredThreads) {\n return { filteredThreads: meta.filteredThreads };\n }\n return value;\n },\n },\n view: (view) => {\n const syncDom = () => {\n const filteredThreads = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n\n // Toggle attribute for all comment-mark spans\n const els = view.dom.querySelectorAll<HTMLElement>(\n \"span.lb-tiptap-thread-mark[data-lb-thread-id]\"\n );\n els.forEach((el) => {\n const id = el.getAttribute(\"data-lb-thread-id\");\n if (!id) return;\n if (!filteredThreads || filteredThreads.has(id)) {\n el.removeAttribute(\"data-hidden\");\n } else {\n el.setAttribute(\"data-hidden\", \"\");\n }\n });\n };\n\n queueMicrotask(syncDom);\n\n return {\n update: (view, prevState) => {\n const curr = FILTERED_THREADS_PLUGIN_KEY.getState(\n view.state\n )?.filteredThreads;\n const prev =\n FILTERED_THREADS_PLUGIN_KEY.getState(\n prevState\n )?.filteredThreads;\n\n if (\n !areSetsEqual(prev, curr) ||\n view.state.doc !== prevState.doc\n ) {\n syncDom();\n\n const active =\n THREADS_PLUGIN_KEY.getState(view.state)?.activeThreadIds ??\n [];\n\n if (active.length && curr) {\n const next = active.filter((id) => curr.has(id));\n if (next.length !== active.length) {\n dispatchSetActiveThreadIds(view, next);\n }\n }\n }\n },\n };\n },\n }),\n ];\n },\n});\n"],"names":["view"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -48,7 +48,6 @@ interface AiConfiguration {
|
|
|
48
48
|
resolveContextualPrompt?: (args: ResolveContextualPromptArgs) => Promise<ContextualPromptResponse>;
|
|
49
49
|
}
|
|
50
50
|
type LiveblocksExtensionOptions = {
|
|
51
|
-
collaborationMode?: "yjs" | "liveblocks";
|
|
52
51
|
field?: string;
|
|
53
52
|
comments?: boolean;
|
|
54
53
|
mentions?: boolean;
|
|
@@ -59,14 +58,10 @@ type LiveblocksExtensionOptions = {
|
|
|
59
58
|
enablePermanentUserData?: boolean;
|
|
60
59
|
};
|
|
61
60
|
type LiveblocksExtensionStorage = {
|
|
62
|
-
mode: "yjs";
|
|
63
61
|
unsubs: (() => void)[];
|
|
64
62
|
doc: Doc;
|
|
65
63
|
provider: LiveblocksYjsProvider;
|
|
66
64
|
permanentUserData?: PermanentUserData;
|
|
67
|
-
} | {
|
|
68
|
-
mode: "liveblocks";
|
|
69
|
-
unsubs: (() => void)[];
|
|
70
65
|
};
|
|
71
66
|
type CommentsExtensionStorage = {
|
|
72
67
|
pendingComment: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,6 @@ interface AiConfiguration {
|
|
|
48
48
|
resolveContextualPrompt?: (args: ResolveContextualPromptArgs) => Promise<ContextualPromptResponse>;
|
|
49
49
|
}
|
|
50
50
|
type LiveblocksExtensionOptions = {
|
|
51
|
-
collaborationMode?: "yjs" | "liveblocks";
|
|
52
51
|
field?: string;
|
|
53
52
|
comments?: boolean;
|
|
54
53
|
mentions?: boolean;
|
|
@@ -59,14 +58,10 @@ type LiveblocksExtensionOptions = {
|
|
|
59
58
|
enablePermanentUserData?: boolean;
|
|
60
59
|
};
|
|
61
60
|
type LiveblocksExtensionStorage = {
|
|
62
|
-
mode: "yjs";
|
|
63
61
|
unsubs: (() => void)[];
|
|
64
62
|
doc: Doc;
|
|
65
63
|
provider: LiveblocksYjsProvider;
|
|
66
64
|
permanentUserData?: PermanentUserData;
|
|
67
|
-
} | {
|
|
68
|
-
mode: "liveblocks";
|
|
69
|
-
unsubs: (() => void)[];
|
|
70
65
|
};
|
|
71
66
|
type CommentsExtensionStorage = {
|
|
72
67
|
pendingComment: boolean;
|
|
@@ -7,7 +7,6 @@ var state = require('@tiptap/pm/state');
|
|
|
7
7
|
var react = require('@tiptap/react');
|
|
8
8
|
var Suggestion = require('@tiptap/suggestion');
|
|
9
9
|
var yProsemirror = require('y-prosemirror');
|
|
10
|
-
var plugin = require('../collaboration-liveblocks/plugin.cjs');
|
|
11
10
|
var types = require('../types.cjs');
|
|
12
11
|
var utils = require('../utils.cjs');
|
|
13
12
|
var GroupMentionNode = require('./GroupMentionNode.cjs');
|
|
@@ -45,9 +44,7 @@ const notifier = ({
|
|
|
45
44
|
if (!docChanges) {
|
|
46
45
|
return;
|
|
47
46
|
}
|
|
48
|
-
if (transactions.some(
|
|
49
|
-
(transaction) => transaction.getMeta(yProsemirror.ySyncPluginKey) || transaction.getMeta(plugin.LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)
|
|
50
|
-
)) {
|
|
47
|
+
if (transactions.some((transaction) => transaction.getMeta(yProsemirror.ySyncPluginKey))) {
|
|
51
48
|
return;
|
|
52
49
|
}
|
|
53
50
|
const transform = core$1.combineTransactionSteps(oldState.doc, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionExtension.cjs","sources":["../../src/mentions/MentionExtension.ts"],"sourcesContent":["import {\n assertNever,\n createInboxNotificationId,\n MENTION_CHARACTER,\n} from \"@liveblocks/core\";\nimport {\n combineTransactionSteps,\n type Content,\n Extension,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"../collaboration-liveblocks/plugin\";\nimport {\n LIVEBLOCKS_GROUP_MENTION_TYPE,\n LIVEBLOCKS_MENTION_EXTENSION,\n LIVEBLOCKS_MENTION_KEY,\n LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n LIVEBLOCKS_MENTION_PASTE_KEY,\n LIVEBLOCKS_MENTION_TYPE,\n type TiptapMentionData,\n} from \"../types\";\nimport { getMentionsFromNode, mapFragment } from \"../utils\";\nimport { GroupMentionNode } from \"./GroupMentionNode\";\nimport { MentionNode } from \"./MentionNode\";\nimport type { MentionsListHandle, MentionsListProps } from \"./MentionsList\";\nimport { MentionsList } from \"./MentionsList\";\n\n/**\n *\n * Handles creating new notificationIds when notifications are pasted\n *\n * @returns Plugin\n */\nconst mentionPasteHandler = (): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_PASTE_KEY,\n props: {\n transformPasted: (slice) => {\n const getNewNotificationIds = (node: ProseMirrorNode) => {\n // If this is a mention node, we need to get a new notification id\n if (\n node.type.name === LIVEBLOCKS_MENTION_TYPE ||\n node.type.name === LIVEBLOCKS_GROUP_MENTION_TYPE\n ) {\n return node.type.create(\n { ...node.attrs, notificationId: createInboxNotificationId() },\n node.content\n );\n }\n return node.copy(node.content);\n };\n const fragment = mapFragment(slice.content, getNewNotificationIds);\n return new Slice(fragment, slice.openStart, slice.openEnd);\n },\n },\n });\n};\n\nexport type MentionExtensionOptions = {\n onCreateMention: (mention: TiptapMentionData) => void;\n onDeleteMention: (notificationId: string) => void;\n};\n/**\n *\n * The purpose of this plugin is to create inbox notifications when a mention is\n *\n * @returns Plugin (from @tiptap/core)\n */\nconst notifier = ({\n onCreateMention,\n onDeleteMention,\n}: MentionExtensionOptions): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n // don't run if there was no change\n if (!docChanges) {\n return;\n }\n // don't run if from collab\n if (\n transactions.some(\n (transaction) =>\n transaction.getMeta(ySyncPluginKey) ||\n transaction.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)\n )\n ) {\n return;\n }\n const transform = combineTransactionSteps(oldState.doc, [\n ...transactions,\n ]);\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange, oldRange }) => {\n const newMentions = getMentionsFromNode(newState.doc, newRange);\n const oldMentions = getMentionsFromNode(oldState.doc, oldRange);\n\n if (oldMentions.size || newMentions.size) {\n // create new mentions\n newMentions.forEach((mention) => {\n if (!oldMentions.has(mention.notificationId)) {\n onCreateMention(mention);\n }\n });\n // delete old mentions\n oldMentions.forEach((mention) => {\n if (!newMentions.has(mention.notificationId)) {\n onDeleteMention(mention.notificationId);\n }\n });\n }\n });\n\n return undefined;\n },\n });\n};\n\nexport const MentionExtension = Extension.create<MentionExtensionOptions>({\n name: LIVEBLOCKS_MENTION_EXTENSION,\n\n priority: 101,\n addOptions() {\n return {\n onCreateMention: () => {},\n onDeleteMention: () => {},\n };\n },\n\n addExtensions() {\n return [MentionNode, GroupMentionNode];\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: MENTION_CHARACTER,\n pluginKey: LIVEBLOCKS_MENTION_KEY,\n command: ({ editor, range, props }) => {\n // increase range.to by one when the next node is of type \"text\"\n // and starts with a space character\n const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n const overrideSpace = nodeAfter?.text?.startsWith(\" \");\n\n if (overrideSpace) {\n range.to += 1;\n }\n\n const mention = props as TiptapMentionData;\n\n let mentionNode: Content;\n\n if (mention.kind === \"user\") {\n mentionNode = {\n type: LIVEBLOCKS_MENTION_TYPE,\n attrs: {\n id: mention.id,\n notificationId: mention.notificationId,\n },\n };\n } else if (mention.kind === \"group\") {\n mentionNode = {\n type: LIVEBLOCKS_GROUP_MENTION_TYPE,\n attrs: {\n id: mention.id,\n userIds: mention.userIds\n ? JSON.stringify(mention.userIds)\n : undefined,\n notificationId: mention.notificationId,\n },\n };\n } else {\n assertNever(mention, \"Unhandled mention kind\");\n }\n\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n mentionNode,\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run();\n\n // get reference to `window` object from editor element, to support cross-frame JS usage\n editor.view.dom.ownerDocument.defaultView\n ?.getSelection()\n ?.collapseToEnd();\n },\n allow: ({ state, range }) => {\n const $fromParentType = state.doc.resolve(range.from).parent.type;\n\n return Boolean(\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_MENTION_TYPE]\n ) ||\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_GROUP_MENTION_TYPE]\n )\n );\n },\n allowSpaces: true,\n items: () => [], // we'll let the mentions list component do this\n render: () => {\n let component: ReactRenderer<MentionsListHandle, MentionsListProps>;\n return {\n onStart: (props) => {\n component = new ReactRenderer<\n MentionsListHandle,\n MentionsListProps\n >(MentionsList, {\n props,\n editor: props.editor,\n });\n\n if (!props.clientRect) {\n return;\n }\n\n document.body.appendChild(component.element);\n },\n\n onUpdate(props) {\n component.updateProps(props);\n },\n\n onKeyDown(props) {\n if (props.event.key === \"Escape\") {\n component.updateProps({\n ...props,\n hide: true,\n });\n return true;\n }\n return component.ref?.onKeyDown(props) ?? false;\n },\n\n onExit() {\n if (document.body.contains(component.element)) {\n document.body.removeChild(component.element);\n }\n component.destroy();\n },\n };\n },\n }),\n notifier(this.options),\n mentionPasteHandler(),\n ];\n },\n});\n"],"names":["Plugin","LIVEBLOCKS_MENTION_PASTE_KEY","LIVEBLOCKS_MENTION_TYPE","LIVEBLOCKS_GROUP_MENTION_TYPE","createInboxNotificationId","mapFragment","Slice","LIVEBLOCKS_MENTION_NOTIFIER_KEY","ySyncPluginKey","LIVEBLOCKS_COLLABORATION_PLUGIN_KEY","combineTransactionSteps","getChangedRanges","getMentionsFromNode","Extension","LIVEBLOCKS_MENTION_EXTENSION","MentionNode","GroupMentionNode","MENTION_CHARACTER","LIVEBLOCKS_MENTION_KEY","assertNever","ReactRenderer","MentionsList"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MentionExtension.cjs","sources":["../../src/mentions/MentionExtension.ts"],"sourcesContent":["import {\n assertNever,\n createInboxNotificationId,\n MENTION_CHARACTER,\n} from \"@liveblocks/core\";\nimport {\n combineTransactionSteps,\n type Content,\n Extension,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport {\n LIVEBLOCKS_GROUP_MENTION_TYPE,\n LIVEBLOCKS_MENTION_EXTENSION,\n LIVEBLOCKS_MENTION_KEY,\n LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n LIVEBLOCKS_MENTION_PASTE_KEY,\n LIVEBLOCKS_MENTION_TYPE,\n type TiptapMentionData,\n} from \"../types\";\nimport { getMentionsFromNode, mapFragment } from \"../utils\";\nimport { GroupMentionNode } from \"./GroupMentionNode\";\nimport { MentionNode } from \"./MentionNode\";\nimport type { MentionsListHandle, MentionsListProps } from \"./MentionsList\";\nimport { MentionsList } from \"./MentionsList\";\n\n/**\n *\n * Handles creating new notificationIds when notifications are pasted\n *\n * @returns Plugin\n */\nconst mentionPasteHandler = (): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_PASTE_KEY,\n props: {\n transformPasted: (slice) => {\n const getNewNotificationIds = (node: ProseMirrorNode) => {\n // If this is a mention node, we need to get a new notification id\n if (\n node.type.name === LIVEBLOCKS_MENTION_TYPE ||\n node.type.name === LIVEBLOCKS_GROUP_MENTION_TYPE\n ) {\n return node.type.create(\n { ...node.attrs, notificationId: createInboxNotificationId() },\n node.content\n );\n }\n return node.copy(node.content);\n };\n const fragment = mapFragment(slice.content, getNewNotificationIds);\n return new Slice(fragment, slice.openStart, slice.openEnd);\n },\n },\n });\n};\n\nexport type MentionExtensionOptions = {\n onCreateMention: (mention: TiptapMentionData) => void;\n onDeleteMention: (notificationId: string) => void;\n};\n/**\n *\n * The purpose of this plugin is to create inbox notifications when a mention is\n *\n * @returns Plugin (from @tiptap/core)\n */\nconst notifier = ({\n onCreateMention,\n onDeleteMention,\n}: MentionExtensionOptions): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n // don't run if there was no change\n if (!docChanges) {\n return;\n }\n // don't run if from collab\n if (\n transactions.some((transaction) => transaction.getMeta(ySyncPluginKey))\n ) {\n return;\n }\n const transform = combineTransactionSteps(oldState.doc, [\n ...transactions,\n ]);\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange, oldRange }) => {\n const newMentions = getMentionsFromNode(newState.doc, newRange);\n const oldMentions = getMentionsFromNode(oldState.doc, oldRange);\n\n if (oldMentions.size || newMentions.size) {\n // create new mentions\n newMentions.forEach((mention) => {\n if (!oldMentions.has(mention.notificationId)) {\n onCreateMention(mention);\n }\n });\n // delete old mentions\n oldMentions.forEach((mention) => {\n if (!newMentions.has(mention.notificationId)) {\n onDeleteMention(mention.notificationId);\n }\n });\n }\n });\n\n return undefined;\n },\n });\n};\n\nexport const MentionExtension = Extension.create<MentionExtensionOptions>({\n name: LIVEBLOCKS_MENTION_EXTENSION,\n\n priority: 101,\n addOptions() {\n return {\n onCreateMention: () => {},\n onDeleteMention: () => {},\n };\n },\n\n addExtensions() {\n return [MentionNode, GroupMentionNode];\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: MENTION_CHARACTER,\n pluginKey: LIVEBLOCKS_MENTION_KEY,\n command: ({ editor, range, props }) => {\n // increase range.to by one when the next node is of type \"text\"\n // and starts with a space character\n const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n const overrideSpace = nodeAfter?.text?.startsWith(\" \");\n\n if (overrideSpace) {\n range.to += 1;\n }\n\n const mention = props as TiptapMentionData;\n\n let mentionNode: Content;\n\n if (mention.kind === \"user\") {\n mentionNode = {\n type: LIVEBLOCKS_MENTION_TYPE,\n attrs: {\n id: mention.id,\n notificationId: mention.notificationId,\n },\n };\n } else if (mention.kind === \"group\") {\n mentionNode = {\n type: LIVEBLOCKS_GROUP_MENTION_TYPE,\n attrs: {\n id: mention.id,\n userIds: mention.userIds\n ? JSON.stringify(mention.userIds)\n : undefined,\n notificationId: mention.notificationId,\n },\n };\n } else {\n assertNever(mention, \"Unhandled mention kind\");\n }\n\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n mentionNode,\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run();\n\n // get reference to `window` object from editor element, to support cross-frame JS usage\n editor.view.dom.ownerDocument.defaultView\n ?.getSelection()\n ?.collapseToEnd();\n },\n allow: ({ state, range }) => {\n const $fromParentType = state.doc.resolve(range.from).parent.type;\n\n return Boolean(\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_MENTION_TYPE]\n ) ||\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_GROUP_MENTION_TYPE]\n )\n );\n },\n allowSpaces: true,\n items: () => [], // we'll let the mentions list component do this\n render: () => {\n let component: ReactRenderer<MentionsListHandle, MentionsListProps>;\n return {\n onStart: (props) => {\n component = new ReactRenderer<\n MentionsListHandle,\n MentionsListProps\n >(MentionsList, {\n props,\n editor: props.editor,\n });\n\n if (!props.clientRect) {\n return;\n }\n\n document.body.appendChild(component.element);\n },\n\n onUpdate(props) {\n component.updateProps(props);\n },\n\n onKeyDown(props) {\n if (props.event.key === \"Escape\") {\n component.updateProps({\n ...props,\n hide: true,\n });\n return true;\n }\n return component.ref?.onKeyDown(props) ?? false;\n },\n\n onExit() {\n if (document.body.contains(component.element)) {\n document.body.removeChild(component.element);\n }\n component.destroy();\n },\n };\n },\n }),\n notifier(this.options),\n mentionPasteHandler(),\n ];\n },\n});\n"],"names":["Plugin","LIVEBLOCKS_MENTION_PASTE_KEY","LIVEBLOCKS_MENTION_TYPE","LIVEBLOCKS_GROUP_MENTION_TYPE","createInboxNotificationId","mapFragment","Slice","LIVEBLOCKS_MENTION_NOTIFIER_KEY","ySyncPluginKey","combineTransactionSteps","getChangedRanges","getMentionsFromNode","Extension","LIVEBLOCKS_MENTION_EXTENSION","MentionNode","GroupMentionNode","MENTION_CHARACTER","LIVEBLOCKS_MENTION_KEY","assertNever","ReactRenderer","MentionsList"],"mappings":"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"}
|
|
@@ -5,7 +5,6 @@ import { Plugin } from '@tiptap/pm/state';
|
|
|
5
5
|
import { ReactRenderer } from '@tiptap/react';
|
|
6
6
|
import Suggestion from '@tiptap/suggestion';
|
|
7
7
|
import { ySyncPluginKey } from 'y-prosemirror';
|
|
8
|
-
import { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from '../collaboration-liveblocks/plugin.js';
|
|
9
8
|
import { LIVEBLOCKS_MENTION_PASTE_KEY, LIVEBLOCKS_MENTION_TYPE, LIVEBLOCKS_GROUP_MENTION_TYPE, LIVEBLOCKS_MENTION_NOTIFIER_KEY, LIVEBLOCKS_MENTION_EXTENSION, LIVEBLOCKS_MENTION_KEY } from '../types.js';
|
|
10
9
|
import { mapFragment, getMentionsFromNode } from '../utils.js';
|
|
11
10
|
import { GroupMentionNode } from './GroupMentionNode.js';
|
|
@@ -43,9 +42,7 @@ const notifier = ({
|
|
|
43
42
|
if (!docChanges) {
|
|
44
43
|
return;
|
|
45
44
|
}
|
|
46
|
-
if (transactions.some(
|
|
47
|
-
(transaction) => transaction.getMeta(ySyncPluginKey) || transaction.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)
|
|
48
|
-
)) {
|
|
45
|
+
if (transactions.some((transaction) => transaction.getMeta(ySyncPluginKey))) {
|
|
49
46
|
return;
|
|
50
47
|
}
|
|
51
48
|
const transform = combineTransactionSteps(oldState.doc, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionExtension.js","sources":["../../src/mentions/MentionExtension.ts"],"sourcesContent":["import {\n assertNever,\n createInboxNotificationId,\n MENTION_CHARACTER,\n} from \"@liveblocks/core\";\nimport {\n combineTransactionSteps,\n type Content,\n Extension,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"../collaboration-liveblocks/plugin\";\nimport {\n LIVEBLOCKS_GROUP_MENTION_TYPE,\n LIVEBLOCKS_MENTION_EXTENSION,\n LIVEBLOCKS_MENTION_KEY,\n LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n LIVEBLOCKS_MENTION_PASTE_KEY,\n LIVEBLOCKS_MENTION_TYPE,\n type TiptapMentionData,\n} from \"../types\";\nimport { getMentionsFromNode, mapFragment } from \"../utils\";\nimport { GroupMentionNode } from \"./GroupMentionNode\";\nimport { MentionNode } from \"./MentionNode\";\nimport type { MentionsListHandle, MentionsListProps } from \"./MentionsList\";\nimport { MentionsList } from \"./MentionsList\";\n\n/**\n *\n * Handles creating new notificationIds when notifications are pasted\n *\n * @returns Plugin\n */\nconst mentionPasteHandler = (): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_PASTE_KEY,\n props: {\n transformPasted: (slice) => {\n const getNewNotificationIds = (node: ProseMirrorNode) => {\n // If this is a mention node, we need to get a new notification id\n if (\n node.type.name === LIVEBLOCKS_MENTION_TYPE ||\n node.type.name === LIVEBLOCKS_GROUP_MENTION_TYPE\n ) {\n return node.type.create(\n { ...node.attrs, notificationId: createInboxNotificationId() },\n node.content\n );\n }\n return node.copy(node.content);\n };\n const fragment = mapFragment(slice.content, getNewNotificationIds);\n return new Slice(fragment, slice.openStart, slice.openEnd);\n },\n },\n });\n};\n\nexport type MentionExtensionOptions = {\n onCreateMention: (mention: TiptapMentionData) => void;\n onDeleteMention: (notificationId: string) => void;\n};\n/**\n *\n * The purpose of this plugin is to create inbox notifications when a mention is\n *\n * @returns Plugin (from @tiptap/core)\n */\nconst notifier = ({\n onCreateMention,\n onDeleteMention,\n}: MentionExtensionOptions): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n // don't run if there was no change\n if (!docChanges) {\n return;\n }\n // don't run if from collab\n if (\n transactions.some(\n (transaction) =>\n transaction.getMeta(ySyncPluginKey) ||\n transaction.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)\n )\n ) {\n return;\n }\n const transform = combineTransactionSteps(oldState.doc, [\n ...transactions,\n ]);\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange, oldRange }) => {\n const newMentions = getMentionsFromNode(newState.doc, newRange);\n const oldMentions = getMentionsFromNode(oldState.doc, oldRange);\n\n if (oldMentions.size || newMentions.size) {\n // create new mentions\n newMentions.forEach((mention) => {\n if (!oldMentions.has(mention.notificationId)) {\n onCreateMention(mention);\n }\n });\n // delete old mentions\n oldMentions.forEach((mention) => {\n if (!newMentions.has(mention.notificationId)) {\n onDeleteMention(mention.notificationId);\n }\n });\n }\n });\n\n return undefined;\n },\n });\n};\n\nexport const MentionExtension = Extension.create<MentionExtensionOptions>({\n name: LIVEBLOCKS_MENTION_EXTENSION,\n\n priority: 101,\n addOptions() {\n return {\n onCreateMention: () => {},\n onDeleteMention: () => {},\n };\n },\n\n addExtensions() {\n return [MentionNode, GroupMentionNode];\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: MENTION_CHARACTER,\n pluginKey: LIVEBLOCKS_MENTION_KEY,\n command: ({ editor, range, props }) => {\n // increase range.to by one when the next node is of type \"text\"\n // and starts with a space character\n const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n const overrideSpace = nodeAfter?.text?.startsWith(\" \");\n\n if (overrideSpace) {\n range.to += 1;\n }\n\n const mention = props as TiptapMentionData;\n\n let mentionNode: Content;\n\n if (mention.kind === \"user\") {\n mentionNode = {\n type: LIVEBLOCKS_MENTION_TYPE,\n attrs: {\n id: mention.id,\n notificationId: mention.notificationId,\n },\n };\n } else if (mention.kind === \"group\") {\n mentionNode = {\n type: LIVEBLOCKS_GROUP_MENTION_TYPE,\n attrs: {\n id: mention.id,\n userIds: mention.userIds\n ? JSON.stringify(mention.userIds)\n : undefined,\n notificationId: mention.notificationId,\n },\n };\n } else {\n assertNever(mention, \"Unhandled mention kind\");\n }\n\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n mentionNode,\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run();\n\n // get reference to `window` object from editor element, to support cross-frame JS usage\n editor.view.dom.ownerDocument.defaultView\n ?.getSelection()\n ?.collapseToEnd();\n },\n allow: ({ state, range }) => {\n const $fromParentType = state.doc.resolve(range.from).parent.type;\n\n return Boolean(\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_MENTION_TYPE]\n ) ||\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_GROUP_MENTION_TYPE]\n )\n );\n },\n allowSpaces: true,\n items: () => [], // we'll let the mentions list component do this\n render: () => {\n let component: ReactRenderer<MentionsListHandle, MentionsListProps>;\n return {\n onStart: (props) => {\n component = new ReactRenderer<\n MentionsListHandle,\n MentionsListProps\n >(MentionsList, {\n props,\n editor: props.editor,\n });\n\n if (!props.clientRect) {\n return;\n }\n\n document.body.appendChild(component.element);\n },\n\n onUpdate(props) {\n component.updateProps(props);\n },\n\n onKeyDown(props) {\n if (props.event.key === \"Escape\") {\n component.updateProps({\n ...props,\n hide: true,\n });\n return true;\n }\n return component.ref?.onKeyDown(props) ?? false;\n },\n\n onExit() {\n if (document.body.contains(component.element)) {\n document.body.removeChild(component.element);\n }\n component.destroy();\n },\n };\n },\n }),\n notifier(this.options),\n mentionPasteHandler(),\n ];\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MentionExtension.js","sources":["../../src/mentions/MentionExtension.ts"],"sourcesContent":["import {\n assertNever,\n createInboxNotificationId,\n MENTION_CHARACTER,\n} from \"@liveblocks/core\";\nimport {\n combineTransactionSteps,\n type Content,\n Extension,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport {\n LIVEBLOCKS_GROUP_MENTION_TYPE,\n LIVEBLOCKS_MENTION_EXTENSION,\n LIVEBLOCKS_MENTION_KEY,\n LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n LIVEBLOCKS_MENTION_PASTE_KEY,\n LIVEBLOCKS_MENTION_TYPE,\n type TiptapMentionData,\n} from \"../types\";\nimport { getMentionsFromNode, mapFragment } from \"../utils\";\nimport { GroupMentionNode } from \"./GroupMentionNode\";\nimport { MentionNode } from \"./MentionNode\";\nimport type { MentionsListHandle, MentionsListProps } from \"./MentionsList\";\nimport { MentionsList } from \"./MentionsList\";\n\n/**\n *\n * Handles creating new notificationIds when notifications are pasted\n *\n * @returns Plugin\n */\nconst mentionPasteHandler = (): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_PASTE_KEY,\n props: {\n transformPasted: (slice) => {\n const getNewNotificationIds = (node: ProseMirrorNode) => {\n // If this is a mention node, we need to get a new notification id\n if (\n node.type.name === LIVEBLOCKS_MENTION_TYPE ||\n node.type.name === LIVEBLOCKS_GROUP_MENTION_TYPE\n ) {\n return node.type.create(\n { ...node.attrs, notificationId: createInboxNotificationId() },\n node.content\n );\n }\n return node.copy(node.content);\n };\n const fragment = mapFragment(slice.content, getNewNotificationIds);\n return new Slice(fragment, slice.openStart, slice.openEnd);\n },\n },\n });\n};\n\nexport type MentionExtensionOptions = {\n onCreateMention: (mention: TiptapMentionData) => void;\n onDeleteMention: (notificationId: string) => void;\n};\n/**\n *\n * The purpose of this plugin is to create inbox notifications when a mention is\n *\n * @returns Plugin (from @tiptap/core)\n */\nconst notifier = ({\n onCreateMention,\n onDeleteMention,\n}: MentionExtensionOptions): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n // don't run if there was no change\n if (!docChanges) {\n return;\n }\n // don't run if from collab\n if (\n transactions.some((transaction) => transaction.getMeta(ySyncPluginKey))\n ) {\n return;\n }\n const transform = combineTransactionSteps(oldState.doc, [\n ...transactions,\n ]);\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange, oldRange }) => {\n const newMentions = getMentionsFromNode(newState.doc, newRange);\n const oldMentions = getMentionsFromNode(oldState.doc, oldRange);\n\n if (oldMentions.size || newMentions.size) {\n // create new mentions\n newMentions.forEach((mention) => {\n if (!oldMentions.has(mention.notificationId)) {\n onCreateMention(mention);\n }\n });\n // delete old mentions\n oldMentions.forEach((mention) => {\n if (!newMentions.has(mention.notificationId)) {\n onDeleteMention(mention.notificationId);\n }\n });\n }\n });\n\n return undefined;\n },\n });\n};\n\nexport const MentionExtension = Extension.create<MentionExtensionOptions>({\n name: LIVEBLOCKS_MENTION_EXTENSION,\n\n priority: 101,\n addOptions() {\n return {\n onCreateMention: () => {},\n onDeleteMention: () => {},\n };\n },\n\n addExtensions() {\n return [MentionNode, GroupMentionNode];\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: MENTION_CHARACTER,\n pluginKey: LIVEBLOCKS_MENTION_KEY,\n command: ({ editor, range, props }) => {\n // increase range.to by one when the next node is of type \"text\"\n // and starts with a space character\n const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n const overrideSpace = nodeAfter?.text?.startsWith(\" \");\n\n if (overrideSpace) {\n range.to += 1;\n }\n\n const mention = props as TiptapMentionData;\n\n let mentionNode: Content;\n\n if (mention.kind === \"user\") {\n mentionNode = {\n type: LIVEBLOCKS_MENTION_TYPE,\n attrs: {\n id: mention.id,\n notificationId: mention.notificationId,\n },\n };\n } else if (mention.kind === \"group\") {\n mentionNode = {\n type: LIVEBLOCKS_GROUP_MENTION_TYPE,\n attrs: {\n id: mention.id,\n userIds: mention.userIds\n ? JSON.stringify(mention.userIds)\n : undefined,\n notificationId: mention.notificationId,\n },\n };\n } else {\n assertNever(mention, \"Unhandled mention kind\");\n }\n\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n mentionNode,\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run();\n\n // get reference to `window` object from editor element, to support cross-frame JS usage\n editor.view.dom.ownerDocument.defaultView\n ?.getSelection()\n ?.collapseToEnd();\n },\n allow: ({ state, range }) => {\n const $fromParentType = state.doc.resolve(range.from).parent.type;\n\n return Boolean(\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_MENTION_TYPE]\n ) ||\n $fromParentType.contentMatch.matchType(\n state.schema.nodes[LIVEBLOCKS_GROUP_MENTION_TYPE]\n )\n );\n },\n allowSpaces: true,\n items: () => [], // we'll let the mentions list component do this\n render: () => {\n let component: ReactRenderer<MentionsListHandle, MentionsListProps>;\n return {\n onStart: (props) => {\n component = new ReactRenderer<\n MentionsListHandle,\n MentionsListProps\n >(MentionsList, {\n props,\n editor: props.editor,\n });\n\n if (!props.clientRect) {\n return;\n }\n\n document.body.appendChild(component.element);\n },\n\n onUpdate(props) {\n component.updateProps(props);\n },\n\n onKeyDown(props) {\n if (props.event.key === \"Escape\") {\n component.updateProps({\n ...props,\n hide: true,\n });\n return true;\n }\n return component.ref?.onKeyDown(props) ?? false;\n },\n\n onExit() {\n if (document.body.contains(component.element)) {\n document.body.removeChild(component.element);\n }\n component.destroy();\n },\n };\n },\n }),\n notifier(this.options),\n mentionPasteHandler(),\n ];\n },\n});\n"],"names":[],"mappings":"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"}
|
package/dist/types.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","sources":["../src/types.ts"],"sourcesContent":["import type {\n ContextualPromptContext,\n ContextualPromptResponse,\n MentionData,\n Relax,\n TextEditorType,\n ThreadData,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { Content, Range } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\nimport type { ChainedCommands, SingleCommands } from \"@tiptap/react\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\nimport type { Doc, PermanentUserData, Snapshot } from \"yjs\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\n\nexport const LIVEBLOCKS_MENTION_EXTENSION = \"liveblocksMentionExt\";\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\nexport const LIVEBLOCKS_GROUP_MENTION_TYPE = \"liveblocksGroupMention\";\n\nexport const THREADS_ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-threads-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\nexport const AI_TOOLBAR_SELECTION_PLUGIN = new PluginKey(\n \"lb-ai-toolbar-selection-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptArgs = {\n /**\n * The prompt being requested by the user.\n */\n prompt: string;\n\n /**\n * The context of the document and its current selection.\n */\n context: ContextualPromptContext;\n\n /**\n * The previous request and its response, if this is a follow-up request.\n */\n previous?: {\n prompt: string;\n response: ContextualPromptResponse;\n };\n\n /**\n * An abort signal that can be used to cancel requests.\n */\n signal: AbortSignal;\n};\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptResponse = ContextualPromptResponse;\n\nexport interface AiConfiguration {\n /**\n * The AI's name. (\"Ask {name} anything…\", \"{name} is thinking…\", etc)\n */\n name?: string;\n\n /**\n * A function that returns an a response to a contextual prompt.\n */\n resolveContextualPrompt?: (\n args: ResolveContextualPromptArgs\n ) => Promise<ContextualPromptResponse>;\n}\n\nexport type LiveblocksExtensionOptions = {\n collaborationMode?: \"yjs\" | \"liveblocks\";\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n ai?: boolean | AiConfiguration;\n offlineSupport_experimental?: boolean;\n threads_experimental?: ThreadData[];\n initialContent?: Content;\n enablePermanentUserData?: boolean;\n /**\n * @internal\n * For reporting another text editor type from a\n * text editor extended from `TipTap` such as our `BlockNote` integration.\n *\n * Only useful for Liveblocks developers, not for end users.\n */\n textEditorType?: TextEditorType;\n};\n\nexport type LiveblocksExtensionStorage =\n | {\n mode: \"yjs\";\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider;\n permanentUserData?: PermanentUserData;\n }\n | {\n mode: \"liveblocks\";\n unsubs: (() => void)[];\n };\n\nexport type CommentsExtensionStorage = {\n pendingComment: boolean;\n};\n\nexport const enum ThreadPluginActions {\n SET_ACTIVE_THREAD_IDS = \"SET_ACTIVE_THREAD_IDS\",\n}\n\nexport type AiExtensionOptions = Required<\n Pick<AiConfiguration, \"name\" | \"resolveContextualPrompt\">\n> & {\n doc: Doc | undefined;\n pud: PermanentUserData | undefined;\n};\n\n/**\n * The state of the AI toolbar.\n *\n * ┌────────────────────────────────────────────────────────────────────────────────┐\n * │ │\n * │ ┌──────────────────────────────────────────────┐ │\n * ▼ ▼ │ │\n * ┌───────$closeAiToolbar()───────┐ │ │\n * ▼ ◇ ◇ ◇\n * ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐\n * │ CLOSED │ │ ASKING │ │ THINKING │ │ REVIEWING │\n * └───────────────────────┘ └───────────────────────┘ └───────────────────────┘ └───────────────────────┘\n * ▲ ◇ ◇ ▲ ▲ ◇ ▲ ▲ ◇ ▲ ◇ ◇\n * │ │ └───$openAiToolbarAsking()──┘ │ │ └ ─ ─ ─ ─ ─ ─⚠─ ─ ─ ─ ─ ─ ─│─├── ─ ─ ─ ─ ─ ─✓─ ─ ─ ─ ─ ─ ─ ┘ │ │\n * │ │ │ ▼ │ │ │ │\n * │ └─────────────────$startAiToolbarThinking(prompt)──────────────┘ │ │ │\n * │ │ ▲ │ │ │\n * │ │ └──────────────────────────────┼───────────────────────────────┘ │\n * │ │ │ │\n * │ └───$cancelAiToolbarThinking()───┘ │\n * │ │\n * └─────────────────────────────────────$acceptAiToolbarResponse()─────────────────────────────────────┘\n *\n */\nexport type AiToolbarState = Relax<\n | {\n phase: \"closed\";\n }\n | {\n phase: \"asking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * A potential error that occurred during the last AI request.\n */\n error?: Error;\n }\n | {\n phase: \"thinking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * An abort controller to cancel the AI request.\n */\n abortController: AbortController;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The previous response if this \"thinking\" phase is a refinement.\n */\n previousResponse?: ContextualPromptResponse;\n }\n | {\n phase: \"reviewing\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The response of the AI request.\n */\n response: ContextualPromptResponse;\n }\n>;\n\nexport type AiExtensionStorage = {\n name: string;\n state: AiToolbarState;\n snapshot?: Snapshot;\n};\n\ndeclare module \"@tiptap/core\" {\n interface Storage {\n liveblocksAi: AiExtensionStorage;\n liveblocksExtension: LiveblocksExtensionStorage;\n liveblocksComments: CommentsExtensionStorage;\n }\n // TODO: this is already defined in collaboration-caret, we shouldn't need it, but something isn't working\n // maybe because we use configure?\n interface Commands<ReturnType> {\n collaborationCaret: {\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-caret\n */\n user: (attributes: Record<string, any>) => ReturnType;\n };\n\n collaboration: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType;\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType;\n };\n }\n}\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n activeThreadIds: string[];\n decorations: DecorationSet;\n};\n\nexport type FloatingPosition = \"top\" | \"bottom\";\n\nexport type ExtendedCommands<\n T extends string,\n A extends any[] = [],\n> = SingleCommands & Record<T, (...args: A) => boolean>;\n\nexport type ExtendedChainedCommands<\n T extends string,\n A extends any[] = [],\n> = ChainedCommands & Record<T, (...args: A) => ChainedCommands>;\n\nexport type ChainedAiCommands = ChainedCommands & {\n [K in keyof AiCommands]: (\n ...args: Parameters<AiCommands[K]>\n ) => ChainedCommands;\n};\n\nexport type CommentsCommands<ReturnType = boolean> = {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n\n /** @internal */\n closePendingComment: () => ReturnType;\n};\n\nexport type AiCommands<ReturnType = boolean> = {\n /**\n * Open the AI toolbar, with an optional prompt.\n */\n askAi: (prompt?: string) => ReturnType;\n\n /**\n * Close the AI toolbar.\n */\n closeAi: () => ReturnType;\n\n // Transitions (see AiToolbarState)\n\n /**\n * @internal\n * @transition\n *\n * Close the AI toolbar.\n */\n $closeAiToolbar: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Accept the current AI response and close the AI toolbar.\n */\n $acceptAiToolbarResponse: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Open the AI toolbar in the \"asking\" phase.\n */\n $openAiToolbarAsking: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Set (and open if not already open) the AI toolbar in the \"thinking\" phase with the given prompt.\n */\n $startAiToolbarThinking: (\n prompt: string,\n withPreviousResponse?: boolean\n ) => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Cancel the current \"thinking\" phase, going back to the \"asking\" phase.\n */\n $cancelAiToolbarThinking: () => ReturnType;\n\n // Other\n\n /**\n * @internal\n *\n * Show the diff of the current \"reviewing\" phase.\n */\n _showAiToolbarReviewingDiff: () => ReturnType;\n\n /**\n * @internal\n *\n * Handle the success of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingSuccess: (\n response: ContextualPromptResponse\n ) => ReturnType;\n\n /**\n * @internal\n *\n * Handle an error of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingError: (error: unknown) => ReturnType;\n\n /**\n * @internal\n *\n * Update the current custom AI prompt.\n */\n _updateAiToolbarCustomPrompt: (\n customPrompt: string | ((currentCustomPrompt: string) => string)\n ) => ReturnType;\n};\n\nexport type YSyncPluginState = {\n binding: ProsemirrorBinding;\n};\n\nexport type TiptapMentionData = MentionData & {\n notificationId: string;\n};\n\nexport type SerializedTiptapMentionData = TiptapMentionData extends infer T\n ? T extends { kind: \"group\" }\n ? Omit<T, \"userIds\"> & { userIds?: string }\n : T\n : never;\n"],"names":["PluginKey","ThreadPluginActions"],"mappings":";;;;AAgBa,MAAA,sBAAA,GAAyB,IAAIA,eAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAIA,eAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAIA,eAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,uBAAA;AACrC,MAAM,uBAA0B,GAAA,oBAAA;AAChC,MAAM,6BAAgC,GAAA,yBAAA;AAEtC,MAAM,kCAAkC,IAAIA,eAAA;AAAA,EACjD,oCAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAIA,eAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AACO,MAAM,8BAA8B,IAAIA,eAAA;AAAA,EAC7C,gCAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AAsF1B,IAAA,mBAAA,qBAAAC,oBAAX,KAAA;AACL,EAAAA,qBAAA,uBAAwB,CAAA,GAAA,uBAAA,CAAA;AADR,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"types.cjs","sources":["../src/types.ts"],"sourcesContent":["import type {\n ContextualPromptContext,\n ContextualPromptResponse,\n MentionData,\n Relax,\n TextEditorType,\n ThreadData,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { Content, Range } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\nimport type { ChainedCommands, SingleCommands } from \"@tiptap/react\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\nimport type { Doc, PermanentUserData, Snapshot } from \"yjs\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\n\nexport const LIVEBLOCKS_MENTION_EXTENSION = \"liveblocksMentionExt\";\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\nexport const LIVEBLOCKS_GROUP_MENTION_TYPE = \"liveblocksGroupMention\";\n\nexport const THREADS_ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-threads-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\nexport const AI_TOOLBAR_SELECTION_PLUGIN = new PluginKey(\n \"lb-ai-toolbar-selection-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptArgs = {\n /**\n * The prompt being requested by the user.\n */\n prompt: string;\n\n /**\n * The context of the document and its current selection.\n */\n context: ContextualPromptContext;\n\n /**\n * The previous request and its response, if this is a follow-up request.\n */\n previous?: {\n prompt: string;\n response: ContextualPromptResponse;\n };\n\n /**\n * An abort signal that can be used to cancel requests.\n */\n signal: AbortSignal;\n};\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptResponse = ContextualPromptResponse;\n\nexport interface AiConfiguration {\n /**\n * The AI's name. (\"Ask {name} anything…\", \"{name} is thinking…\", etc)\n */\n name?: string;\n\n /**\n * A function that returns an a response to a contextual prompt.\n */\n resolveContextualPrompt?: (\n args: ResolveContextualPromptArgs\n ) => Promise<ContextualPromptResponse>;\n}\n\nexport type LiveblocksExtensionOptions = {\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n ai?: boolean | AiConfiguration;\n offlineSupport_experimental?: boolean;\n threads_experimental?: ThreadData[];\n initialContent?: Content;\n enablePermanentUserData?: boolean;\n /**\n * @internal\n * For reporting another text editor type from a\n * text editor extended from `TipTap` such as our `BlockNote` integration.\n *\n * Only useful for Liveblocks developers, not for end users.\n */\n textEditorType?: TextEditorType;\n};\n\nexport type LiveblocksExtensionStorage = {\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider;\n permanentUserData?: PermanentUserData;\n};\n\nexport type CommentsExtensionStorage = {\n pendingComment: boolean;\n};\n\nexport const enum ThreadPluginActions {\n SET_ACTIVE_THREAD_IDS = \"SET_ACTIVE_THREAD_IDS\",\n}\n\nexport type AiExtensionOptions = Required<\n Pick<AiConfiguration, \"name\" | \"resolveContextualPrompt\">\n> & {\n doc: Doc | undefined;\n pud: PermanentUserData | undefined;\n};\n\n/**\n * The state of the AI toolbar.\n *\n * ┌────────────────────────────────────────────────────────────────────────────────┐\n * │ │\n * │ ┌──────────────────────────────────────────────┐ │\n * ▼ ▼ │ │\n * ┌───────$closeAiToolbar()───────┐ │ │\n * ▼ ◇ ◇ ◇\n * ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐\n * │ CLOSED │ │ ASKING │ │ THINKING │ │ REVIEWING │\n * └───────────────────────┘ └───────────────────────┘ └───────────────────────┘ └───────────────────────┘\n * ▲ ◇ ◇ ▲ ▲ ◇ ▲ ▲ ◇ ▲ ◇ ◇\n * │ │ └───$openAiToolbarAsking()──┘ │ │ └ ─ ─ ─ ─ ─ ─⚠─ ─ ─ ─ ─ ─ ─│─├── ─ ─ ─ ─ ─ ─✓─ ─ ─ ─ ─ ─ ─ ┘ │ │\n * │ │ │ ▼ │ │ │ │\n * │ └─────────────────$startAiToolbarThinking(prompt)──────────────┘ │ │ │\n * │ │ ▲ │ │ │\n * │ │ └──────────────────────────────┼───────────────────────────────┘ │\n * │ │ │ │\n * │ └───$cancelAiToolbarThinking()───┘ │\n * │ │\n * └─────────────────────────────────────$acceptAiToolbarResponse()─────────────────────────────────────┘\n *\n */\nexport type AiToolbarState = Relax<\n | {\n phase: \"closed\";\n }\n | {\n phase: \"asking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * A potential error that occurred during the last AI request.\n */\n error?: Error;\n }\n | {\n phase: \"thinking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * An abort controller to cancel the AI request.\n */\n abortController: AbortController;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The previous response if this \"thinking\" phase is a refinement.\n */\n previousResponse?: ContextualPromptResponse;\n }\n | {\n phase: \"reviewing\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The response of the AI request.\n */\n response: ContextualPromptResponse;\n }\n>;\n\nexport type AiExtensionStorage = {\n name: string;\n state: AiToolbarState;\n snapshot?: Snapshot;\n};\n\ndeclare module \"@tiptap/core\" {\n interface Storage {\n liveblocksAi: AiExtensionStorage;\n liveblocksExtension: LiveblocksExtensionStorage;\n liveblocksComments: CommentsExtensionStorage;\n }\n // TODO: this is already defined in collaboration-caret, we shouldn't need it, but something isn't working\n // maybe because we use configure?\n interface Commands<ReturnType> {\n collaborationCaret: {\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-caret\n */\n user: (attributes: Record<string, any>) => ReturnType;\n };\n\n collaboration: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType;\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType;\n };\n }\n}\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n activeThreadIds: string[];\n decorations: DecorationSet;\n};\n\nexport type FloatingPosition = \"top\" | \"bottom\";\n\nexport type ExtendedCommands<\n T extends string,\n A extends any[] = [],\n> = SingleCommands & Record<T, (...args: A) => boolean>;\n\nexport type ExtendedChainedCommands<\n T extends string,\n A extends any[] = [],\n> = ChainedCommands & Record<T, (...args: A) => ChainedCommands>;\n\nexport type ChainedAiCommands = ChainedCommands & {\n [K in keyof AiCommands]: (\n ...args: Parameters<AiCommands[K]>\n ) => ChainedCommands;\n};\n\nexport type CommentsCommands<ReturnType = boolean> = {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n\n /** @internal */\n closePendingComment: () => ReturnType;\n};\n\nexport type AiCommands<ReturnType = boolean> = {\n /**\n * Open the AI toolbar, with an optional prompt.\n */\n askAi: (prompt?: string) => ReturnType;\n\n /**\n * Close the AI toolbar.\n */\n closeAi: () => ReturnType;\n\n // Transitions (see AiToolbarState)\n\n /**\n * @internal\n * @transition\n *\n * Close the AI toolbar.\n */\n $closeAiToolbar: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Accept the current AI response and close the AI toolbar.\n */\n $acceptAiToolbarResponse: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Open the AI toolbar in the \"asking\" phase.\n */\n $openAiToolbarAsking: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Set (and open if not already open) the AI toolbar in the \"thinking\" phase with the given prompt.\n */\n $startAiToolbarThinking: (\n prompt: string,\n withPreviousResponse?: boolean\n ) => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Cancel the current \"thinking\" phase, going back to the \"asking\" phase.\n */\n $cancelAiToolbarThinking: () => ReturnType;\n\n // Other\n\n /**\n * @internal\n *\n * Show the diff of the current \"reviewing\" phase.\n */\n _showAiToolbarReviewingDiff: () => ReturnType;\n\n /**\n * @internal\n *\n * Handle the success of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingSuccess: (\n response: ContextualPromptResponse\n ) => ReturnType;\n\n /**\n * @internal\n *\n * Handle an error of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingError: (error: unknown) => ReturnType;\n\n /**\n * @internal\n *\n * Update the current custom AI prompt.\n */\n _updateAiToolbarCustomPrompt: (\n customPrompt: string | ((currentCustomPrompt: string) => string)\n ) => ReturnType;\n};\n\nexport type YSyncPluginState = {\n binding: ProsemirrorBinding;\n};\n\nexport type TiptapMentionData = MentionData & {\n notificationId: string;\n};\n\nexport type SerializedTiptapMentionData = TiptapMentionData extends infer T\n ? T extends { kind: \"group\" }\n ? Omit<T, \"userIds\"> & { userIds?: string }\n : T\n : never;\n"],"names":["PluginKey","ThreadPluginActions"],"mappings":";;;;AAgBa,MAAA,sBAAA,GAAyB,IAAIA,eAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAIA,eAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAIA,eAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,uBAAA;AACrC,MAAM,uBAA0B,GAAA,oBAAA;AAChC,MAAM,6BAAgC,GAAA,yBAAA;AAEtC,MAAM,kCAAkC,IAAIA,eAAA;AAAA,EACjD,oCAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAIA,eAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AACO,MAAM,8BAA8B,IAAIA,eAAA;AAAA,EAC7C,gCAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AA+E1B,IAAA,mBAAA,qBAAAC,oBAAX,KAAA;AACL,EAAAA,qBAAA,uBAAwB,CAAA,GAAA,uBAAA,CAAA;AADR,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;;;;;;;;;;;"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import type {\n ContextualPromptContext,\n ContextualPromptResponse,\n MentionData,\n Relax,\n TextEditorType,\n ThreadData,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { Content, Range } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\nimport type { ChainedCommands, SingleCommands } from \"@tiptap/react\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\nimport type { Doc, PermanentUserData, Snapshot } from \"yjs\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\n\nexport const LIVEBLOCKS_MENTION_EXTENSION = \"liveblocksMentionExt\";\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\nexport const LIVEBLOCKS_GROUP_MENTION_TYPE = \"liveblocksGroupMention\";\n\nexport const THREADS_ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-threads-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\nexport const AI_TOOLBAR_SELECTION_PLUGIN = new PluginKey(\n \"lb-ai-toolbar-selection-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptArgs = {\n /**\n * The prompt being requested by the user.\n */\n prompt: string;\n\n /**\n * The context of the document and its current selection.\n */\n context: ContextualPromptContext;\n\n /**\n * The previous request and its response, if this is a follow-up request.\n */\n previous?: {\n prompt: string;\n response: ContextualPromptResponse;\n };\n\n /**\n * An abort signal that can be used to cancel requests.\n */\n signal: AbortSignal;\n};\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptResponse = ContextualPromptResponse;\n\nexport interface AiConfiguration {\n /**\n * The AI's name. (\"Ask {name} anything…\", \"{name} is thinking…\", etc)\n */\n name?: string;\n\n /**\n * A function that returns an a response to a contextual prompt.\n */\n resolveContextualPrompt?: (\n args: ResolveContextualPromptArgs\n ) => Promise<ContextualPromptResponse>;\n}\n\nexport type LiveblocksExtensionOptions = {\n collaborationMode?: \"yjs\" | \"liveblocks\";\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n ai?: boolean | AiConfiguration;\n offlineSupport_experimental?: boolean;\n threads_experimental?: ThreadData[];\n initialContent?: Content;\n enablePermanentUserData?: boolean;\n /**\n * @internal\n * For reporting another text editor type from a\n * text editor extended from `TipTap` such as our `BlockNote` integration.\n *\n * Only useful for Liveblocks developers, not for end users.\n */\n textEditorType?: TextEditorType;\n};\n\nexport type LiveblocksExtensionStorage =\n | {\n mode: \"yjs\";\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider;\n permanentUserData?: PermanentUserData;\n }\n | {\n mode: \"liveblocks\";\n unsubs: (() => void)[];\n };\n\nexport type CommentsExtensionStorage = {\n pendingComment: boolean;\n};\n\nexport const enum ThreadPluginActions {\n SET_ACTIVE_THREAD_IDS = \"SET_ACTIVE_THREAD_IDS\",\n}\n\nexport type AiExtensionOptions = Required<\n Pick<AiConfiguration, \"name\" | \"resolveContextualPrompt\">\n> & {\n doc: Doc | undefined;\n pud: PermanentUserData | undefined;\n};\n\n/**\n * The state of the AI toolbar.\n *\n * ┌────────────────────────────────────────────────────────────────────────────────┐\n * │ │\n * │ ┌──────────────────────────────────────────────┐ │\n * ▼ ▼ │ │\n * ┌───────$closeAiToolbar()───────┐ │ │\n * ▼ ◇ ◇ ◇\n * ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐\n * │ CLOSED │ │ ASKING │ │ THINKING │ │ REVIEWING │\n * └───────────────────────┘ └───────────────────────┘ └───────────────────────┘ └───────────────────────┘\n * ▲ ◇ ◇ ▲ ▲ ◇ ▲ ▲ ◇ ▲ ◇ ◇\n * │ │ └───$openAiToolbarAsking()──┘ │ │ └ ─ ─ ─ ─ ─ ─⚠─ ─ ─ ─ ─ ─ ─│─├── ─ ─ ─ ─ ─ ─✓─ ─ ─ ─ ─ ─ ─ ┘ │ │\n * │ │ │ ▼ │ │ │ │\n * │ └─────────────────$startAiToolbarThinking(prompt)──────────────┘ │ │ │\n * │ │ ▲ │ │ │\n * │ │ └──────────────────────────────┼───────────────────────────────┘ │\n * │ │ │ │\n * │ └───$cancelAiToolbarThinking()───┘ │\n * │ │\n * └─────────────────────────────────────$acceptAiToolbarResponse()─────────────────────────────────────┘\n *\n */\nexport type AiToolbarState = Relax<\n | {\n phase: \"closed\";\n }\n | {\n phase: \"asking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * A potential error that occurred during the last AI request.\n */\n error?: Error;\n }\n | {\n phase: \"thinking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * An abort controller to cancel the AI request.\n */\n abortController: AbortController;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The previous response if this \"thinking\" phase is a refinement.\n */\n previousResponse?: ContextualPromptResponse;\n }\n | {\n phase: \"reviewing\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The response of the AI request.\n */\n response: ContextualPromptResponse;\n }\n>;\n\nexport type AiExtensionStorage = {\n name: string;\n state: AiToolbarState;\n snapshot?: Snapshot;\n};\n\ndeclare module \"@tiptap/core\" {\n interface Storage {\n liveblocksAi: AiExtensionStorage;\n liveblocksExtension: LiveblocksExtensionStorage;\n liveblocksComments: CommentsExtensionStorage;\n }\n // TODO: this is already defined in collaboration-caret, we shouldn't need it, but something isn't working\n // maybe because we use configure?\n interface Commands<ReturnType> {\n collaborationCaret: {\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-caret\n */\n user: (attributes: Record<string, any>) => ReturnType;\n };\n\n collaboration: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType;\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType;\n };\n }\n}\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n activeThreadIds: string[];\n decorations: DecorationSet;\n};\n\nexport type FloatingPosition = \"top\" | \"bottom\";\n\nexport type ExtendedCommands<\n T extends string,\n A extends any[] = [],\n> = SingleCommands & Record<T, (...args: A) => boolean>;\n\nexport type ExtendedChainedCommands<\n T extends string,\n A extends any[] = [],\n> = ChainedCommands & Record<T, (...args: A) => ChainedCommands>;\n\nexport type ChainedAiCommands = ChainedCommands & {\n [K in keyof AiCommands]: (\n ...args: Parameters<AiCommands[K]>\n ) => ChainedCommands;\n};\n\nexport type CommentsCommands<ReturnType = boolean> = {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n\n /** @internal */\n closePendingComment: () => ReturnType;\n};\n\nexport type AiCommands<ReturnType = boolean> = {\n /**\n * Open the AI toolbar, with an optional prompt.\n */\n askAi: (prompt?: string) => ReturnType;\n\n /**\n * Close the AI toolbar.\n */\n closeAi: () => ReturnType;\n\n // Transitions (see AiToolbarState)\n\n /**\n * @internal\n * @transition\n *\n * Close the AI toolbar.\n */\n $closeAiToolbar: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Accept the current AI response and close the AI toolbar.\n */\n $acceptAiToolbarResponse: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Open the AI toolbar in the \"asking\" phase.\n */\n $openAiToolbarAsking: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Set (and open if not already open) the AI toolbar in the \"thinking\" phase with the given prompt.\n */\n $startAiToolbarThinking: (\n prompt: string,\n withPreviousResponse?: boolean\n ) => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Cancel the current \"thinking\" phase, going back to the \"asking\" phase.\n */\n $cancelAiToolbarThinking: () => ReturnType;\n\n // Other\n\n /**\n * @internal\n *\n * Show the diff of the current \"reviewing\" phase.\n */\n _showAiToolbarReviewingDiff: () => ReturnType;\n\n /**\n * @internal\n *\n * Handle the success of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingSuccess: (\n response: ContextualPromptResponse\n ) => ReturnType;\n\n /**\n * @internal\n *\n * Handle an error of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingError: (error: unknown) => ReturnType;\n\n /**\n * @internal\n *\n * Update the current custom AI prompt.\n */\n _updateAiToolbarCustomPrompt: (\n customPrompt: string | ((currentCustomPrompt: string) => string)\n ) => ReturnType;\n};\n\nexport type YSyncPluginState = {\n binding: ProsemirrorBinding;\n};\n\nexport type TiptapMentionData = MentionData & {\n notificationId: string;\n};\n\nexport type SerializedTiptapMentionData = TiptapMentionData extends infer T\n ? T extends { kind: \"group\" }\n ? Omit<T, \"userIds\"> & { userIds?: string }\n : T\n : never;\n"],"names":["ThreadPluginActions"],"mappings":";;AAgBa,MAAA,sBAAA,GAAyB,IAAI,SAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAI,SAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAI,SAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,uBAAA;AACrC,MAAM,uBAA0B,GAAA,oBAAA;AAChC,MAAM,6BAAgC,GAAA,yBAAA;AAEtC,MAAM,kCAAkC,IAAI,SAAA;AAAA,EACjD,oCAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAI,SAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AACO,MAAM,8BAA8B,IAAI,SAAA;AAAA,EAC7C,gCAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AAsF1B,IAAA,mBAAA,qBAAAA,oBAAX,KAAA;AACL,EAAAA,qBAAA,uBAAwB,CAAA,GAAA,uBAAA,CAAA;AADR,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import type {\n ContextualPromptContext,\n ContextualPromptResponse,\n MentionData,\n Relax,\n TextEditorType,\n ThreadData,\n} from \"@liveblocks/core\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { Content, Range } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\nimport type { ChainedCommands, SingleCommands } from \"@tiptap/react\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\nimport type { Doc, PermanentUserData, Snapshot } from \"yjs\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\n\nexport const LIVEBLOCKS_MENTION_EXTENSION = \"liveblocksMentionExt\";\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\nexport const LIVEBLOCKS_GROUP_MENTION_TYPE = \"liveblocksGroupMention\";\n\nexport const THREADS_ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-threads-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\nexport const AI_TOOLBAR_SELECTION_PLUGIN = new PluginKey(\n \"lb-ai-toolbar-selection-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptArgs = {\n /**\n * The prompt being requested by the user.\n */\n prompt: string;\n\n /**\n * The context of the document and its current selection.\n */\n context: ContextualPromptContext;\n\n /**\n * The previous request and its response, if this is a follow-up request.\n */\n previous?: {\n prompt: string;\n response: ContextualPromptResponse;\n };\n\n /**\n * An abort signal that can be used to cancel requests.\n */\n signal: AbortSignal;\n};\n\n/**\n * @beta\n */\nexport type ResolveContextualPromptResponse = ContextualPromptResponse;\n\nexport interface AiConfiguration {\n /**\n * The AI's name. (\"Ask {name} anything…\", \"{name} is thinking…\", etc)\n */\n name?: string;\n\n /**\n * A function that returns an a response to a contextual prompt.\n */\n resolveContextualPrompt?: (\n args: ResolveContextualPromptArgs\n ) => Promise<ContextualPromptResponse>;\n}\n\nexport type LiveblocksExtensionOptions = {\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n ai?: boolean | AiConfiguration;\n offlineSupport_experimental?: boolean;\n threads_experimental?: ThreadData[];\n initialContent?: Content;\n enablePermanentUserData?: boolean;\n /**\n * @internal\n * For reporting another text editor type from a\n * text editor extended from `TipTap` such as our `BlockNote` integration.\n *\n * Only useful for Liveblocks developers, not for end users.\n */\n textEditorType?: TextEditorType;\n};\n\nexport type LiveblocksExtensionStorage = {\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider;\n permanentUserData?: PermanentUserData;\n};\n\nexport type CommentsExtensionStorage = {\n pendingComment: boolean;\n};\n\nexport const enum ThreadPluginActions {\n SET_ACTIVE_THREAD_IDS = \"SET_ACTIVE_THREAD_IDS\",\n}\n\nexport type AiExtensionOptions = Required<\n Pick<AiConfiguration, \"name\" | \"resolveContextualPrompt\">\n> & {\n doc: Doc | undefined;\n pud: PermanentUserData | undefined;\n};\n\n/**\n * The state of the AI toolbar.\n *\n * ┌────────────────────────────────────────────────────────────────────────────────┐\n * │ │\n * │ ┌──────────────────────────────────────────────┐ │\n * ▼ ▼ │ │\n * ┌───────$closeAiToolbar()───────┐ │ │\n * ▼ ◇ ◇ ◇\n * ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐\n * │ CLOSED │ │ ASKING │ │ THINKING │ │ REVIEWING │\n * └───────────────────────┘ └───────────────────────┘ └───────────────────────┘ └───────────────────────┘\n * ▲ ◇ ◇ ▲ ▲ ◇ ▲ ▲ ◇ ▲ ◇ ◇\n * │ │ └───$openAiToolbarAsking()──┘ │ │ └ ─ ─ ─ ─ ─ ─⚠─ ─ ─ ─ ─ ─ ─│─├── ─ ─ ─ ─ ─ ─✓─ ─ ─ ─ ─ ─ ─ ┘ │ │\n * │ │ │ ▼ │ │ │ │\n * │ └─────────────────$startAiToolbarThinking(prompt)──────────────┘ │ │ │\n * │ │ ▲ │ │ │\n * │ │ └──────────────────────────────┼───────────────────────────────┘ │\n * │ │ │ │\n * │ └───$cancelAiToolbarThinking()───┘ │\n * │ │\n * └─────────────────────────────────────$acceptAiToolbarResponse()─────────────────────────────────────┘\n *\n */\nexport type AiToolbarState = Relax<\n | {\n phase: \"closed\";\n }\n | {\n phase: \"asking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * A potential error that occurred during the last AI request.\n */\n error?: Error;\n }\n | {\n phase: \"thinking\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * An abort controller to cancel the AI request.\n */\n abortController: AbortController;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The previous response if this \"thinking\" phase is a refinement.\n */\n previousResponse?: ContextualPromptResponse;\n }\n | {\n phase: \"reviewing\";\n\n /**\n * The selection stored when opening the AI toolbar.\n */\n initialSelection: Range;\n\n /**\n * The custom prompt being written in the toolbar.\n */\n customPrompt: string;\n\n /**\n * The prompt sent to the AI.\n */\n prompt: string;\n\n /**\n * The response of the AI request.\n */\n response: ContextualPromptResponse;\n }\n>;\n\nexport type AiExtensionStorage = {\n name: string;\n state: AiToolbarState;\n snapshot?: Snapshot;\n};\n\ndeclare module \"@tiptap/core\" {\n interface Storage {\n liveblocksAi: AiExtensionStorage;\n liveblocksExtension: LiveblocksExtensionStorage;\n liveblocksComments: CommentsExtensionStorage;\n }\n // TODO: this is already defined in collaboration-caret, we shouldn't need it, but something isn't working\n // maybe because we use configure?\n interface Commands<ReturnType> {\n collaborationCaret: {\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-caret\n */\n user: (attributes: Record<string, any>) => ReturnType;\n };\n\n collaboration: {\n /**\n * Undo recent changes\n * @example editor.commands.undo()\n */\n undo: () => ReturnType;\n /**\n * Reapply reverted changes\n * @example editor.commands.redo()\n */\n redo: () => ReturnType;\n };\n }\n}\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n activeThreadIds: string[];\n decorations: DecorationSet;\n};\n\nexport type FloatingPosition = \"top\" | \"bottom\";\n\nexport type ExtendedCommands<\n T extends string,\n A extends any[] = [],\n> = SingleCommands & Record<T, (...args: A) => boolean>;\n\nexport type ExtendedChainedCommands<\n T extends string,\n A extends any[] = [],\n> = ChainedCommands & Record<T, (...args: A) => ChainedCommands>;\n\nexport type ChainedAiCommands = ChainedCommands & {\n [K in keyof AiCommands]: (\n ...args: Parameters<AiCommands[K]>\n ) => ChainedCommands;\n};\n\nexport type CommentsCommands<ReturnType = boolean> = {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n\n /** @internal */\n closePendingComment: () => ReturnType;\n};\n\nexport type AiCommands<ReturnType = boolean> = {\n /**\n * Open the AI toolbar, with an optional prompt.\n */\n askAi: (prompt?: string) => ReturnType;\n\n /**\n * Close the AI toolbar.\n */\n closeAi: () => ReturnType;\n\n // Transitions (see AiToolbarState)\n\n /**\n * @internal\n * @transition\n *\n * Close the AI toolbar.\n */\n $closeAiToolbar: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Accept the current AI response and close the AI toolbar.\n */\n $acceptAiToolbarResponse: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Open the AI toolbar in the \"asking\" phase.\n */\n $openAiToolbarAsking: () => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Set (and open if not already open) the AI toolbar in the \"thinking\" phase with the given prompt.\n */\n $startAiToolbarThinking: (\n prompt: string,\n withPreviousResponse?: boolean\n ) => ReturnType;\n\n /**\n * @internal\n * @transition\n *\n * Cancel the current \"thinking\" phase, going back to the \"asking\" phase.\n */\n $cancelAiToolbarThinking: () => ReturnType;\n\n // Other\n\n /**\n * @internal\n *\n * Show the diff of the current \"reviewing\" phase.\n */\n _showAiToolbarReviewingDiff: () => ReturnType;\n\n /**\n * @internal\n *\n * Handle the success of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingSuccess: (\n response: ContextualPromptResponse\n ) => ReturnType;\n\n /**\n * @internal\n *\n * Handle an error of the current \"thinking\" phase.\n */\n _handleAiToolbarThinkingError: (error: unknown) => ReturnType;\n\n /**\n * @internal\n *\n * Update the current custom AI prompt.\n */\n _updateAiToolbarCustomPrompt: (\n customPrompt: string | ((currentCustomPrompt: string) => string)\n ) => ReturnType;\n};\n\nexport type YSyncPluginState = {\n binding: ProsemirrorBinding;\n};\n\nexport type TiptapMentionData = MentionData & {\n notificationId: string;\n};\n\nexport type SerializedTiptapMentionData = TiptapMentionData extends infer T\n ? T extends { kind: \"group\" }\n ? Omit<T, \"userIds\"> & { userIds?: string }\n : T\n : never;\n"],"names":["ThreadPluginActions"],"mappings":";;AAgBa,MAAA,sBAAA,GAAyB,IAAI,SAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAI,SAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAI,SAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,uBAAA;AACrC,MAAM,uBAA0B,GAAA,oBAAA;AAChC,MAAM,6BAAgC,GAAA,yBAAA;AAEtC,MAAM,kCAAkC,IAAI,SAAA;AAAA,EACjD,oCAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAI,SAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AACO,MAAM,8BAA8B,IAAI,SAAA;AAAA,EAC7C,gCAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AA+E1B,IAAA,mBAAA,qBAAAA,oBAAX,KAAA;AACL,EAAAA,qBAAA,uBAAwB,CAAA,GAAA,uBAAA,CAAA;AADR,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;"}
|
package/dist/version.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const PKG_NAME = "@liveblocks/react-tiptap";
|
|
4
|
-
const PKG_VERSION = typeof "3.19.4
|
|
4
|
+
const PKG_VERSION = typeof "3.19.4" === "string" && "3.19.4";
|
|
5
5
|
const PKG_FORMAT = typeof "cjs" === "string" && "cjs";
|
|
6
6
|
|
|
7
7
|
exports.PKG_FORMAT = PKG_FORMAT;
|
package/dist/version.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.cjs","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-tiptap\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,2BAAA;AACX,MAAA,WAAA,GAAc,OAAO,
|
|
1
|
+
{"version":3,"file":"version.cjs","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-tiptap\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,2BAAA;AACX,MAAA,WAAA,GAAc,OAAO,QAAA,KAAgB,QAAY,IAAA,SAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;;;"}
|
package/dist/version.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PKG_NAME = "@liveblocks/react-tiptap";
|
|
2
|
-
const PKG_VERSION = typeof "3.19.4
|
|
2
|
+
const PKG_VERSION = typeof "3.19.4" === "string" && "3.19.4";
|
|
3
3
|
const PKG_FORMAT = typeof "esm" === "string" && "esm";
|
|
4
4
|
|
|
5
5
|
export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
|
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-tiptap\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,2BAAA;AACX,MAAA,WAAA,GAAc,OAAO,
|
|
1
|
+
{"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-tiptap\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,2BAAA;AACX,MAAA,WAAA,GAAc,OAAO,QAAA,KAAgB,QAAY,IAAA,SAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react-tiptap",
|
|
3
|
-
"version": "3.19.4
|
|
3
|
+
"version": "3.19.4",
|
|
4
4
|
"description": "An integration of TipTap + React to enable collaboration, comments, live cursors, and more with Liveblocks.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Liveblocks Inc.",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"cmdk": "^1.0.4",
|
|
38
38
|
"radix-ui": "^1.4.0",
|
|
39
39
|
"y-prosemirror": "^1.3.7",
|
|
40
|
-
"@liveblocks/client": "3.19.4
|
|
41
|
-
"@liveblocks/
|
|
42
|
-
"@liveblocks/react
|
|
43
|
-
"@liveblocks/
|
|
44
|
-
"@liveblocks/
|
|
40
|
+
"@liveblocks/client": "3.19.4",
|
|
41
|
+
"@liveblocks/core": "3.19.4",
|
|
42
|
+
"@liveblocks/react": "3.19.4",
|
|
43
|
+
"@liveblocks/react-ui": "3.19.4",
|
|
44
|
+
"@liveblocks/yjs": "3.19.4"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@tiptap/core": "^3",
|
package/src/styles/index.css
CHANGED
|
@@ -622,22 +622,14 @@
|
|
|
622
622
|
.collaboration-carets__caret,
|
|
623
623
|
.collaboration-cursor__caret {
|
|
624
624
|
position: relative;
|
|
625
|
+
margin-inline-start: -1px;
|
|
626
|
+
margin-inline-end: -1px;
|
|
627
|
+
border-inline-start: 1px solid #0d0d0d;
|
|
628
|
+
border-inline-end: 1px solid #0d0d0d;
|
|
625
629
|
word-break: normal;
|
|
626
630
|
pointer-events: none;
|
|
627
631
|
}
|
|
628
632
|
|
|
629
|
-
.collaboration-carets__caret::after,
|
|
630
|
-
.collaboration-cursor__caret::after {
|
|
631
|
-
content: "";
|
|
632
|
-
position: absolute;
|
|
633
|
-
inset-inline-start: -1px;
|
|
634
|
-
inset-block-start: -0.15em;
|
|
635
|
-
block-size: 1.3em;
|
|
636
|
-
border-inline-start-width: 2px;
|
|
637
|
-
border-inline-start-style: solid;
|
|
638
|
-
border-inline-start-color: inherit;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
633
|
/* Render the username above the caret */
|
|
642
634
|
.collaboration-carets__label,
|
|
643
635
|
.collaboration-cursor__label {
|