@liveblocks/react-tiptap 2.22.0 → 2.22.2

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.
@@ -3,6 +3,7 @@
3
3
  var core$1 = require('@liveblocks/core');
4
4
  var react$1 = require('@liveblocks/react');
5
5
  var _private = require('@liveblocks/react/_private');
6
+ var _private$1 = require('@liveblocks/react-ui/_private');
6
7
  var yjs = require('@liveblocks/yjs');
7
8
  var core = require('@tiptap/core');
8
9
  var Collaboration = require('@tiptap/extension-collaboration');
@@ -118,6 +119,9 @@ const useLiveblocksExtension = (opts) => {
118
119
  ...DEFAULT_OPTIONS,
119
120
  ...opts
120
121
  };
122
+ const textEditorType = _private$1.useInitial(
123
+ options.textEditorType ?? core$1.TextEditorType.TipTap
124
+ );
121
125
  const editor = react.useRef(null);
122
126
  const room = react$1.useRoom();
123
127
  const isEditorReady = useIsEditorReady();
@@ -135,10 +139,7 @@ const useLiveblocksExtension = (opts) => {
135
139
  editor.current.commands.setContent(options.initialContent);
136
140
  }
137
141
  }, [isEditorReady, yjsProvider, options.initialContent]);
138
- _private.useReportTextEditor(
139
- core$1.TextEditorType.TipTap,
140
- options.field ?? DEFAULT_OPTIONS.field
141
- );
142
+ _private.useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);
142
143
  const createTextMention = _private.useCreateTextMention();
143
144
  const deleteTextMention = _private.useDeleteTextMention();
