@liveblocks/react-tiptap 2.16.1-ai5 → 2.16.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.
Files changed (47) hide show
  1. package/dist/LiveblocksExtension.js +21 -116
  2. package/dist/LiveblocksExtension.js.map +1 -1
  3. package/dist/LiveblocksExtension.mjs +19 -114
  4. package/dist/LiveblocksExtension.mjs.map +1 -1
  5. package/dist/comments/CommentsExtension.js.map +1 -1
  6. package/dist/comments/CommentsExtension.mjs.map +1 -1
  7. package/dist/comments/FloatingComposer.js +2 -2
  8. package/dist/comments/FloatingComposer.js.map +1 -1
  9. package/dist/comments/FloatingComposer.mjs +2 -2
  10. package/dist/comments/FloatingComposer.mjs.map +1 -1
  11. package/dist/index.d.mts +15 -107
  12. package/dist/index.d.ts +15 -107
  13. package/dist/index.js +0 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +0 -1
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/toolbar/FloatingToolbar.js +0 -7
  18. package/dist/toolbar/FloatingToolbar.js.map +1 -1
  19. package/dist/toolbar/FloatingToolbar.mjs +0 -7
  20. package/dist/toolbar/FloatingToolbar.mjs.map +1 -1
  21. package/dist/toolbar/Toolbar.js +1 -35
  22. package/dist/toolbar/Toolbar.js.map +1 -1
  23. package/dist/toolbar/Toolbar.mjs +2 -36
  24. package/dist/toolbar/Toolbar.mjs.map +1 -1
  25. package/dist/types.js.map +1 -1
  26. package/dist/types.mjs.map +1 -1
  27. package/dist/utils.js +6 -118
  28. package/dist/utils.js.map +1 -1
  29. package/dist/utils.mjs +7 -116
  30. package/dist/utils.mjs.map +1 -1
  31. package/dist/version.js +1 -1
  32. package/dist/version.js.map +1 -1
  33. package/dist/version.mjs +1 -1
  34. package/dist/version.mjs.map +1 -1
  35. package/package.json +6 -7
  36. package/src/styles/index.css +3 -380
  37. package/src/styles/utils.css +0 -6
  38. package/styles.css +1 -1
  39. package/styles.css.map +1 -1
  40. package/dist/ai/AiExtension.js +0 -382
  41. package/dist/ai/AiExtension.js.map +0 -1
  42. package/dist/ai/AiExtension.mjs +0 -378
  43. package/dist/ai/AiExtension.mjs.map +0 -1
  44. package/dist/ai/AiToolbar.js +0 -663
  45. package/dist/ai/AiToolbar.js.map +0 -1
  46. package/dist/ai/AiToolbar.mjs +0 -660
  47. package/dist/ai/AiToolbar.mjs.map +0 -1
@@ -1,22 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var core$1 = require('@liveblocks/core');
3
+ var core = require('@liveblocks/core');
4
4
  var react$1 = require('@liveblocks/react');
5
5
  var _private = require('@liveblocks/react/_private');
6
6
  var yjs$1 = require('@liveblocks/yjs');
7
- var core = require('@tiptap/core');
7
+ var core$1 = require('@tiptap/core');
8
8
  var Collaboration = require('@tiptap/extension-collaboration');
9
9
  var CollaborationCursor = require('@tiptap/extension-collaboration-cursor');
10
10
  var react = require('react');
11
11
  var yjs = require('yjs');
12
- var AiExtension = require('./ai/AiExtension.js');
13
12
  var CommentsExtension = require('./comments/CommentsExtension.js');
14
13
  var MentionExtension = require('./mentions/MentionExtension.js');
15
14
  var types = require('./types.js');
16
15
 
17
16
  const providersMap = /* @__PURE__ */ new Map();
18
17
  const docMap = /* @__PURE__ */ new Map();
19
- const pudMap = /* @__PURE__ */ new Map();
20
18
  const DEFAULT_OPTIONS = {
21
19
  field: "default",
22
20
  comments: true,
@@ -69,53 +67,6 @@ function useIsEditorReady() {
69
67
  );
70
68
  return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
71
69
  }