144
145
  return core.Extension.create({
@@ -1 +1 @@
1
- {"version":3,"file":"LiveblocksExtension.cjs","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\")\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, commentMarkType);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":["useYjsProvider","useCallback","useSyncExternalStore","Mark","useRef","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","TextEditorType","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","getYjsProviderForRoom","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":"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"}
1
+ {"version":3,"file":"LiveblocksExtension.cjs","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\")\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, commentMarkType);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":["useYjsProvider","useCallback","useSyncExternalStore","Mark","useInitial","TextEditorType","useRef","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","getYjsProviderForRoom","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { TextEditorType, kInternal } from '@liveblocks/core';
2
2
  import { useRoom, useClient } from '@liveblocks/react';
3
3
  import { useYjsProvider, getUmbrellaStoreForClient, useReportTextEditor, useCreateTextMention, useDeleteTextMention } from '@liveblocks/react/_private';
4
+ import { useInitial } from '@liveblocks/react-ui/_private';
4
5
  import { getYjsProviderForRoom } from '@liveblocks/yjs';
5
6
  import { Mark, Extension, getMarkType } from '@tiptap/core';
6
7
  import Collaboration from '@tiptap/extension-collaboration';
@@ -116,6 +117,9 @@ const useLiveblocksExtension = (opts) => {
116
117
  ...DEFAULT_OPTIONS,
117
118
  ...opts
118
119
  };
120
+ const textEditorType = useInitial(
121
+ options.textEditorType ?? TextEditorType.TipTap
122
+ );
119
123
  const editor = useRef(null);
120
124
  const room = useRoom();
121
125
  const isEditorReady = useIsEditorReady();
@@ -133,10 +137,7 @@ const useLiveblocksExtension = (opts) => {
133
137
  editor.current.commands.setContent(options.initialContent);
134
138
  }
135
139
  }, [isEditorReady, yjsProvider, options.initialContent]);
136
- useReportTextEditor(
137
- TextEditorType.TipTap,
138
- options.field ?? DEFAULT_OPTIONS.field
139
- );
140
+ useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);
140
141
  const createTextMention = useCreateTextMention();
141
142
  const deleteTextMention = useDeleteTextMention();
142
143
  return Extension.create({
@@ -1 +1 @@
1
- {"version":3,"file":"LiveblocksExtension.js","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(\n TextEditorType.TipTap,\n options.field ?? DEFAULT_OPTIONS.field\n );\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\")\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, commentMarkType);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LiveblocksExtension.js","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import type {\n BaseUserMeta,\n IUserInfo,\n JsonObject,\n User,\n} from \"@liveblocks/core\";\nimport { kInternal, TextEditorType } from \"@liveblocks/core\";\nimport { useClient, useRoom } from \"@liveblocks/react\";\nimport {\n getUmbrellaStoreForClient,\n useCreateTextMention,\n useDeleteTextMention,\n useReportTextEditor,\n useYjsProvider,\n} from \"@liveblocks/react/_private\";\nimport { useInitial } from \"@liveblocks/react-ui/_private\";\nimport type { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport { getYjsProviderForRoom } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType, Mark } from \"@tiptap/core\";\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport type { Mark as PMMark } from \"@tiptap/pm/model\";\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\n\nimport { AiExtension } from \"./ai/AiExtension\";\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport type {\n LiveblocksExtensionOptions,\n LiveblocksExtensionStorage,\n ResolveContextualPromptArgs,\n ResolveContextualPromptResponse,\n} from \"./types\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: false,\n enablePermanentUserData: false,\n};\n\nconst LiveblocksCollab = Collaboration.extend({\n // Override the onCreate method to warn users about potential misconfigurations\n onCreate() {\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"doc\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap document extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n !this.editor.extensionManager.extensions.find(\n (e) => e.name === \"paragraph\"\n )\n ) {\n console.warn(\n \"[Liveblocks] The tiptap paragraph extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n\n if (\n !this.editor.extensionManager.extensions.find((e) => e.name === \"text\")\n ) {\n console.warn(\n \"[Liveblocks] The tiptap text extension is required for Liveblocks collaboration. Please add it or use Tiptap StarterKit extension.\"\n );\n }\n if (\n this.editor.extensionManager.extensions.find((e) => e.name === \"history\")\n ) {\n console.warn(\n \"[Liveblocks] The history extension is enabled, Liveblocks extension provides its own. Please remove or disable the History plugin to prevent unwanted conflicts.\"\n );\n }\n },\n});\n\n/**\n * Returns whether the editor has loaded the initial text contents from the\n * server and is ready to be used.\n *\n */\nexport function useIsEditorReady(): boolean {\n const yjsProvider = useYjsProvider();\n\n const getSnapshot = useCallback(() => {\n const status = yjsProvider?.getStatus();\n return status === \"synchronizing\" || status === \"synchronized\";\n }, [yjsProvider]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n if (yjsProvider === undefined) return () => {};\n yjsProvider.on(\"status\", callback);\n return () => {\n yjsProvider.off(\"status\", callback);\n };\n },\n [yjsProvider]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst YChangeMark = Mark.create({\n name: \"ychange\",\n inclusive: false,\n parseHTML() {\n return [{ tag: \"ychange\" }];\n },\n addAttributes() {\n return {\n user: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_user\") ?? null,\n renderHTML: (attributes: { user: string | null }) => {\n if (!attributes.user) {\n return {};\n }\n return { \"data-ychange-user\": attributes.user };\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"ychange_type\") ?? null,\n renderHTML: (attributes: { type: string | null }) => {\n if (!attributes.type) {\n return {};\n }\n return {\n \"data-ychange-type\": attributes.type,\n \"data-liveblocks\": \"\",\n class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`,\n };\n },\n },\n color: {\n default: null,\n parseHTML: (element) => {\n return element.getAttribute(\"ychange_color\") ?? null;\n },\n renderHTML: () => {\n // attributes: { color: { light: string; dark: string } | null }\n return {}; // we don't need this color attribute for now\n },\n },\n };\n },\n renderHTML({ HTMLAttributes }) {\n return [\"ychange\", HTMLAttributes, 0];\n },\n});\n\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const textEditorType = useInitial<TextEditorType>(\n options.textEditorType ?? TextEditorType.TipTap\n );\n const editor = useRef<Editor | null>(null);\n const room = useRoom();\n\n // TODO: we don't need these things if comments isn't turned on...\n // TODO: we don't have a reference to the editor here, need to figure this out\n // useErrorListener((error) => {\n // // If thread creation fails, we remove the thread id from the associated nodes and unwrap the nodes if they are no longer associated with any threads\n // if (\n // error.context.type === \"CREATE_THREAD_ERROR\" &&\n // error.context.roomId === room.id\n // ) {\n // handleThreadDelete(error.context.threadId);\n // }\n // });\n\n const isEditorReady = useIsEditorReady();\n const client = useClient();\n const store = getUmbrellaStoreForClient(client);\n const roomId = room.id;\n const yjsProvider = useYjsProvider();\n\n // If the user provided initialContent, wait for ready and then set it\n useEffect(() => {\n if (\n !isEditorReady ||\n !yjsProvider ||\n !options.initialContent ||\n !editor.current\n )\n return;\n\n // As noted in the tiptap documentation, you may not set initial content with collaboration.\n // The docs provide the following workaround:\n const ydoc = (yjsProvider as LiveblocksYjsProvider).getYDoc();\n const hasContentSet = ydoc.getMap(\"liveblocks_config\").get(\"hasContentSet\");\n if (!hasContentSet) {\n ydoc.getMap(\"liveblocks_config\").set(\"hasContentSet\", true);\n editor.current.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent]);\n\n useReportTextEditor(textEditorType, options.field ?? DEFAULT_OPTIONS.field);\n\n const createTextMention = useCreateTextMention();\n const deleteTextMention = useDeleteTextMention();\n\n return Extension.create<never, LiveblocksExtensionStorage>({\n name: \"liveblocksExtension\",\n\n onCreate() {\n editor.current = this.editor;\n if (this.editor.options.content) {\n console.warn(\n \"[Liveblocks] Initial content must be set in the useLiveblocksExtension hook option. Remove content from your editor options.\"\n );\n }\n if (\n options.mentions &&\n this.editor.extensionManager.extensions.find(\n (e) => e.name.toLowerCase() === \"mention\"\n )\n ) {\n console.warn(\n \"[Liveblocks] Liveblocks own mention plugin is enabled, using another mention plugin may cause a conflict.\"\n );\n }\n const self = room.getSelf();\n const updateUser = ({\n info,\n id: userId,\n }: User<JsonObject, BaseUserMeta>) => {\n if (!info) {\n return;\n }\n const { user: storedUser } =\n this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n if (this.storage.permanentUserData) {\n const pud = this.storage.permanentUserData.clients.get(\n this.storage.doc.clientID\n );\n // Only update if there is no entry or if the entry is different\n if (!pud || pud !== userId) {\n this.storage.permanentUserData.setUserMapping(\n this.storage.doc,\n this.storage.doc.clientID,\n userId ?? \"Unknown\" // TODO: change this to the user's ID so we can map it to the user's name\n );\n }\n }\n if (\n info.name !== storedUser?.name ||\n info.color !== storedUser?.color\n ) {\n this.editor.commands.updateUser({\n name: info.name,\n color: info.color,\n });\n }\n };\n // if we already have user info, we update the user\n if (self?.info) {\n updateUser(self);\n }\n // we also listen in case the user info changes\n this.storage.unsubs.push(room.events.self.subscribe(updateUser));\n if (options.comments) {\n const commentMarkType = getMarkType(\n LIVEBLOCKS_COMMENT_MARK_TYPE,\n this.editor.schema\n );\n this.storage.unsubs.push(\n // Subscribe to threads so we can update comment marks if they become resolved/deleted\n store.outputs.threads.subscribe(() => {\n const threadMap = new Map(\n store.outputs.threads\n .get()\n .findMany(roomId, { resolved: false }, \"asc\")\n .map((thread) => [thread.id, true])\n );\n function isComment(mark: PMMark): mark is PMMark & {\n attrs: { orphan: boolean; threadId: string };\n } {\n return mark.type.name === LIVEBLOCKS_COMMENT_MARK_TYPE;\n }\n // when threads change, find marks and update them if needed\n this.editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (isComment(mark)) {\n const markThreadId = mark.attrs.threadId;\n const isOrphan = !threadMap.has(markThreadId);\n if (isOrphan !== mark.attrs.orphan) {\n const { tr } = this.editor.state;\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n this.editor.state.doc.content.size - 1\n );\n tr.removeMark(trimmedFrom, trimmedTo, commentMarkType);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n commentMarkType.create({\n ...mark.attrs,\n orphan: isOrphan,\n })\n );\n this.editor.view.dispatch(tr);\n }\n }\n });\n });\n })\n );\n }\n },\n onDestroy() {\n this.storage.unsubs.forEach((unsub) => unsub());\n },\n addGlobalAttributes() {\n return [\n {\n types: [\"paragraph\", \"heading\"],\n attributes: {\n ychange: { default: null },\n },\n },\n ];\n },\n addStorage() {\n const provider = getYjsProviderForRoom(room, {\n enablePermanentUserData:\n !!options.ai || options.enablePermanentUserData,\n offlineSupport_experimental: options.offlineSupport_experimental,\n });\n return {\n doc: provider.getYDoc(),\n provider,\n permanentUserData: provider.permanentUserData,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n YChangeMark,\n LiveblocksCollab.configure({\n ySyncOptions: {\n permanentUserData: this.storage.permanentUserData,\n },\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider,\n }),\n ];\n\n if (options.comments) {\n extensions.push(CommentsExtension);\n }\n if (options.mentions) {\n extensions.push(\n MentionExtension.configure({\n onCreateMention: createTextMention,\n onDeleteMention: deleteTextMention,\n })\n );\n }\n if (options.ai) {\n const resolveContextualPrompt = async ({\n prompt,\n context,\n previous,\n signal,\n }: ResolveContextualPromptArgs): Promise<ResolveContextualPromptResponse> => {\n const result = await room[kInternal].executeContextualPrompt({\n prompt,\n context,\n previous,\n signal,\n });\n\n // This response is validated afterwards by AiExtension itself\n return JSON.parse(result) as ResolveContextualPromptResponse;\n };\n\n extensions.push(\n AiExtension.configure({\n resolveContextualPrompt,\n ...(typeof options.ai === \"boolean\" ? {} : options.ai),\n doc: this.storage.doc,\n pud: this.storage.permanentUserData,\n })\n );\n }\n\n return extensions;\n },\n });\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","sources":["../src/types.ts"],"sourcesContent":["import type {\n ContextualPromptContext,\n ContextualPromptResponse,\n Relax,\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\";\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 initialContent?: Content;\n enablePermanentUserData?: boolean;\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_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\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\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\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 askAi: (prompt?: string) => 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"],"names":["PluginKey","ThreadPluginActions"],"mappings":";;;;AAaa,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;AAEhC,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;AAsE1B,IAAA,mBAAA,qBAAAC,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,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 Relax,\n TextEditorType,\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\";\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 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_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\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\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\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 askAi: (prompt?: string) => 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"],"names":["PluginKey","ThreadPluginActions"],"mappings":";;;;AAca,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;AAEhC,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;AA8E1B,IAAA,mBAAA,qBAAAC,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,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 Relax,\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\";\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 initialContent?: Content;\n enablePermanentUserData?: boolean;\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_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\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\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\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 askAi: (prompt?: string) => 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"],"names":["ThreadPluginActions"],"mappings":";;AAaa,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;AAEhC,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;AAsE1B,IAAA,mBAAA,qBAAAA,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,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 Relax,\n TextEditorType,\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\";\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 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_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\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\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\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 askAi: (prompt?: string) => 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"],"names":["ThreadPluginActions"],"mappings":";;AAca,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;AAEhC,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;AA8E1B,IAAA,mBAAA,qBAAAA,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,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 "2.22.0" === "string" && "2.22.0";
4
+ const PKG_VERSION = typeof "2.22.2" === "string" && "2.22.2";
5
5
  const PKG_FORMAT = typeof "cjs" === "string" && "cjs";
6
6
 
7
7
  exports.PKG_FORMAT = PKG_FORMAT;
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const PKG_NAME = "@liveblocks/react-tiptap";
2
- const PKG_VERSION = typeof "2.22.0" === "string" && "2.22.0";
2
+ const PKG_VERSION = typeof "2.22.2" === "string" && "2.22.2";
3
3
  const PKG_FORMAT = typeof "esm" === "string" && "esm";
4
4
 
5
5
  export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react-tiptap",
3
- "version": "2.22.0",
3
+ "version": "2.22.2",
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
  "type": "module",
@@ -43,11 +43,11 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@floating-ui/react-dom": "^2.1.2",
46
- "@liveblocks/client": "2.22.0",
47
- "@liveblocks/core": "2.22.0",
48
- "@liveblocks/react": "2.22.0",
49
- "@liveblocks/react-ui": "2.22.0",
50
- "@liveblocks/yjs": "2.22.0",
46
+ "@liveblocks/client": "2.22.2",
47
+ "@liveblocks/core": "2.22.2",
48
+ "@liveblocks/react": "2.22.2",
49
+ "@liveblocks/react-ui": "2.22.2",
50
+ "@liveblocks/yjs": "2.22.2",
51
51
  "@radix-ui/react-select": "^2.1.2",
52
52
  "@radix-ui/react-toggle": "^1.1.0",
53
53
  "@tiptap/core": "^2.7.2",