72
- const YChangeMark = core.Mark.create({
73
- name: "ychange",
74
- inclusive: false,
75
- parseHTML() {
76
- return [{ tag: "ychange" }];
77
- },
78
- addAttributes() {
79
- return {
80
- user: {
81
- default: null,
82
- parseHTML: (element) => element.getAttribute("ychange_user") ?? null,
83
- renderHTML: (attributes) => {
84
- if (!attributes.user) {
85
- return {};
86
- }
87
- return { "data-ychange-user": attributes.user };
88
- }
89
- },
90
- type: {
91
- default: null,
92
- parseHTML: (element) => element.getAttribute("ychange_type") ?? null,
93
- renderHTML: (attributes) => {
94
- if (!attributes.type) {
95
- return {};
96
- }
97
- return {
98
- "data-ychange-type": attributes.type,
99
- "data-liveblocks": "",
100
- class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`
101
- };
102
- }
103
- },
104
- color: {
105
- default: null,
106
- parseHTML: (element) => {
107
- return element.getAttribute("ychange_color") ?? null;
108
- },
109
- renderHTML: () => {
110
- return {};
111
- }
112
- }
113
- };
114
- },
115
- renderHTML({ HTMLAttributes }) {
116
- return ["ychange", HTMLAttributes, 0];
117
- }
118
- });
119
70
  const useLiveblocksExtension = (opts) => {
120
71
  const options = {
121
72
  ...DEFAULT_OPTIONS,
@@ -139,12 +90,12 @@ const useLiveblocksExtension = (opts) => {
139
90
  }
140
91
  }, [isEditorReady, yjsProvider, options.initialContent, editor]);
141
92
  _private.useReportTextEditor(
142
- core$1.TextEditorType.TipTap,
93
+ core.TextEditorType.TipTap,
143
94
  options.field ?? DEFAULT_OPTIONS.field
144
95
  );
145
96
  const createTextMention = _private.useCreateTextMention();
146
97
  const deleteTextMention = _private.useDeleteTextMention();
147
- return core.Extension.create({
98
+ return core$1.Extension.create({
148
99
  name: "liveblocksExtension",
149
100
  onCreate() {
150
101
  setEditor(this.editor);
@@ -161,32 +112,26 @@ const useLiveblocksExtension = (opts) => {
161
112
  );
162
113
  }
163
114
  const self = room.getSelf();
164
- const updateUser = ({
165
- info,
166
- id: userId
167
- }) => {
168
- if (!info) {
169
- return;
170
- }
171
- const { user: storedUser } = this.storage.provider.awareness.getLocalState();
172
- this.storage.permanentUserData?.setUserMapping(
173
- this.storage.doc,
174
- this.storage.doc.clientID,
175
- userId ?? "Unknown"
176
- );
177
- if (info.name !== storedUser?.name || info.color !== storedUser?.color) {
178
- this.editor.commands.updateUser({
179
- name: info.name,
180
- color: info.color
181
- });
182
- }
183
- };
184
115
  if (self?.info) {
185
- updateUser(self);
116
+ this.editor.commands.updateUser({
117
+ name: self.info.name,
118
+ color: self.info.color
119
+ });
186
120
  }
187
- this.storage.unsubs.push(room.events.self.subscribe(updateUser));
121
+ this.storage.unsubs.push(
122
+ room.events.self.subscribe(({ info }) => {
123
+ if (!info) {
124
+ return;
125
+ }
126
+ const { name, color } = info;
127
+ const { user } = this.storage.provider.awareness.getLocalState();
128
+ if (name !== user?.name || color !== user?.color) {
129
+ this.editor.commands.updateUser({ name, color });
130
+ }
131
+ })
132
+ );
188
133
  if (options.comments) {
189
- const commentMarkType = core.getMarkType(
134
+ const commentMarkType = core$1.getMarkType(
190
135
  types.LIVEBLOCKS_COMMENT_MARK_TYPE,
191
136
  this.editor.schema
192
137
  );
@@ -231,21 +176,10 @@ const useLiveblocksExtension = (opts) => {
231
176
  onDestroy() {
232
177
  this.storage.unsubs.forEach((unsub) => unsub());
233
178
  },
234
- addGlobalAttributes() {
235
- return [
236
- {
237
- types: ["paragraph", "heading"],
238
- attributes: {
239
- ychange: { default: null }
240
- }
241
- }
242
- ];
243
- },
244
179
  addStorage() {
245
180
  if (!providersMap.has(room.id)) {
246
181
  const doc = new yjs.Doc();
247
182
  docMap.set(room.id, doc);
248
- pudMap.set(room.id, new yjs.PermanentUserData(doc));
249
183
  providersMap.set(
250
184
  room.id,
251
185
  new yjs$1.LiveblocksYjsProvider(room, doc, {
@@ -256,17 +190,12 @@ const useLiveblocksExtension = (opts) => {
256
190
  return {
257
191
  doc: docMap.get(room.id),
258
192
  provider: providersMap.get(room.id),
259
- permanentUserData: pudMap.get(room.id),
260
193
  unsubs: []
261
194
  };
262
195
  },
263
196
  addExtensions() {
264
197
  const extensions = [
265
- YChangeMark,
266
198
  LiveblocksCollab.configure({
267
- ySyncOptions: {
268
- permanentUserData: this.storage.permanentUserData
269
- },
270
199
  document: this.storage.doc,
271
200
  field: options.field
272
201
  }),
@@ -285,30 +214,6 @@ const useLiveblocksExtension = (opts) => {
285
214
  })
286
215
  );
287
216
  }
288
- if (options.ai) {
289
- const resolveContextualPrompt = async ({
290
- prompt,
291
- context,
292
- previous,
293
- signal
294
- }) => {
295
- const result = await room[core$1.kInternal].executeContextualPrompt({
296
- prompt,
297
- context,
298
- previous,
299
- signal
300
- });
301
- return JSON.parse(result);
302
- };
303
- extensions.push(
304
- AiExtension.AiExtension.configure({
305
- resolveContextualPrompt,
306
- ...typeof options.ai === "boolean" ? {} : options.ai,
307
- doc: this.storage.doc,
308
- pud: this.storage.permanentUserData
309
- })
310
- );
311
- }
312
217
  return extensions;
313
218
  }
314
219
  });
@@ -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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\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\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\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 setEditor(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 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 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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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","useState","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","TextEditorType","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","Doc","PermanentUserData","LiveblocksYjsProvider","CommentsExtension","MentionExtension","kInternal","AiExtension"],"mappings":"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"}
1
+ {"version":3,"file":"LiveblocksExtension.js","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import { type IUserInfo, 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 { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Content, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc } from \"yjs\";\n\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype LiveblocksExtensionOptions = {\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n offlineSupport_experimental?: boolean;\n initialContent?: Content;\n};\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\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<\n never,\n {\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider<any, any, any, any, any>;\n }\n >({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 if (self?.info) {\n this.editor.commands.updateUser({\n name: self.info.name,\n color: self.info.color,\n });\n }\n this.storage.unsubs.push(\n room.events.self.subscribe(({ info }) => {\n if (!info) {\n return;\n }\n const { name, color } = info;\n const { user } = this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n // TODO: maybe we need a deep compare here so other info can be provided\n if (name !== user?.name || color !== user?.color) {\n this.editor.commands.updateUser({ name, color });\n }\n })\n );\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 addStorage() {\n if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n LiveblocksCollab.configure({\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider, //todo change the ! to an assert\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\n return extensions;\n },\n });\n};\n"],"names":["useYjsProvider","useCallback","useSyncExternalStore","useState","useRoom","useClient","getUmbrellaStoreForClient","useEffect","useReportTextEditor","TextEditorType","useCreateTextMention","useDeleteTextMention","Extension","getMarkType","LIVEBLOCKS_COMMENT_MARK_TYPE","Doc","LiveblocksYjsProvider","CommentsExtension","MentionExtension"],"mappings":"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"}
@@ -1,20 +1,18 @@
1
- import { TextEditorType, kInternal } from '@liveblocks/core';
1
+ import { TextEditorType } from '@liveblocks/core';
2
2
  import { useRoom, useClient } from '@liveblocks/react';
3
3
  import { useYjsProvider, getUmbrellaStoreForClient, useReportTextEditor, useCreateTextMention, useDeleteTextMention } from '@liveblocks/react/_private';
4
4
  import { LiveblocksYjsProvider } from '@liveblocks/yjs';
5
- import { Mark, Extension, getMarkType } from '@tiptap/core';
5
+ import { Extension, getMarkType } from '@tiptap/core';
6
6
  import Collaboration from '@tiptap/extension-collaboration';
7
7
  import CollaborationCursor from '@tiptap/extension-collaboration-cursor';
8
8
  import { useCallback, useSyncExternalStore, useState, useEffect } from 'react';
9
- import { Doc, PermanentUserData } from 'yjs';
10
- import { AiExtension } from './ai/AiExtension.mjs';
9
+ import { Doc } from 'yjs';
11
10
  import { CommentsExtension } from './comments/CommentsExtension.mjs';
12
11
  import { MentionExtension } from './mentions/MentionExtension.mjs';
13
12
  import { LIVEBLOCKS_COMMENT_MARK_TYPE } from './types.mjs';
14
13
 
15
14
  const providersMap = /* @__PURE__ */ new Map();
16
15
  const docMap = /* @__PURE__ */ new Map();
17
- const pudMap = /* @__PURE__ */ new Map();
18
16
  const DEFAULT_OPTIONS = {
19
17
  field: "default",
20
18
  comments: true,
@@ -67,53 +65,6 @@ function useIsEditorReady() {
67
65
  );
68
66
  return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
69
67
  }
70
- const YChangeMark = Mark.create({
71
- name: "ychange",
72
- inclusive: false,
73
- parseHTML() {
74
- return [{ tag: "ychange" }];
75
- },
76
- addAttributes() {
77
- return {
78
- user: {
79
- default: null,
80
- parseHTML: (element) => element.getAttribute("ychange_user") ?? null,
81
- renderHTML: (attributes) => {
82
- if (!attributes.user) {
83
- return {};
84
- }
85
- return { "data-ychange-user": attributes.user };
86
- }
87
- },
88
- type: {
89
- default: null,
90
- parseHTML: (element) => element.getAttribute("ychange_type") ?? null,
91
- renderHTML: (attributes) => {
92
- if (!attributes.type) {
93
- return {};
94
- }
95
- return {
96
- "data-ychange-type": attributes.type,
97
- "data-liveblocks": "",
98
- class: `lb-root lb-tiptap-change lb-tiptap-change-${attributes.type}`
99
- };
100
- }
101
- },
102
- color: {
103
- default: null,
104
- parseHTML: (element) => {
105
- return element.getAttribute("ychange_color") ?? null;
106
- },
107
- renderHTML: () => {
108
- return {};
109
- }
110
- }
111
- };
112
- },
113
- renderHTML({ HTMLAttributes }) {
114
- return ["ychange", HTMLAttributes, 0];
115
- }
116
- });
117
68
  const useLiveblocksExtension = (opts) => {
118
69
  const options = {
119
70
  ...DEFAULT_OPTIONS,
@@ -159,30 +110,24 @@ const useLiveblocksExtension = (opts) => {
159
110
  );
160
111
  }
161
112
  const self = room.getSelf();
162
- const updateUser = ({
163
- info,
164
- id: userId
165
- }) => {
166
- if (!info) {
167
- return;
168
- }
169
- const { user: storedUser } = this.storage.provider.awareness.getLocalState();
170
- this.storage.permanentUserData?.setUserMapping(
171
- this.storage.doc,
172
- this.storage.doc.clientID,
173
- userId ?? "Unknown"
174
- );
175
- if (info.name !== storedUser?.name || info.color !== storedUser?.color) {
176
- this.editor.commands.updateUser({
177
- name: info.name,
178
- color: info.color
179
- });
180
- }
181
- };
182
113
  if (self?.info) {
183
- updateUser(self);
114
+ this.editor.commands.updateUser({
115
+ name: self.info.name,
116
+ color: self.info.color
117
+ });
184
118
  }
185
- this.storage.unsubs.push(room.events.self.subscribe(updateUser));
119
+ this.storage.unsubs.push(
120
+ room.events.self.subscribe(({ info }) => {
121
+ if (!info) {
122
+ return;
123
+ }
124
+ const { name, color } = info;
125
+ const { user } = this.storage.provider.awareness.getLocalState();
126
+ if (name !== user?.name || color !== user?.color) {
127
+ this.editor.commands.updateUser({ name, color });
128
+ }
129
+ })
130
+ );
186
131
  if (options.comments) {
187
132
  const commentMarkType = getMarkType(
188
133
  LIVEBLOCKS_COMMENT_MARK_TYPE,
@@ -229,21 +174,10 @@ const useLiveblocksExtension = (opts) => {
229
174
  onDestroy() {
230
175
  this.storage.unsubs.forEach((unsub) => unsub());
231
176
  },
232
- addGlobalAttributes() {
233
- return [
234
- {
235
- types: ["paragraph", "heading"],
236
- attributes: {
237
- ychange: { default: null }
238
- }
239
- }
240
- ];
241
- },
242
177
  addStorage() {
243
178
  if (!providersMap.has(room.id)) {
244
179
  const doc = new Doc();
245
180
  docMap.set(room.id, doc);
246
- pudMap.set(room.id, new PermanentUserData(doc));
247
181
  providersMap.set(
248
182
  room.id,
249
183
  new LiveblocksYjsProvider(room, doc, {
@@ -254,17 +188,12 @@ const useLiveblocksExtension = (opts) => {
254
188
  return {
255
189
  doc: docMap.get(room.id),
256
190
  provider: providersMap.get(room.id),
257
- permanentUserData: pudMap.get(room.id),
258
191
  unsubs: []
259
192
  };
260
193
  },
261
194
  addExtensions() {
262
195
  const extensions = [
263
- YChangeMark,
264
196
  LiveblocksCollab.configure({
265
- ySyncOptions: {
266
- permanentUserData: this.storage.permanentUserData
267
- },
268
197
  document: this.storage.doc,
269
198
  field: options.field
270
199
  }),
@@ -283,30 +212,6 @@ const useLiveblocksExtension = (opts) => {
283
212
  })
284
213
  );
285
214
  }
286
- if (options.ai) {
287
- const resolveContextualPrompt = async ({
288
- prompt,
289
- context,
290
- previous,
291
- signal
292
- }) => {
293
- const result = await room[kInternal].executeContextualPrompt({
294
- prompt,
295
- context,
296
- previous,
297
- signal
298
- });
299
- return JSON.parse(result);
300
- };
301
- extensions.push(
302
- AiExtension.configure({
303
- resolveContextualPrompt,
304
- ...typeof options.ai === "boolean" ? {} : options.ai,
305
- doc: this.storage.doc,
306
- pud: this.storage.permanentUserData
307
- })
308
- );
309
- }
310
215
  return extensions;
311
216
  }
312
217
  });
@@ -1 +1 @@
1
- {"version":3,"file":"LiveblocksExtension.mjs","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 { LiveblocksYjsProvider } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc, PermanentUserData } from \"yjs\";\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\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\nconst pudMap = new Map<string, PermanentUserData>();\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\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 setEditor(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 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 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 if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n pudMap.set(room.id, new PermanentUserData(doc));\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n permanentUserData: pudMap.get(room.id)!,\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":";;;;;;;;;;;;;;AAmCA,MAAM,YAAA,uBAAmB,GAGvB,EAAA,CAAA;AAEF,MAAM,MAAA,uBAAa,GAAiB,EAAA,CAAA;AAIpC,MAAM,MAAA,uBAAa,GAA+B,EAAA,CAAA;AAElD,MAAM,eAAqE,GAAA;AAAA,EACzE,KAAO,EAAA,SAAA;AAAA,EACP,QAAU,EAAA,IAAA;AAAA,EACV,QAAU,EAAA,IAAA;AAAA,EACV,2BAA6B,EAAA,KAAA;AAC/B,CAAA,CAAA;AAEA,MAAM,gBAAA,GAAmB,cAAc,MAAO,CAAA;AAAA,EAE5C,QAAW,GAAA;AACT,IACE,IAAA,CAAC,IAAK,CAAA,MAAA,CAAO,gBAAiB,CAAA,UAAA,CAAW,IAAK,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,KAAK,CACrE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,wIAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAA,IACE,CAAC,IAAA,CAAK,MAAO,CAAA,gBAAA,CAAiB,UAAW,CAAA,IAAA;AAAA,MACvC,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,WAAA;AAAA,KAEpB,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,yIAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IACE,IAAA,CAAC,IAAK,CAAA,MAAA,CAAO,gBAAiB,CAAA,UAAA,CAAW,IAAK,CAAA,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,MAAM,CACtE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,oIAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IACE,IAAA,IAAA,CAAK,MAAO,CAAA,gBAAA,CAAiB,UAAW,CAAA,IAAA,CAAK,CAAC,CAAM,KAAA,CAAA,CAAE,IAAS,KAAA,SAAS,CACxE,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,kKAAA;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACF;AACF,CAAC,CAAA,CAAA;AAOM,SAAS,gBAA4B,GAAA;AAC1C,EAAA,MAAM,cAAc,cAAe,EAAA,CAAA;AAEnC,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAM,MAAA,MAAA,GAAS,aAAa,SAAU,EAAA,CAAA;AACtC,IAAO,OAAA,MAAA,KAAW,mBAAmB,MAAW,KAAA,cAAA,CAAA;AAAA,GAClD,EAAG,CAAC,WAAW,CAAC,CAAA,CAAA;AAEhB,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IAChB,CAAC,QAAyB,KAAA;AACxB,MAAA,IAAI,WAAgB,KAAA,KAAA,CAAA;AAAW,QAAA,OAAO,MAAM;AAAA,SAAC,CAAA;AAC7C,MAAY,WAAA,CAAA,EAAA,CAAG,UAAU,QAAQ,CAAA,CAAA;AACjC,MAAA,OAAO,MAAM;AACX,QAAY,WAAA,CAAA,GAAA,CAAI,UAAU,QAAQ,CAAA,CAAA;AAAA,OACpC,CAAA;AAAA,KACF;AAAA,IACA,CAAC,WAAW,CAAA;AAAA,GACd,CAAA;AAEA,EAAO,OAAA,oBAAA,CAAqB,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACjE,CAAA;AAEA,MAAM,WAAA,GAAc,KAAK,MAAO,CAAA;AAAA,EAC9B,IAAM,EAAA,SAAA;AAAA,EACN,SAAW,EAAA,KAAA;AAAA,EACX,SAAY,GAAA;AACV,IAAA,OAAO,CAAC,EAAE,GAAK,EAAA,SAAA,EAAW,CAAA,CAAA;AAAA,GAC5B;AAAA,EACA,aAAgB,GAAA;AACd,IAAO,OAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA,IAAA;AAAA,QACT,WAAW,CAAC,OAAA,KAAY,OAAQ,CAAA,YAAA,CAAa,cAAc,CAAK,IAAA,IAAA;AAAA,QAChE,UAAA,EAAY,CAAC,UAAwC,KAAA;AACnD,UAAI,IAAA,CAAC,WAAW,IAAM,EAAA;AACpB,YAAA,OAAO,EAAC,CAAA;AAAA,WACV;AACA,UAAO,OAAA,EAAE,mBAAqB,EAAA,UAAA,CAAW,IAAK,EAAA,CAAA;AAAA,SAChD;AAAA,OACF;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA,IAAA;AAAA,QACT,WAAW,CAAC,OAAA,KAAY,OAAQ,CAAA,YAAA,CAAa,cAAc,CAAK,IAAA,IAAA;AAAA,QAChE,UAAA,EAAY,CAAC,UAAwC,KAAA;AACnD,UAAI,IAAA,CAAC,WAAW,IAAM,EAAA;AACpB,YAAA,OAAO,EAAC,CAAA;AAAA,WACV;AACA,UAAO,OAAA;AAAA,YACL,qBAAqB,UAAW,CAAA,IAAA;AAAA,YAChC,iBAAmB,EAAA,EAAA;AAAA,YACnB,KAAA,EAAO,6CAA6C,UAAW,CAAA,IAAA,CAAA,CAAA;AAAA,WACjE,CAAA;AAAA,SACF;AAAA,OACF;AAAA,MACA,KAAO,EAAA;AAAA,QACL,OAAS,EAAA,IAAA;AAAA,QACT,SAAA,EAAW,CAAC,OAAY,KAAA;AACtB,UAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,eAAe,CAAK,IAAA,IAAA,CAAA;AAAA,SAClD;AAAA,QACA,YAAY,MAAM;AAEhB,UAAA,OAAO,EAAC,CAAA;AAAA,SACV;AAAA,OACF;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EACA,UAAA,CAAW,EAAE,cAAA,EAAkB,EAAA;AAC7B,IAAO,OAAA,CAAC,SAAW,EAAA,cAAA,EAAgB,CAAC,CAAA,CAAA;AAAA,GACtC;AACF,CAAC,CAAA,CAAA;AAEY,MAAA,sBAAA,GAAyB,CACpC,IACc,KAAA;AACd,EAAA,MAAM,OAAU,GAAA;AAAA,IACd,GAAG,eAAA;AAAA,IACH,GAAG,IAAA;AAAA,GACL,CAAA;AACA,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAwB,IAAI,CAAA,CAAA;AACxD,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AAcrB,EAAA,MAAM,gBAAgB,gBAAiB,EAAA,CAAA;AACvC,EAAA,MAAM,SAAS,SAAU,EAAA,CAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,0BAA0B,MAAM,CAAA,CAAA;AAC9C,EAAA,MAAM,SAAS,IAAK,CAAA,EAAA,CAAA;AACpB,EAAA,MAAM,cAAc,cAAe,EAAA,CAAA;AAGnC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,aAAiB,IAAA,CAAC,eAAe,CAAC,OAAA,CAAQ,kBAAkB,CAAC,MAAA;AAChE,MAAA,OAAA;AAIF,IAAM,MAAA,IAAA,GAAQ,YAAsC,OAAQ,EAAA,CAAA;AAC5D,IAAA,MAAM,gBAAgB,IAAK,CAAA,MAAA,CAAO,mBAAmB,CAAA,CAAE,IAAI,eAAe,CAAA,CAAA;AAC1E,IAAA,IAAI,CAAC,aAAe,EAAA;AAClB,MAAA,IAAA,CAAK,MAAO,CAAA,mBAAmB,CAAE,CAAA,GAAA,CAAI,iBAAiB,IAAI,CAAA,CAAA;AAC1D,MAAO,MAAA,CAAA,QAAA,CAAS,UAAW,CAAA,OAAA,CAAQ,cAAc,CAAA,CAAA;AAAA,KACnD;AAAA,KACC,CAAC,aAAA,EAAe,aAAa,OAAQ,CAAA,cAAA,EAAgB,MAAM,CAAC,CAAA,CAAA;AAE/D,EAAA,mBAAA;AAAA,IACE,cAAe,CAAA,MAAA;AAAA,IACf,OAAA,CAAQ,SAAS,eAAgB,CAAA,KAAA;AAAA,GACnC,CAAA;AAEA,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAC/C,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAE/C,EAAA,OAAO,UAAU,MAA0C,CAAA;AAAA,IACzD,IAAM,EAAA,qBAAA;AAAA,IAEN,QAAW,GAAA;AACT,MAAA,SAAA,CAAU,KAAK,MAAM,CAAA,CAAA;AACrB,MAAI,IAAA,IAAA,CAAK,MAAO,CAAA,OAAA,CAAQ,OAAS,EAAA;AAC/B,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,8HAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAA,IACE,OAAQ,CAAA,QAAA,IACR,IAAK,CAAA,MAAA,CAAO,iBAAiB,UAAW,CAAA,IAAA;AAAA,QACtC,CAAC,CAAA,KAAM,CAAE,CAAA,IAAA,CAAK,aAAkB,KAAA,SAAA;AAAA,OAElC,EAAA;AACA,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,2GAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAM,MAAA,IAAA,GAAO,KAAK,OAAQ,EAAA,CAAA;AAC1B,MAAA,MAAM,aAAa,CAAC;AAAA,QAClB,IAAA;AAAA,QACA,EAAI,EAAA,MAAA;AAAA,OACgC,KAAA;AACpC,QAAA,IAAI,CAAC,IAAM,EAAA;AACT,UAAA,OAAA;AAAA,SACF;AACA,QAAM,MAAA,EAAE,MAAM,UAAW,EAAA,GACvB,KAAK,OAAQ,CAAA,QAAA,CAAS,UAAU,aAAc,EAAA,CAAA;AAGhD,QAAA,IAAA,CAAK,QAAQ,iBAAmB,EAAA,cAAA;AAAA,UAC9B,KAAK,OAAQ,CAAA,GAAA;AAAA,UACb,IAAA,CAAK,QAAQ,GAAI,CAAA,QAAA;AAAA,UACjB,MAAU,IAAA,SAAA;AAAA,SACZ,CAAA;AACA,QAAA,IACE,KAAK,IAAS,KAAA,UAAA,EAAY,QAC1B,IAAK,CAAA,KAAA,KAAU,YAAY,KAC3B,EAAA;AACA,UAAK,IAAA,CAAA,MAAA,CAAO,SAAS,UAAW,CAAA;AAAA,YAC9B,MAAM,IAAK,CAAA,IAAA;AAAA,YACX,OAAO,IAAK,CAAA,KAAA;AAAA,WACb,CAAA,CAAA;AAAA,SACH;AAAA,OACF,CAAA;AAEA,MAAA,IAAI,MAAM,IAAM,EAAA;AACd,QAAA,UAAA,CAAW,IAAI,CAAA,CAAA;AAAA,OACjB;AAEA,MAAK,IAAA,CAAA,OAAA,CAAQ,OAAO,IAAK,CAAA,IAAA,CAAK,OAAO,IAAK,CAAA,SAAA,CAAU,UAAU,CAAC,CAAA,CAAA;AAC/D,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAA,MAAM,eAAkB,GAAA,WAAA;AAAA,UACtB,4BAAA;AAAA,UACA,KAAK,MAAO,CAAA,MAAA;AAAA,SACd,CAAA;AACA,QAAA,IAAA,CAAK,QAAQ,MAAO,CAAA,IAAA;AAAA,UAElB,KAAM,CAAA,OAAA,CAAQ,OAAQ,CAAA,SAAA,CAAU,MAAM;AACpC,YAAA,MAAM,YAAY,IAAI,GAAA;AAAA,cACpB,KAAA,CAAM,QAAQ,OACX,CAAA,GAAA,GACA,QAAS,CAAA,MAAA,EAAQ,EAAE,QAAU,EAAA,KAAA,IAAS,KAAK,CAAA,CAC3C,IAAI,CAAC,MAAA,KAAW,CAAC,MAAO,CAAA,EAAA,EAAI,IAAI,CAAC,CAAA;AAAA,aACtC,CAAA;AACA,YAAA,SAAS,UAAU,IAEjB,EAAA;AACA,cAAO,OAAA,IAAA,CAAK,KAAK,IAAS,KAAA,4BAAA,CAAA;AAAA,aAC5B;AAEA,YAAA,IAAA,CAAK,OAAO,KAAM,CAAA,GAAA,CAAI,WAAY,CAAA,CAAC,MAAM,GAAQ,KAAA;AAC/C,cAAK,IAAA,CAAA,KAAA,CAAM,OAAQ,CAAA,CAAC,IAAS,KAAA;AAC3B,gBAAI,IAAA,SAAA,CAAU,IAAI,CAAG,EAAA;AACnB,kBAAM,MAAA,YAAA,GAAe,KAAK,KAAM,CAAA,QAAA,CAAA;AAChC,kBAAA,MAAM,QAAW,GAAA,CAAC,SAAU,CAAA,GAAA,CAAI,YAAY,CAAA,CAAA;AAC5C,kBAAI,IAAA,QAAA,KAAa,IAAK,CAAA,KAAA,CAAM,MAAQ,EAAA;AAClC,oBAAA,MAAM,EAAE,EAAA,EAAO,GAAA,IAAA,CAAK,MAAO,CAAA,KAAA,CAAA;AAC3B,oBAAA,MAAM,WAAc,GAAA,IAAA,CAAK,GAAI,CAAA,GAAA,EAAK,CAAC,CAAA,CAAA;AACnC,oBAAA,MAAM,YAAY,IAAK,CAAA,GAAA;AAAA,sBACrB,MAAM,IAAK,CAAA,QAAA;AAAA,sBACX,IAAK,CAAA,MAAA,CAAO,KAAM,CAAA,GAAA,CAAI,QAAQ,IAAO,GAAA,CAAA;AAAA,qBACvC,CAAA;AACA,oBAAG,EAAA,CAAA,UAAA,CAAW,WAAa,EAAA,SAAA,EAAW,eAAe,CAAA,CAAA;AACrD,oBAAG,EAAA,CAAA,OAAA;AAAA,sBACD,WAAA;AAAA,sBACA,SAAA;AAAA,sBACA,gBAAgB,MAAO,CAAA;AAAA,wBACrB,GAAG,IAAK,CAAA,KAAA;AAAA,wBACR,MAAQ,EAAA,QAAA;AAAA,uBACT,CAAA;AAAA,qBACH,CAAA;AACA,oBAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,QAAA,CAAS,EAAE,CAAA,CAAA;AAAA,mBAC9B;AAAA,iBACF;AAAA,eACD,CAAA,CAAA;AAAA,aACF,CAAA,CAAA;AAAA,WACF,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,KACF;AAAA,IACA,SAAY,GAAA;AACV,MAAA,IAAA,CAAK,QAAQ,MAAO,CAAA,OAAA,CAAQ,CAAC,KAAA,KAAU,OAAO,CAAA,CAAA;AAAA,KAChD;AAAA,IACA,mBAAsB,GAAA;AACpB,MAAO,OAAA;AAAA,QACL;AAAA,UACE,KAAA,EAAO,CAAC,WAAA,EAAa,SAAS,CAAA;AAAA,UAC9B,UAAY,EAAA;AAAA,YACV,OAAA,EAAS,EAAE,OAAA,EAAS,IAAK,EAAA;AAAA,WAC3B;AAAA,SACF;AAAA,OACF,CAAA;AAAA,KACF;AAAA,IACA,UAAa,GAAA;AACX,MAAA,IAAI,CAAC,YAAA,CAAa,GAAI,CAAA,IAAA,CAAK,EAAE,CAAG,EAAA;AAC9B,QAAM,MAAA,GAAA,GAAM,IAAI,GAAI,EAAA,CAAA;AACpB,QAAO,MAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,GAAG,CAAA,CAAA;AACvB,QAAA,MAAA,CAAO,IAAI,IAAK,CAAA,EAAA,EAAI,IAAI,iBAAA,CAAkB,GAAG,CAAC,CAAA,CAAA;AAC9C,QAAa,YAAA,CAAA,GAAA;AAAA,UACX,IAAK,CAAA,EAAA;AAAA,UACL,IAAI,qBAAsB,CAAA,IAAA,EAAM,GAAK,EAAA;AAAA,YACnC,6BAA6B,OAAQ,CAAA,2BAAA;AAAA,WACtC,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AACA,MAAO,OAAA;AAAA,QACL,GAAK,EAAA,MAAA,CAAO,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QACvB,QAAU,EAAA,YAAA,CAAa,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QAClC,iBAAmB,EAAA,MAAA,CAAO,GAAI,CAAA,IAAA,CAAK,EAAE,CAAA;AAAA,QACrC,QAAQ,EAAC;AAAA,OACX,CAAA;AAAA,KACF;AAAA,IACA,aAAgB,GAAA;AACd,MAAA,MAAM,UAA6B,GAAA;AAAA,QACjC,WAAA;AAAA,QACA,iBAAiB,SAAU,CAAA;AAAA,UACzB,YAAc,EAAA;AAAA,YACZ,iBAAA,EAAmB,KAAK,OAAQ,CAAA,iBAAA;AAAA,WAClC;AAAA,UACA,QAAA,EAAU,KAAK,OAAQ,CAAA,GAAA;AAAA,UACvB,OAAO,OAAQ,CAAA,KAAA;AAAA,SAChB,CAAA;AAAA,QACD,oBAAoB,SAAU,CAAA;AAAA,UAC5B,QAAA,EAAU,KAAK,OAAQ,CAAA,QAAA;AAAA,SACxB,CAAA;AAAA,OACH,CAAA;AAEA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAA,UAAA,CAAW,KAAK,iBAAiB,CAAA,CAAA;AAAA,OACnC;AACA,MAAA,IAAI,QAAQ,QAAU,EAAA;AACpB,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,iBAAiB,SAAU,CAAA;AAAA,YACzB,eAAiB,EAAA,iBAAA;AAAA,YACjB,eAAiB,EAAA,iBAAA;AAAA,WAClB,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AACA,MAAA,IAAI,QAAQ,EAAI,EAAA;AACd,QAAA,MAAM,0BAA0B,OAAO;AAAA,UACrC,MAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,MAAA;AAAA,SAC2E,KAAA;AAC3E,UAAA,MAAM,MAAS,GAAA,MAAM,IAAK,CAAA,SAAA,CAAA,CAAW,uBAAwB,CAAA;AAAA,YAC3D,MAAA;AAAA,YACA,OAAA;AAAA,YACA,QAAA;AAAA,YACA,MAAA;AAAA,WACD,CAAA,CAAA;AAGD,UAAO,OAAA,IAAA,CAAK,MAAM,MAAM,CAAA,CAAA;AAAA,SAC1B,CAAA;AAEA,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,YAAY,SAAU,CAAA;AAAA,YACpB,uBAAA;AAAA,YACA,GAAI,OAAO,OAAA,CAAQ,OAAO,SAAY,GAAA,KAAK,OAAQ,CAAA,EAAA;AAAA,YACnD,GAAA,EAAK,KAAK,OAAQ,CAAA,GAAA;AAAA,YAClB,GAAA,EAAK,KAAK,OAAQ,CAAA,iBAAA;AAAA,WACnB,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAEA,MAAO,OAAA,UAAA,CAAA;AAAA,KACT;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"LiveblocksExtension.mjs","sources":["../src/LiveblocksExtension.ts"],"sourcesContent":["import { type IUserInfo, 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 { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { AnyExtension, Content, Editor } from \"@tiptap/core\";\nimport { Extension, getMarkType } 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, useState, useSyncExternalStore } from \"react\";\nimport { Doc } from \"yjs\";\n\nimport { CommentsExtension } from \"./comments/CommentsExtension\";\nimport { MentionExtension } from \"./mentions/MentionExtension\";\nimport { LIVEBLOCKS_COMMENT_MARK_TYPE } from \"./types\";\n\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<any, any, any, any, any>\n>();\n\nconst docMap = new Map<string, Doc>();\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype LiveblocksExtensionOptions = {\n field?: string;\n comments?: boolean; // | CommentsConfiguration\n mentions?: boolean; // | MentionsConfiguration\n offlineSupport_experimental?: boolean;\n initialContent?: Content;\n};\n\nconst DEFAULT_OPTIONS: WithRequired<LiveblocksExtensionOptions, \"field\"> = {\n field: \"default\",\n comments: true,\n mentions: true,\n offlineSupport_experimental: 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\nexport const useLiveblocksExtension = (\n opts?: LiveblocksExtensionOptions\n): Extension => {\n const options = {\n ...DEFAULT_OPTIONS,\n ...opts,\n };\n const [editor, setEditor] = useState<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 (!isEditorReady || !yjsProvider || !options.initialContent || !editor)\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.commands.setContent(options.initialContent);\n }\n }, [isEditorReady, yjsProvider, options.initialContent, editor]);\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<\n never,\n {\n unsubs: (() => void)[];\n doc: Doc;\n provider: LiveblocksYjsProvider<any, any, any, any, any>;\n }\n >({\n name: \"liveblocksExtension\",\n\n onCreate() {\n setEditor(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 if (self?.info) {\n this.editor.commands.updateUser({\n name: self.info.name,\n color: self.info.color,\n });\n }\n this.storage.unsubs.push(\n room.events.self.subscribe(({ info }) => {\n if (!info) {\n return;\n }\n const { name, color } = info;\n const { user } = this.storage.provider.awareness.getLocalState() as {\n user: IUserInfo;\n };\n // TODO: maybe we need a deep compare here so other info can be provided\n if (name !== user?.name || color !== user?.color) {\n this.editor.commands.updateUser({ name, color });\n }\n })\n );\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 addStorage() {\n if (!providersMap.has(room.id)) {\n const doc = new Doc();\n docMap.set(room.id, doc);\n providersMap.set(\n room.id,\n new LiveblocksYjsProvider(room, doc, {\n offlineSupport_experimental: options.offlineSupport_experimental,\n })\n );\n }\n return {\n doc: docMap.get(room.id)!,\n provider: providersMap.get(room.id)!,\n unsubs: [],\n };\n },\n addExtensions() {\n const extensions: AnyExtension[] = [\n LiveblocksCollab.configure({\n document: this.storage.doc,\n field: options.field,\n }),\n CollaborationCursor.configure({\n provider: this.storage.provider, //todo change the ! to an assert\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\n return extensions;\n },\n });\n};\n"],"names":[],"mappings":"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"}