@liveblocks/react-tiptap 3.21.0-exp1 → 3.21.0-exp3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collaboration-liveblocks/cursors.cjs +10 -211
- package/dist/collaboration-liveblocks/cursors.cjs.map +1 -1
- package/dist/collaboration-liveblocks/cursors.js +6 -209
- package/dist/collaboration-liveblocks/cursors.js.map +1 -1
- package/dist/collaboration-liveblocks/plugin.cjs +13 -189
- package/dist/collaboration-liveblocks/plugin.cjs.map +1 -1
- package/dist/collaboration-liveblocks/plugin.js +12 -190
- package/dist/collaboration-liveblocks/plugin.js.map +1 -1
- package/dist/collaboration-liveblocks/schema.cjs +23 -139
- package/dist/collaboration-liveblocks/schema.cjs.map +1 -1
- package/dist/collaboration-liveblocks/schema.js +5 -128
- package/dist/collaboration-liveblocks/schema.js.map +1 -1
- package/dist/comments/CommentsExtension.cjs +3 -2
- package/dist/comments/CommentsExtension.cjs.map +1 -1
- package/dist/comments/CommentsExtension.js +2 -1
- package/dist/comments/CommentsExtension.js.map +1 -1
- package/dist/mentions/MentionExtension.cjs +3 -2
- package/dist/mentions/MentionExtension.cjs.map +1 -1
- package/dist/mentions/MentionExtension.js +2 -1
- package/dist/mentions/MentionExtension.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -6
- package/dist/collaboration-liveblocks/mapping.cjs +0 -218
- package/dist/collaboration-liveblocks/mapping.cjs.map +0 -1
- package/dist/collaboration-liveblocks/mapping.js +0 -207
- package/dist/collaboration-liveblocks/mapping.js.map +0 -1
- package/dist/collaboration-liveblocks/remote.cjs +0 -210
- package/dist/collaboration-liveblocks/remote.cjs.map +0 -1
- package/dist/collaboration-liveblocks/remote.js +0 -207
- package/dist/collaboration-liveblocks/remote.js.map +0 -1
- package/dist/collaboration-liveblocks/steps.cjs +0 -359
- package/dist/collaboration-liveblocks/steps.cjs.map +0 -1
- package/dist/collaboration-liveblocks/steps.js +0 -356
- package/dist/collaboration-liveblocks/steps.js.map +0 -1
|
@@ -1,214 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var prosemirror = require('@liveblocks/prosemirror');
|
|
3
4
|
var core = require('@tiptap/core');
|
|
4
|
-
var state = require('@tiptap/pm/state');
|
|
5
|
-
var view = require('@tiptap/pm/view');
|
|
6
|
-
var plugin = require('./plugin.cjs');
|
|
7
5
|
|
|
8
|
-
const PRESENCE_KEY = "liveblocksTiptap";
|
|
9
|
-
const LIVEBLOCKS_CARET_PLUGIN_KEY = new state.PluginKey("liveblocks-collaboration-caret");
|
|
10
|
-
function isCursorPresence(value) {
|
|
11
|
-
return typeof value === "object" && value !== null && typeof value.field === "string" && typeof value.anchor === "number" && typeof value.head === "number";
|
|
12
|
-
}
|
|
13
|
-
function getCursorUser(value) {
|
|
14
|
-
if (typeof value !== "object" || value === null) {
|
|
15
|
-
return void 0;
|
|
16
|
-
}
|
|
17
|
-
const user = value;
|
|
18
|
-
const name = typeof user.name === "string" ? user.name : void 0;
|
|
19
|
-
const color = typeof user.color === "string" ? user.color : void 0;
|
|
20
|
-
return name !== void 0 || color !== void 0 ? { name, color } : void 0;
|
|
21
|
-
}
|
|
22
|
-
function presencePatch(presence) {
|
|
23
|
-
const user = getCursorUser(presence.user);
|
|
24
|
-
return {
|
|
25
|
-
[PRESENCE_KEY]: {
|
|
26
|
-
field: presence.field,
|
|
27
|
-
anchor: presence.anchor,
|
|
28
|
-
head: presence.head,
|
|
29
|
-
...user !== void 0 ? { user } : {}
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function createCursorElement(user) {
|
|
34
|
-
const color = user?.color ?? "#0f83ff";
|
|
35
|
-
const name = user?.name ?? "Anonymous";
|
|
36
|
-
const cursor = document.createElement("span");
|
|
37
|
-
cursor.classList.add("collaboration-carets__caret");
|
|
38
|
-
cursor.setAttribute("style", `border-color: ${color}`);
|
|
39
|
-
const label = document.createElement("div");
|
|
40
|
-
label.classList.add("collaboration-carets__label");
|
|
41
|
-
label.setAttribute("style", `background-color: ${color}`);
|
|
42
|
-
label.insertBefore(document.createTextNode(name), null);
|
|
43
|
-
cursor.insertBefore(label, null);
|
|
44
|
-
return cursor;
|
|
45
|
-
}
|
|
46
|
-
function clampPosition(position, doc) {
|
|
47
|
-
return Math.max(0, Math.min(position, doc.content.size));
|
|
48
|
-
}
|
|
49
|
-
function normalizeCaretPosition(position, doc) {
|
|
50
|
-
const clampedPosition = clampPosition(position, doc);
|
|
51
|
-
const $position = doc.resolve(clampedPosition);
|
|
52
|
-
if ($position.parent.isTextblock) {
|
|
53
|
-
return clampedPosition;
|
|
54
|
-
}
|
|
55
|
-
return state.Selection.near($position, -1).anchor;
|
|
56
|
-
}
|
|
57
|
-
function getRemoteCursors(room, field, previousCursors = []) {
|
|
58
|
-
const cursors = [];
|
|
59
|
-
for (const other of room.getOthers()) {
|
|
60
|
-
const rawPresence = other.presence[PRESENCE_KEY];
|
|
61
|
-
if (!isCursorPresence(rawPresence) || rawPresence.field !== field) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
const user = getCursorUser(rawPresence.user) ?? getCursorUser(other.info);
|
|
65
|
-
const previousCursor = previousCursors.find(
|
|
66
|
-
(cursor) => cursor.connectionId === other.connectionId
|
|
67
|
-
);
|
|
68
|
-
const hasPresencePositionChanged = previousCursor === void 0 || previousCursor.rawAnchor !== rawPresence.anchor || previousCursor.rawHead !== rawPresence.head;
|
|
69
|
-
cursors.push({
|
|
70
|
-
anchor: hasPresencePositionChanged ? rawPresence.anchor : previousCursor.anchor,
|
|
71
|
-
connectionId: other.connectionId,
|
|
72
|
-
head: hasPresencePositionChanged ? rawPresence.head : previousCursor.head,
|
|
73
|
-
rawAnchor: rawPresence.anchor,
|
|
74
|
-
rawHead: rawPresence.head,
|
|
75
|
-
user
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return cursors;
|
|
79
|
-
}
|
|
80
|
-
function buildDecorationsFromCursors(cursors, doc) {
|
|
81
|
-
const decorations = [];
|
|
82
|
-
for (const cursor of cursors) {
|
|
83
|
-
const anchor = clampPosition(cursor.anchor, doc);
|
|
84
|
-
const head = clampPosition(cursor.head, doc);
|
|
85
|
-
const from = Math.min(anchor, head);
|
|
86
|
-
const to = Math.max(anchor, head);
|
|
87
|
-
const user = cursor.user;
|
|
88
|
-
const color = user?.color ?? "#0f83ff";
|
|
89
|
-
if (from !== to) {
|
|
90
|
-
decorations.push(
|
|
91
|
-
view.Decoration.inline(from, to, {
|
|
92
|
-
class: "collaboration-carets__selection",
|
|
93
|
-
style: `background-color: ${color}33`
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
decorations.push(
|
|
98
|
-
view.Decoration.widget(
|
|
99
|
-
normalizeCaretPosition(head, doc),
|
|
100
|
-
() => createCursorElement(user),
|
|
101
|
-
{
|
|
102
|
-
key: `liveblocks-caret-${cursor.connectionId}`,
|
|
103
|
-
side: -1
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
return view.DecorationSet.create(doc, decorations);
|
|
109
|
-
}
|
|
110
|
-
function createLiveblocksCaretPlugin(options, storage) {
|
|
111
|
-
const room = options.room;
|
|
112
|
-
if (room === void 0) {
|
|
113
|
-
throw new Error("[Liveblocks] The Liveblocks caret plugin requires a room.");
|
|
114
|
-
}
|
|
115
|
-
let view$1;
|
|
116
|
-
let unsubscribe;
|
|
117
|
-
const updatePresence = (nextView) => {
|
|
118
|
-
const { anchor, head } = nextView.state.selection;
|
|
119
|
-
room.updatePresence(
|
|
120
|
-
presencePatch({
|
|
121
|
-
field: options.field,
|
|
122
|
-
anchor,
|
|
123
|
-
head,
|
|
124
|
-
user: options.user
|
|
125
|
-
})
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
const updateDecorations = () => {
|
|
129
|
-
if (view$1 === void 0) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
storage.users = room.getOthers().map((other) => {
|
|
133
|
-
const rawPresence = other.presence[PRESENCE_KEY];
|
|
134
|
-
const cursorPresence = isCursorPresence(rawPresence) ? rawPresence : void 0;
|
|
135
|
-
return {
|
|
136
|
-
clientId: other.connectionId,
|
|
137
|
-
...getCursorUser(cursorPresence?.user) ?? getCursorUser(other.info)
|
|
138
|
-
};
|
|
139
|
-
});
|
|
140
|
-
const previousCursors = LIVEBLOCKS_CARET_PLUGIN_KEY.getState(view$1.state)?.cursors ?? [];
|
|
141
|
-
const cursors = getRemoteCursors(room, options.field, previousCursors);
|
|
142
|
-
view$1.dispatch(
|
|
143
|
-
view$1.state.tr.setMeta(LIVEBLOCKS_CARET_PLUGIN_KEY, {
|
|
144
|
-
cursors
|
|
145
|
-
})
|
|
146
|
-
);
|
|
147
|
-
};
|
|
148
|
-
return new state.Plugin({
|
|
149
|
-
key: LIVEBLOCKS_CARET_PLUGIN_KEY,
|
|
150
|
-
state: {
|
|
151
|
-
init(_, state) {
|
|
152
|
-
return {
|
|
153
|
-
cursors: [],
|
|
154
|
-
decorations: view.DecorationSet.create(state.doc, [])
|
|
155
|
-
};
|
|
156
|
-
},
|
|
157
|
-
apply(tr, state) {
|
|
158
|
-
const meta = tr.getMeta(LIVEBLOCKS_CARET_PLUGIN_KEY);
|
|
159
|
-
if (meta !== void 0) {
|
|
160
|
-
return {
|
|
161
|
-
cursors: meta.cursors,
|
|
162
|
-
decorations: buildDecorationsFromCursors(meta.cursors, tr.doc)
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
if (!tr.docChanged) {
|
|
166
|
-
return state;
|
|
167
|
-
}
|
|
168
|
-
if (!tr.getMeta(plugin.LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)) {
|
|
169
|
-
const cursors = state.cursors.map((cursor) => ({
|
|
170
|
-
...cursor,
|
|
171
|
-
anchor: tr.mapping.map(cursor.anchor, -1),
|
|
172
|
-
head: tr.mapping.map(cursor.head, -1)
|
|
173
|
-
}));
|
|
174
|
-
return {
|
|
175
|
-
cursors,
|
|
176
|
-
decorations: buildDecorationsFromCursors(cursors, tr.doc)
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
return {
|
|
180
|
-
cursors: state.cursors,
|
|
181
|
-
decorations: buildDecorationsFromCursors(state.cursors, tr.doc)
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
props: {
|
|
186
|
-
decorations(state) {
|
|
187
|
-
return LIVEBLOCKS_CARET_PLUGIN_KEY.getState(state)?.decorations ?? view.DecorationSet.empty;
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
view(editorView) {
|
|
191
|
-
view$1 = editorView;
|
|
192
|
-
updatePresence(editorView);
|
|
193
|
-
updateDecorations();
|
|
194
|
-
unsubscribe = room.events.others.subscribe(updateDecorations);
|
|
195
|
-
return {
|
|
196
|
-
update(nextView, prevState) {
|
|
197
|
-
view$1 = nextView;
|
|
198
|
-
if (!nextView.state.selection.eq(prevState.selection)) {
|
|
199
|
-
updatePresence(nextView);
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
destroy() {
|
|
203
|
-
unsubscribe?.();
|
|
204
|
-
unsubscribe = void 0;
|
|
205
|
-
view$1 = void 0;
|
|
206
|
-
room.updatePresence({ [PRESENCE_KEY]: null });
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
6
|
const LiveblocksCollaborationCaret = core.Extension.create({
|
|
213
7
|
name: "collaborationCaret",
|
|
214
8
|
priority: 999,
|
|
@@ -230,7 +24,7 @@ const LiveblocksCollaborationCaret = core.Extension.create({
|
|
|
230
24
|
addCommands() {
|
|
231
25
|
return {
|
|
232
26
|
updateUser: (attributes) => ({ editor }) => {
|
|
233
|
-
const nextUser = getCursorUser({
|
|
27
|
+
const nextUser = prosemirror.getCursorUser({
|
|
234
28
|
...this.options.user,
|
|
235
29
|
name: typeof attributes.name === "string" ? attributes.name : this.options.user.name,
|
|
236
30
|
color: typeof attributes.color === "string" ? attributes.color : this.options.user.color
|
|
@@ -242,7 +36,7 @@ const LiveblocksCollaborationCaret = core.Extension.create({
|
|
|
242
36
|
if (this.options.room !== void 0) {
|
|
243
37
|
const { anchor, head } = editor.state.selection;
|
|
244
38
|
this.options.room.updatePresence(
|
|
245
|
-
presencePatch({
|
|
39
|
+
prosemirror.presencePatch({
|
|
246
40
|
field: this.options.field,
|
|
247
41
|
anchor,
|
|
248
42
|
head,
|
|
@@ -258,10 +52,15 @@ const LiveblocksCollaborationCaret = core.Extension.create({
|
|
|
258
52
|
};
|
|
259
53
|
},
|
|
260
54
|
addProseMirrorPlugins() {
|
|
261
|
-
return [
|
|
55
|
+
return [
|
|
56
|
+
prosemirror.createLiveblocksCollaborationCaretPlugin(this.options, this.storage)
|
|
57
|
+
];
|
|
262
58
|
}
|
|
263
59
|
});
|
|
264
60
|
|
|
265
|
-
exports
|
|
61
|
+
Object.defineProperty(exports, 'LIVEBLOCKS_CARET_PLUGIN_KEY', {
|
|
62
|
+
enumerable: true,
|
|
63
|
+
get: function () { return prosemirror.LIVEBLOCKS_CARET_PLUGIN_KEY; }
|
|
64
|
+
});
|
|
266
65
|
exports.LiveblocksCollaborationCaret = LiveblocksCollaborationCaret;
|
|
267
66
|
//# sourceMappingURL=cursors.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursors.cjs","sources":["../../src/collaboration-liveblocks/cursors.ts"],"sourcesContent":["import type { JsonObject } from \"@liveblocks/client\";\nimport { Extension } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Plugin, PluginKey, Selection } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"./plugin\";\nimport type { LiveblocksTiptapRoom } from \"./types\";\n\nconst PRESENCE_KEY = \"liveblocksTiptap\";\n\ntype CursorUser = {\n name?: string;\n color?: string;\n};\n\ntype CursorPresence = {\n field: string;\n anchor: number;\n head: number;\n user?: CursorUser;\n};\n\ntype CollaborationCaretStorage = {\n users: { clientId: number; [key: string]: unknown }[];\n};\n\ntype RemoteCursor = {\n anchor: number;\n connectionId: number;\n head: number;\n rawAnchor: number;\n rawHead: number;\n user?: CursorUser;\n};\n\ntype CollaborationCaretPluginState = {\n cursors: RemoteCursor[];\n decorations: DecorationSet;\n};\n\ntype CollaborationCaretOptions = {\n room?: LiveblocksTiptapRoom;\n field: string;\n user: CursorUser;\n};\n\nexport const LIVEBLOCKS_CARET_PLUGIN_KEY =\n new PluginKey<CollaborationCaretPluginState>(\"liveblocks-collaboration-caret\");\n\nfunction isCursorPresence(value: unknown): value is CursorPresence {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { field?: unknown }).field === \"string\" &&\n typeof (value as { anchor?: unknown }).anchor === \"number\" &&\n typeof (value as { head?: unknown }).head === \"number\"\n );\n}\n\nfunction getCursorUser(value: unknown): CursorUser | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n\n const user = value as { name?: unknown; color?: unknown };\n const name = typeof user.name === \"string\" ? user.name : undefined;\n const color = typeof user.color === \"string\" ? user.color : undefined;\n\n return name !== undefined || color !== undefined ? { name, color } : undefined;\n}\n\nfunction presencePatch(presence: CursorPresence): JsonObject {\n const user = getCursorUser(presence.user);\n\n return {\n [PRESENCE_KEY]: {\n field: presence.field,\n anchor: presence.anchor,\n head: presence.head,\n ...(user !== undefined ? { user } : {}),\n },\n };\n}\n\nfunction createCursorElement(user: CursorUser | undefined): HTMLElement {\n const color = user?.color ?? \"#0f83ff\";\n const name = user?.name ?? \"Anonymous\";\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(\"collaboration-carets__caret\");\n cursor.setAttribute(\"style\", `border-color: ${color}`);\n\n const label = document.createElement(\"div\");\n label.classList.add(\"collaboration-carets__label\");\n label.setAttribute(\"style\", `background-color: ${color}`);\n label.insertBefore(document.createTextNode(name), null);\n cursor.insertBefore(label, null);\n\n return cursor;\n}\n\nfunction clampPosition(position: number, doc: ProseMirrorNode): number {\n return Math.max(0, Math.min(position, doc.content.size));\n}\n\nfunction normalizeCaretPosition(position: number, doc: ProseMirrorNode): number {\n const clampedPosition = clampPosition(position, doc);\n const $position = doc.resolve(clampedPosition);\n\n if ($position.parent.isTextblock) {\n return clampedPosition;\n }\n\n return Selection.near($position, -1).anchor;\n}\n\nfunction getRemoteCursors(\n room: LiveblocksTiptapRoom,\n field: string,\n previousCursors: readonly RemoteCursor[] = []\n): RemoteCursor[] {\n const cursors: RemoteCursor[] = [];\n\n for (const other of room.getOthers()) {\n const rawPresence: unknown = other.presence[PRESENCE_KEY];\n if (!isCursorPresence(rawPresence) || rawPresence.field !== field) {\n continue;\n }\n\n const user = getCursorUser(rawPresence.user) ?? getCursorUser(other.info);\n const previousCursor = previousCursors.find(\n (cursor) => cursor.connectionId === other.connectionId\n );\n const hasPresencePositionChanged =\n previousCursor === undefined ||\n previousCursor.rawAnchor !== rawPresence.anchor ||\n previousCursor.rawHead !== rawPresence.head;\n\n cursors.push({\n anchor: hasPresencePositionChanged\n ? rawPresence.anchor\n : previousCursor.anchor,\n connectionId: other.connectionId,\n head: hasPresencePositionChanged ? rawPresence.head : previousCursor.head,\n rawAnchor: rawPresence.anchor,\n rawHead: rawPresence.head,\n user,\n });\n }\n\n return cursors;\n}\n\nfunction buildDecorationsFromCursors(\n cursors: readonly RemoteCursor[],\n doc: ProseMirrorNode\n): DecorationSet {\n const decorations: Decoration[] = [];\n\n for (const cursor of cursors) {\n const anchor = clampPosition(cursor.anchor, doc);\n const head = clampPosition(cursor.head, doc);\n const from = Math.min(anchor, head);\n const to = Math.max(anchor, head);\n const user = cursor.user;\n const color = user?.color ?? \"#0f83ff\";\n\n if (from !== to) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"collaboration-carets__selection\",\n style: `background-color: ${color}33`,\n })\n );\n }\n\n decorations.push(\n Decoration.widget(\n normalizeCaretPosition(head, doc),\n () => createCursorElement(user),\n {\n key: `liveblocks-caret-${cursor.connectionId}`,\n side: -1,\n }\n )\n );\n }\n\n return DecorationSet.create(doc, decorations);\n}\n\nfunction createLiveblocksCaretPlugin(\n options: CollaborationCaretOptions,\n storage: CollaborationCaretStorage\n): Plugin {\n const room = options.room;\n if (room === undefined) {\n throw new Error(\"[Liveblocks] The Liveblocks caret plugin requires a room.\");\n }\n\n let view: EditorView | undefined;\n let unsubscribe: (() => void) | undefined;\n\n const updatePresence = (nextView: EditorView) => {\n const { anchor, head } = nextView.state.selection;\n room.updatePresence(\n presencePatch({\n field: options.field,\n anchor,\n head,\n user: options.user,\n })\n );\n };\n\n const updateDecorations = () => {\n if (view === undefined) {\n return;\n }\n\n storage.users = room.getOthers().map((other) => {\n const rawPresence: unknown = other.presence[PRESENCE_KEY];\n const cursorPresence = isCursorPresence(rawPresence)\n ? rawPresence\n : undefined;\n\n return {\n clientId: other.connectionId,\n ...(getCursorUser(cursorPresence?.user) ?? getCursorUser(other.info)),\n };\n });\n\n const previousCursors =\n LIVEBLOCKS_CARET_PLUGIN_KEY.getState(view.state)?.cursors ?? [];\n const cursors = getRemoteCursors(room, options.field, previousCursors);\n\n view.dispatch(\n view.state.tr.setMeta(LIVEBLOCKS_CARET_PLUGIN_KEY, {\n cursors,\n })\n );\n };\n\n return new Plugin({\n key: LIVEBLOCKS_CARET_PLUGIN_KEY,\n state: {\n init(_, state): CollaborationCaretPluginState {\n return {\n cursors: [],\n decorations: DecorationSet.create(state.doc, []),\n };\n },\n apply(tr, state): CollaborationCaretPluginState {\n const meta = tr.getMeta(LIVEBLOCKS_CARET_PLUGIN_KEY) as\n | { cursors: RemoteCursor[] }\n | undefined;\n\n if (meta !== undefined) {\n return {\n cursors: meta.cursors,\n decorations: buildDecorationsFromCursors(meta.cursors, tr.doc),\n };\n }\n\n if (!tr.docChanged) {\n return state;\n }\n\n if (!tr.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)) {\n const cursors = state.cursors.map((cursor) => ({\n ...cursor,\n anchor: tr.mapping.map(cursor.anchor, -1),\n head: tr.mapping.map(cursor.head, -1),\n }));\n\n return {\n cursors,\n decorations: buildDecorationsFromCursors(cursors, tr.doc),\n };\n }\n\n // Remote presence can arrive before the matching remote document\n // update. Keep the stored cursor positions and rebuild them against\n // the new document so pre-arrived presence is no longer clamped to the\n // old document size.\n return {\n cursors: state.cursors,\n decorations: buildDecorationsFromCursors(state.cursors, tr.doc),\n };\n },\n },\n props: {\n decorations(state) {\n return (\n LIVEBLOCKS_CARET_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n },\n view(editorView) {\n view = editorView;\n updatePresence(editorView);\n updateDecorations();\n unsubscribe = room.events.others.subscribe(updateDecorations);\n\n return {\n update(nextView, prevState) {\n view = nextView;\n\n if (!nextView.state.selection.eq(prevState.selection)) {\n updatePresence(nextView);\n }\n\n },\n destroy() {\n unsubscribe?.();\n unsubscribe = undefined;\n view = undefined;\n room.updatePresence({ [PRESENCE_KEY]: null });\n },\n };\n },\n });\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n collaborationCaret: {\n updateUser: (attributes: Record<string, any>) => ReturnType;\n user: (attributes: Record<string, any>) => ReturnType;\n };\n }\n}\n\nexport const LiveblocksCollaborationCaret = Extension.create<\n CollaborationCaretOptions,\n CollaborationCaretStorage\n>({\n name: \"collaborationCaret\",\n priority: 999,\n\n addOptions() {\n return {\n room: undefined,\n field: \"default\",\n user: {\n name: undefined,\n color: undefined,\n },\n };\n },\n\n addStorage() {\n return {\n users: [],\n };\n },\n\n addCommands() {\n return {\n updateUser:\n (attributes) =>\n ({ editor }) => {\n const nextUser = getCursorUser({\n ...this.options.user,\n name:\n typeof attributes.name === \"string\"\n ? attributes.name\n : this.options.user.name,\n color:\n typeof attributes.color === \"string\"\n ? attributes.color\n : this.options.user.color,\n }) ?? {};\n\n if (\n nextUser.name === this.options.user.name &&\n nextUser.color === this.options.user.color\n ) {\n return true;\n }\n\n this.options.user = nextUser;\n\n if (this.options.room !== undefined) {\n const { anchor, head } = editor.state.selection;\n this.options.room.updatePresence(\n presencePatch({\n field: this.options.field,\n anchor,\n head,\n user: this.options.user,\n })\n );\n }\n return true;\n },\n user:\n (attributes) =>\n ({ editor }) => {\n return editor.commands.updateUser(attributes);\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [createLiveblocksCaretPlugin(this.options, this.storage)];\n },\n});\n"],"names":["PluginKey","Selection","Decoration","DecorationSet","view","Plugin","LIVEBLOCKS_COLLABORATION_PLUGIN_KEY","Extension"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cursors.cjs","sources":["../../src/collaboration-liveblocks/cursors.ts"],"sourcesContent":["import {\n type CollaborationCaretOptions,\n type CollaborationCaretStorage,\n createLiveblocksCollaborationCaretPlugin,\n getCursorUser,\n LIVEBLOCKS_CARET_PLUGIN_KEY,\n presencePatch,\n} from \"@liveblocks/prosemirror\";\nimport { Extension } from \"@tiptap/core\";\n\nexport { LIVEBLOCKS_CARET_PLUGIN_KEY };\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n collaborationCaret: {\n updateUser: (attributes: Record<string, any>) => ReturnType;\n user: (attributes: Record<string, any>) => ReturnType;\n };\n }\n}\n\nexport const LiveblocksCollaborationCaret = Extension.create<\n CollaborationCaretOptions,\n CollaborationCaretStorage\n>({\n name: \"collaborationCaret\",\n priority: 999,\n\n addOptions() {\n return {\n room: undefined,\n field: \"default\",\n user: {\n name: undefined,\n color: undefined,\n },\n };\n },\n\n addStorage() {\n return {\n users: [],\n };\n },\n\n addCommands() {\n return {\n updateUser:\n (attributes) =>\n ({ editor }) => {\n const nextUser =\n getCursorUser({\n ...this.options.user,\n name:\n typeof attributes.name === \"string\"\n ? attributes.name\n : this.options.user.name,\n color:\n typeof attributes.color === \"string\"\n ? attributes.color\n : this.options.user.color,\n }) ?? {};\n\n if (\n nextUser.name === this.options.user.name &&\n nextUser.color === this.options.user.color\n ) {\n return true;\n }\n\n this.options.user = nextUser;\n\n if (this.options.room !== undefined) {\n const { anchor, head } = editor.state.selection;\n this.options.room.updatePresence(\n presencePatch({\n field: this.options.field,\n anchor,\n head,\n user: this.options.user,\n })\n );\n }\n return true;\n },\n user:\n (attributes) =>\n ({ editor }) => {\n return editor.commands.updateUser(attributes);\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [\n createLiveblocksCollaborationCaretPlugin(this.options, this.storage),\n ];\n },\n});\n"],"names":["Extension","getCursorUser","presencePatch","createLiveblocksCollaborationCaretPlugin"],"mappings":";;;;;AAqBa,MAAA,4BAAA,GAA+BA,eAAU,MAGpD,CAAA;AAAA,EACA,IAAM,EAAA,oBAAA;AAAA,EACN,QAAU,EAAA,GAAA;AAAA,EAEV,UAAa,GAAA;AACX,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,KAAA,CAAA;AAAA,MACN,KAAO,EAAA,SAAA;AAAA,MACP,IAAM,EAAA;AAAA,QACJ,IAAM,EAAA,KAAA,CAAA;AAAA,QACN,KAAO,EAAA,KAAA,CAAA;AAAA,OACT;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,UAAa,GAAA;AACX,IAAO,OAAA;AAAA,MACL,OAAO,EAAC;AAAA,KACV,CAAA;AAAA,GACF;AAAA,EAEA,WAAc,GAAA;AACZ,IAAO,OAAA;AAAA,MACL,YACE,CAAC,UAAA,KACD,CAAC,EAAE,QAAa,KAAA;AACd,QAAA,MAAM,WACJC,yBAAc,CAAA;AAAA,UACZ,GAAG,KAAK,OAAQ,CAAA,IAAA;AAAA,UAChB,IAAA,EACE,OAAO,UAAW,CAAA,IAAA,KAAS,WACvB,UAAW,CAAA,IAAA,GACX,IAAK,CAAA,OAAA,CAAQ,IAAK,CAAA,IAAA;AAAA,UACxB,KAAA,EACE,OAAO,UAAW,CAAA,KAAA,KAAU,WACxB,UAAW,CAAA,KAAA,GACX,IAAK,CAAA,OAAA,CAAQ,IAAK,CAAA,KAAA;AAAA,SACzB,KAAK,EAAC,CAAA;AAET,QACE,IAAA,QAAA,CAAS,IAAS,KAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,IACpC,IAAA,QAAA,CAAS,KAAU,KAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,KACrC,EAAA;AACA,UAAO,OAAA,IAAA,CAAA;AAAA,SACT;AAEA,QAAA,IAAA,CAAK,QAAQ,IAAO,GAAA,QAAA,CAAA;AAEpB,QAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,KAAS,KAAW,CAAA,EAAA;AACnC,UAAA,MAAM,EAAE,MAAA,EAAQ,IAAK,EAAA,GAAI,OAAO,KAAM,CAAA,SAAA,CAAA;AACtC,UAAA,IAAA,CAAK,QAAQ,IAAK,CAAA,cAAA;AAAA,YAChBC,yBAAc,CAAA;AAAA,cACZ,KAAA,EAAO,KAAK,OAAQ,CAAA,KAAA;AAAA,cACpB,MAAA;AAAA,cACA,IAAA;AAAA,cACA,IAAA,EAAM,KAAK,OAAQ,CAAA,IAAA;AAAA,aACpB,CAAA;AAAA,WACH,CAAA;AAAA,SACF;AACA,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,MACF,MACE,CAAC,UAAA,KACD,CAAC,EAAE,QAAa,KAAA;AACd,QAAO,OAAA,MAAA,CAAO,QAAS,CAAA,UAAA,CAAW,UAAU,CAAA,CAAA;AAAA,OAC9C;AAAA,KACJ,CAAA;AAAA,GACF;AAAA,EAEA,qBAAwB,GAAA;AACtB,IAAO,OAAA;AAAA,MACLC,oDAAyC,CAAA,IAAA,CAAK,OAAS,EAAA,IAAA,CAAK,OAAO,CAAA;AAAA,KACrE,CAAA;AAAA,GACF;AACF,CAAC;;;;;;;;"}
|
|
@@ -1,212 +1,7 @@
|
|
|
1
|
+
import { getCursorUser, presencePatch, createLiveblocksCollaborationCaretPlugin } from '@liveblocks/prosemirror';
|
|
2
|
+
export { LIVEBLOCKS_CARET_PLUGIN_KEY } from '@liveblocks/prosemirror';
|
|
1
3
|
import { Extension } from '@tiptap/core';
|
|
2
|
-
import { PluginKey, Selection, Plugin } from '@tiptap/pm/state';
|
|
3
|
-
import { Decoration, DecorationSet } from '@tiptap/pm/view';
|
|
4
|
-
import { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from './plugin.js';
|
|
5
4
|
|
|
6
|
-
const PRESENCE_KEY = "liveblocksTiptap";
|
|
7
|
-
const LIVEBLOCKS_CARET_PLUGIN_KEY = new PluginKey("liveblocks-collaboration-caret");
|
|
8
|
-
function isCursorPresence(value) {
|
|
9
|
-
return typeof value === "object" && value !== null && typeof value.field === "string" && typeof value.anchor === "number" && typeof value.head === "number";
|
|
10
|
-
}
|
|
11
|
-
function getCursorUser(value) {
|
|
12
|
-
if (typeof value !== "object" || value === null) {
|
|
13
|
-
return void 0;
|
|
14
|
-
}
|
|
15
|
-
const user = value;
|
|
16
|
-
const name = typeof user.name === "string" ? user.name : void 0;
|
|
17
|
-
const color = typeof user.color === "string" ? user.color : void 0;
|
|
18
|
-
return name !== void 0 || color !== void 0 ? { name, color } : void 0;
|
|
19
|
-
}
|
|
20
|
-
function presencePatch(presence) {
|
|
21
|
-
const user = getCursorUser(presence.user);
|
|
22
|
-
return {
|
|
23
|
-
[PRESENCE_KEY]: {
|
|
24
|
-
field: presence.field,
|
|
25
|
-
anchor: presence.anchor,
|
|
26
|
-
head: presence.head,
|
|
27
|
-
...user !== void 0 ? { user } : {}
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function createCursorElement(user) {
|
|
32
|
-
const color = user?.color ?? "#0f83ff";
|
|
33
|
-
const name = user?.name ?? "Anonymous";
|
|
34
|
-
const cursor = document.createElement("span");
|
|
35
|
-
cursor.classList.add("collaboration-carets__caret");
|
|
36
|
-
cursor.setAttribute("style", `border-color: ${color}`);
|
|
37
|
-
const label = document.createElement("div");
|
|
38
|
-
label.classList.add("collaboration-carets__label");
|
|
39
|
-
label.setAttribute("style", `background-color: ${color}`);
|
|
40
|
-
label.insertBefore(document.createTextNode(name), null);
|
|
41
|
-
cursor.insertBefore(label, null);
|
|
42
|
-
return cursor;
|
|
43
|
-
}
|
|
44
|
-
function clampPosition(position, doc) {
|
|
45
|
-
return Math.max(0, Math.min(position, doc.content.size));
|
|
46
|
-
}
|
|
47
|
-
function normalizeCaretPosition(position, doc) {
|
|
48
|
-
const clampedPosition = clampPosition(position, doc);
|
|
49
|
-
const $position = doc.resolve(clampedPosition);
|
|
50
|
-
if ($position.parent.isTextblock) {
|
|
51
|
-
return clampedPosition;
|
|
52
|
-
}
|
|
53
|
-
return Selection.near($position, -1).anchor;
|
|
54
|
-
}
|
|
55
|
-
function getRemoteCursors(room, field, previousCursors = []) {
|
|
56
|
-
const cursors = [];
|
|
57
|
-
for (const other of room.getOthers()) {
|
|
58
|
-
const rawPresence = other.presence[PRESENCE_KEY];
|
|
59
|
-
if (!isCursorPresence(rawPresence) || rawPresence.field !== field) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const user = getCursorUser(rawPresence.user) ?? getCursorUser(other.info);
|
|
63
|
-
const previousCursor = previousCursors.find(
|
|
64
|
-
(cursor) => cursor.connectionId === other.connectionId
|
|
65
|
-
);
|
|
66
|
-
const hasPresencePositionChanged = previousCursor === void 0 || previousCursor.rawAnchor !== rawPresence.anchor || previousCursor.rawHead !== rawPresence.head;
|
|
67
|
-
cursors.push({
|
|
68
|
-
anchor: hasPresencePositionChanged ? rawPresence.anchor : previousCursor.anchor,
|
|
69
|
-
connectionId: other.connectionId,
|
|
70
|
-
head: hasPresencePositionChanged ? rawPresence.head : previousCursor.head,
|
|
71
|
-
rawAnchor: rawPresence.anchor,
|
|
72
|
-
rawHead: rawPresence.head,
|
|
73
|
-
user
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
return cursors;
|
|
77
|
-
}
|
|
78
|
-
function buildDecorationsFromCursors(cursors, doc) {
|
|
79
|
-
const decorations = [];
|
|
80
|
-
for (const cursor of cursors) {
|
|
81
|
-
const anchor = clampPosition(cursor.anchor, doc);
|
|
82
|
-
const head = clampPosition(cursor.head, doc);
|
|
83
|
-
const from = Math.min(anchor, head);
|
|
84
|
-
const to = Math.max(anchor, head);
|
|
85
|
-
const user = cursor.user;
|
|
86
|
-
const color = user?.color ?? "#0f83ff";
|
|
87
|
-
if (from !== to) {
|
|
88
|
-
decorations.push(
|
|
89
|
-
Decoration.inline(from, to, {
|
|
90
|
-
class: "collaboration-carets__selection",
|
|
91
|
-
style: `background-color: ${color}33`
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
decorations.push(
|
|
96
|
-
Decoration.widget(
|
|
97
|
-
normalizeCaretPosition(head, doc),
|
|
98
|
-
() => createCursorElement(user),
|
|
99
|
-
{
|
|
100
|
-
key: `liveblocks-caret-${cursor.connectionId}`,
|
|
101
|
-
side: -1
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
return DecorationSet.create(doc, decorations);
|
|
107
|
-
}
|
|
108
|
-
function createLiveblocksCaretPlugin(options, storage) {
|
|
109
|
-
const room = options.room;
|
|
110
|
-
if (room === void 0) {
|
|
111
|
-
throw new Error("[Liveblocks] The Liveblocks caret plugin requires a room.");
|
|
112
|
-
}
|
|
113
|
-
let view;
|
|
114
|
-
let unsubscribe;
|
|
115
|
-
const updatePresence = (nextView) => {
|
|
116
|
-
const { anchor, head } = nextView.state.selection;
|
|
117
|
-
room.updatePresence(
|
|
118
|
-
presencePatch({
|
|
119
|
-
field: options.field,
|
|
120
|
-
anchor,
|
|
121
|
-
head,
|
|
122
|
-
user: options.user
|
|
123
|
-
})
|
|
124
|
-
);
|
|
125
|
-
};
|
|
126
|
-
const updateDecorations = () => {
|
|
127
|
-
if (view === void 0) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
storage.users = room.getOthers().map((other) => {
|
|
131
|
-
const rawPresence = other.presence[PRESENCE_KEY];
|
|
132
|
-
const cursorPresence = isCursorPresence(rawPresence) ? rawPresence : void 0;
|
|
133
|
-
return {
|
|
134
|
-
clientId: other.connectionId,
|
|
135
|
-
...getCursorUser(cursorPresence?.user) ?? getCursorUser(other.info)
|
|
136
|
-
};
|
|
137
|
-
});
|
|
138
|
-
const previousCursors = LIVEBLOCKS_CARET_PLUGIN_KEY.getState(view.state)?.cursors ?? [];
|
|
139
|
-
const cursors = getRemoteCursors(room, options.field, previousCursors);
|
|
140
|
-
view.dispatch(
|
|
141
|
-
view.state.tr.setMeta(LIVEBLOCKS_CARET_PLUGIN_KEY, {
|
|
142
|
-
cursors
|
|
143
|
-
})
|
|
144
|
-
);
|
|
145
|
-
};
|
|
146
|
-
return new Plugin({
|
|
147
|
-
key: LIVEBLOCKS_CARET_PLUGIN_KEY,
|
|
148
|
-
state: {
|
|
149
|
-
init(_, state) {
|
|
150
|
-
return {
|
|
151
|
-
cursors: [],
|
|
152
|
-
decorations: DecorationSet.create(state.doc, [])
|
|
153
|
-
};
|
|
154
|
-
},
|
|
155
|
-
apply(tr, state) {
|
|
156
|
-
const meta = tr.getMeta(LIVEBLOCKS_CARET_PLUGIN_KEY);
|
|
157
|
-
if (meta !== void 0) {
|
|
158
|
-
return {
|
|
159
|
-
cursors: meta.cursors,
|
|
160
|
-
decorations: buildDecorationsFromCursors(meta.cursors, tr.doc)
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
if (!tr.docChanged) {
|
|
164
|
-
return state;
|
|
165
|
-
}
|
|
166
|
-
if (!tr.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)) {
|
|
167
|
-
const cursors = state.cursors.map((cursor) => ({
|
|
168
|
-
...cursor,
|
|
169
|
-
anchor: tr.mapping.map(cursor.anchor, -1),
|
|
170
|
-
head: tr.mapping.map(cursor.head, -1)
|
|
171
|
-
}));
|
|
172
|
-
return {
|
|
173
|
-
cursors,
|
|
174
|
-
decorations: buildDecorationsFromCursors(cursors, tr.doc)
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
cursors: state.cursors,
|
|
179
|
-
decorations: buildDecorationsFromCursors(state.cursors, tr.doc)
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
props: {
|
|
184
|
-
decorations(state) {
|
|
185
|
-
return LIVEBLOCKS_CARET_PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty;
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
view(editorView) {
|
|
189
|
-
view = editorView;
|
|
190
|
-
updatePresence(editorView);
|
|
191
|
-
updateDecorations();
|
|
192
|
-
unsubscribe = room.events.others.subscribe(updateDecorations);
|
|
193
|
-
return {
|
|
194
|
-
update(nextView, prevState) {
|
|
195
|
-
view = nextView;
|
|
196
|
-
if (!nextView.state.selection.eq(prevState.selection)) {
|
|
197
|
-
updatePresence(nextView);
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
destroy() {
|
|
201
|
-
unsubscribe?.();
|
|
202
|
-
unsubscribe = void 0;
|
|
203
|
-
view = void 0;
|
|
204
|
-
room.updatePresence({ [PRESENCE_KEY]: null });
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
5
|
const LiveblocksCollaborationCaret = Extension.create({
|
|
211
6
|
name: "collaborationCaret",
|
|
212
7
|
priority: 999,
|
|
@@ -256,9 +51,11 @@ const LiveblocksCollaborationCaret = Extension.create({
|
|
|
256
51
|
};
|
|
257
52
|
},
|
|
258
53
|
addProseMirrorPlugins() {
|
|
259
|
-
return [
|
|
54
|
+
return [
|
|
55
|
+
createLiveblocksCollaborationCaretPlugin(this.options, this.storage)
|
|
56
|
+
];
|
|
260
57
|
}
|
|
261
58
|
});
|
|
262
59
|
|
|
263
|
-
export {
|
|
60
|
+
export { LiveblocksCollaborationCaret };
|
|
264
61
|
//# sourceMappingURL=cursors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursors.js","sources":["../../src/collaboration-liveblocks/cursors.ts"],"sourcesContent":["import type { JsonObject } from \"@liveblocks/client\";\nimport { Extension } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Plugin, PluginKey, Selection } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\n\nimport { LIVEBLOCKS_COLLABORATION_PLUGIN_KEY } from \"./plugin\";\nimport type { LiveblocksTiptapRoom } from \"./types\";\n\nconst PRESENCE_KEY = \"liveblocksTiptap\";\n\ntype CursorUser = {\n name?: string;\n color?: string;\n};\n\ntype CursorPresence = {\n field: string;\n anchor: number;\n head: number;\n user?: CursorUser;\n};\n\ntype CollaborationCaretStorage = {\n users: { clientId: number; [key: string]: unknown }[];\n};\n\ntype RemoteCursor = {\n anchor: number;\n connectionId: number;\n head: number;\n rawAnchor: number;\n rawHead: number;\n user?: CursorUser;\n};\n\ntype CollaborationCaretPluginState = {\n cursors: RemoteCursor[];\n decorations: DecorationSet;\n};\n\ntype CollaborationCaretOptions = {\n room?: LiveblocksTiptapRoom;\n field: string;\n user: CursorUser;\n};\n\nexport const LIVEBLOCKS_CARET_PLUGIN_KEY =\n new PluginKey<CollaborationCaretPluginState>(\"liveblocks-collaboration-caret\");\n\nfunction isCursorPresence(value: unknown): value is CursorPresence {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { field?: unknown }).field === \"string\" &&\n typeof (value as { anchor?: unknown }).anchor === \"number\" &&\n typeof (value as { head?: unknown }).head === \"number\"\n );\n}\n\nfunction getCursorUser(value: unknown): CursorUser | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n\n const user = value as { name?: unknown; color?: unknown };\n const name = typeof user.name === \"string\" ? user.name : undefined;\n const color = typeof user.color === \"string\" ? user.color : undefined;\n\n return name !== undefined || color !== undefined ? { name, color } : undefined;\n}\n\nfunction presencePatch(presence: CursorPresence): JsonObject {\n const user = getCursorUser(presence.user);\n\n return {\n [PRESENCE_KEY]: {\n field: presence.field,\n anchor: presence.anchor,\n head: presence.head,\n ...(user !== undefined ? { user } : {}),\n },\n };\n}\n\nfunction createCursorElement(user: CursorUser | undefined): HTMLElement {\n const color = user?.color ?? \"#0f83ff\";\n const name = user?.name ?? \"Anonymous\";\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(\"collaboration-carets__caret\");\n cursor.setAttribute(\"style\", `border-color: ${color}`);\n\n const label = document.createElement(\"div\");\n label.classList.add(\"collaboration-carets__label\");\n label.setAttribute(\"style\", `background-color: ${color}`);\n label.insertBefore(document.createTextNode(name), null);\n cursor.insertBefore(label, null);\n\n return cursor;\n}\n\nfunction clampPosition(position: number, doc: ProseMirrorNode): number {\n return Math.max(0, Math.min(position, doc.content.size));\n}\n\nfunction normalizeCaretPosition(position: number, doc: ProseMirrorNode): number {\n const clampedPosition = clampPosition(position, doc);\n const $position = doc.resolve(clampedPosition);\n\n if ($position.parent.isTextblock) {\n return clampedPosition;\n }\n\n return Selection.near($position, -1).anchor;\n}\n\nfunction getRemoteCursors(\n room: LiveblocksTiptapRoom,\n field: string,\n previousCursors: readonly RemoteCursor[] = []\n): RemoteCursor[] {\n const cursors: RemoteCursor[] = [];\n\n for (const other of room.getOthers()) {\n const rawPresence: unknown = other.presence[PRESENCE_KEY];\n if (!isCursorPresence(rawPresence) || rawPresence.field !== field) {\n continue;\n }\n\n const user = getCursorUser(rawPresence.user) ?? getCursorUser(other.info);\n const previousCursor = previousCursors.find(\n (cursor) => cursor.connectionId === other.connectionId\n );\n const hasPresencePositionChanged =\n previousCursor === undefined ||\n previousCursor.rawAnchor !== rawPresence.anchor ||\n previousCursor.rawHead !== rawPresence.head;\n\n cursors.push({\n anchor: hasPresencePositionChanged\n ? rawPresence.anchor\n : previousCursor.anchor,\n connectionId: other.connectionId,\n head: hasPresencePositionChanged ? rawPresence.head : previousCursor.head,\n rawAnchor: rawPresence.anchor,\n rawHead: rawPresence.head,\n user,\n });\n }\n\n return cursors;\n}\n\nfunction buildDecorationsFromCursors(\n cursors: readonly RemoteCursor[],\n doc: ProseMirrorNode\n): DecorationSet {\n const decorations: Decoration[] = [];\n\n for (const cursor of cursors) {\n const anchor = clampPosition(cursor.anchor, doc);\n const head = clampPosition(cursor.head, doc);\n const from = Math.min(anchor, head);\n const to = Math.max(anchor, head);\n const user = cursor.user;\n const color = user?.color ?? \"#0f83ff\";\n\n if (from !== to) {\n decorations.push(\n Decoration.inline(from, to, {\n class: \"collaboration-carets__selection\",\n style: `background-color: ${color}33`,\n })\n );\n }\n\n decorations.push(\n Decoration.widget(\n normalizeCaretPosition(head, doc),\n () => createCursorElement(user),\n {\n key: `liveblocks-caret-${cursor.connectionId}`,\n side: -1,\n }\n )\n );\n }\n\n return DecorationSet.create(doc, decorations);\n}\n\nfunction createLiveblocksCaretPlugin(\n options: CollaborationCaretOptions,\n storage: CollaborationCaretStorage\n): Plugin {\n const room = options.room;\n if (room === undefined) {\n throw new Error(\"[Liveblocks] The Liveblocks caret plugin requires a room.\");\n }\n\n let view: EditorView | undefined;\n let unsubscribe: (() => void) | undefined;\n\n const updatePresence = (nextView: EditorView) => {\n const { anchor, head } = nextView.state.selection;\n room.updatePresence(\n presencePatch({\n field: options.field,\n anchor,\n head,\n user: options.user,\n })\n );\n };\n\n const updateDecorations = () => {\n if (view === undefined) {\n return;\n }\n\n storage.users = room.getOthers().map((other) => {\n const rawPresence: unknown = other.presence[PRESENCE_KEY];\n const cursorPresence = isCursorPresence(rawPresence)\n ? rawPresence\n : undefined;\n\n return {\n clientId: other.connectionId,\n ...(getCursorUser(cursorPresence?.user) ?? getCursorUser(other.info)),\n };\n });\n\n const previousCursors =\n LIVEBLOCKS_CARET_PLUGIN_KEY.getState(view.state)?.cursors ?? [];\n const cursors = getRemoteCursors(room, options.field, previousCursors);\n\n view.dispatch(\n view.state.tr.setMeta(LIVEBLOCKS_CARET_PLUGIN_KEY, {\n cursors,\n })\n );\n };\n\n return new Plugin({\n key: LIVEBLOCKS_CARET_PLUGIN_KEY,\n state: {\n init(_, state): CollaborationCaretPluginState {\n return {\n cursors: [],\n decorations: DecorationSet.create(state.doc, []),\n };\n },\n apply(tr, state): CollaborationCaretPluginState {\n const meta = tr.getMeta(LIVEBLOCKS_CARET_PLUGIN_KEY) as\n | { cursors: RemoteCursor[] }\n | undefined;\n\n if (meta !== undefined) {\n return {\n cursors: meta.cursors,\n decorations: buildDecorationsFromCursors(meta.cursors, tr.doc),\n };\n }\n\n if (!tr.docChanged) {\n return state;\n }\n\n if (!tr.getMeta(LIVEBLOCKS_COLLABORATION_PLUGIN_KEY)) {\n const cursors = state.cursors.map((cursor) => ({\n ...cursor,\n anchor: tr.mapping.map(cursor.anchor, -1),\n head: tr.mapping.map(cursor.head, -1),\n }));\n\n return {\n cursors,\n decorations: buildDecorationsFromCursors(cursors, tr.doc),\n };\n }\n\n // Remote presence can arrive before the matching remote document\n // update. Keep the stored cursor positions and rebuild them against\n // the new document so pre-arrived presence is no longer clamped to the\n // old document size.\n return {\n cursors: state.cursors,\n decorations: buildDecorationsFromCursors(state.cursors, tr.doc),\n };\n },\n },\n props: {\n decorations(state) {\n return (\n LIVEBLOCKS_CARET_PLUGIN_KEY.getState(state)?.decorations ??\n DecorationSet.empty\n );\n },\n },\n view(editorView) {\n view = editorView;\n updatePresence(editorView);\n updateDecorations();\n unsubscribe = room.events.others.subscribe(updateDecorations);\n\n return {\n update(nextView, prevState) {\n view = nextView;\n\n if (!nextView.state.selection.eq(prevState.selection)) {\n updatePresence(nextView);\n }\n\n },\n destroy() {\n unsubscribe?.();\n unsubscribe = undefined;\n view = undefined;\n room.updatePresence({ [PRESENCE_KEY]: null });\n },\n };\n },\n });\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n collaborationCaret: {\n updateUser: (attributes: Record<string, any>) => ReturnType;\n user: (attributes: Record<string, any>) => ReturnType;\n };\n }\n}\n\nexport const LiveblocksCollaborationCaret = Extension.create<\n CollaborationCaretOptions,\n CollaborationCaretStorage\n>({\n name: \"collaborationCaret\",\n priority: 999,\n\n addOptions() {\n return {\n room: undefined,\n field: \"default\",\n user: {\n name: undefined,\n color: undefined,\n },\n };\n },\n\n addStorage() {\n return {\n users: [],\n };\n },\n\n addCommands() {\n return {\n updateUser:\n (attributes) =>\n ({ editor }) => {\n const nextUser = getCursorUser({\n ...this.options.user,\n name:\n typeof attributes.name === \"string\"\n ? attributes.name\n : this.options.user.name,\n color:\n typeof attributes.color === \"string\"\n ? attributes.color\n : this.options.user.color,\n }) ?? {};\n\n if (\n nextUser.name === this.options.user.name &&\n nextUser.color === this.options.user.color\n ) {\n return true;\n }\n\n this.options.user = nextUser;\n\n if (this.options.room !== undefined) {\n const { anchor, head } = editor.state.selection;\n this.options.room.updatePresence(\n presencePatch({\n field: this.options.field,\n anchor,\n head,\n user: this.options.user,\n })\n );\n }\n return true;\n },\n user:\n (attributes) =>\n ({ editor }) => {\n return editor.commands.updateUser(attributes);\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [createLiveblocksCaretPlugin(this.options, this.storage)];\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cursors.js","sources":["../../src/collaboration-liveblocks/cursors.ts"],"sourcesContent":["import {\n type CollaborationCaretOptions,\n type CollaborationCaretStorage,\n createLiveblocksCollaborationCaretPlugin,\n getCursorUser,\n LIVEBLOCKS_CARET_PLUGIN_KEY,\n presencePatch,\n} from \"@liveblocks/prosemirror\";\nimport { Extension } from \"@tiptap/core\";\n\nexport { LIVEBLOCKS_CARET_PLUGIN_KEY };\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n collaborationCaret: {\n updateUser: (attributes: Record<string, any>) => ReturnType;\n user: (attributes: Record<string, any>) => ReturnType;\n };\n }\n}\n\nexport const LiveblocksCollaborationCaret = Extension.create<\n CollaborationCaretOptions,\n CollaborationCaretStorage\n>({\n name: \"collaborationCaret\",\n priority: 999,\n\n addOptions() {\n return {\n room: undefined,\n field: \"default\",\n user: {\n name: undefined,\n color: undefined,\n },\n };\n },\n\n addStorage() {\n return {\n users: [],\n };\n },\n\n addCommands() {\n return {\n updateUser:\n (attributes) =>\n ({ editor }) => {\n const nextUser =\n getCursorUser({\n ...this.options.user,\n name:\n typeof attributes.name === \"string\"\n ? attributes.name\n : this.options.user.name,\n color:\n typeof attributes.color === \"string\"\n ? attributes.color\n : this.options.user.color,\n }) ?? {};\n\n if (\n nextUser.name === this.options.user.name &&\n nextUser.color === this.options.user.color\n ) {\n return true;\n }\n\n this.options.user = nextUser;\n\n if (this.options.room !== undefined) {\n const { anchor, head } = editor.state.selection;\n this.options.room.updatePresence(\n presencePatch({\n field: this.options.field,\n anchor,\n head,\n user: this.options.user,\n })\n );\n }\n return true;\n },\n user:\n (attributes) =>\n ({ editor }) => {\n return editor.commands.updateUser(attributes);\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [\n createLiveblocksCollaborationCaretPlugin(this.options, this.storage),\n ];\n },\n});\n"],"names":[],"mappings":";;;;AAqBa,MAAA,4BAAA,GAA+B,UAAU,MAGpD,CAAA;AAAA,EACA,IAAM,EAAA,oBAAA;AAAA,EACN,QAAU,EAAA,GAAA;AAAA,EAEV,UAAa,GAAA;AACX,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,KAAA,CAAA;AAAA,MACN,KAAO,EAAA,SAAA;AAAA,MACP,IAAM,EAAA;AAAA,QACJ,IAAM,EAAA,KAAA,CAAA;AAAA,QACN,KAAO,EAAA,KAAA,CAAA;AAAA,OACT;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,UAAa,GAAA;AACX,IAAO,OAAA;AAAA,MACL,OAAO,EAAC;AAAA,KACV,CAAA;AAAA,GACF;AAAA,EAEA,WAAc,GAAA;AACZ,IAAO,OAAA;AAAA,MACL,YACE,CAAC,UAAA,KACD,CAAC,EAAE,QAAa,KAAA;AACd,QAAA,MAAM,WACJ,aAAc,CAAA;AAAA,UACZ,GAAG,KAAK,OAAQ,CAAA,IAAA;AAAA,UAChB,IAAA,EACE,OAAO,UAAW,CAAA,IAAA,KAAS,WACvB,UAAW,CAAA,IAAA,GACX,IAAK,CAAA,OAAA,CAAQ,IAAK,CAAA,IAAA;AAAA,UACxB,KAAA,EACE,OAAO,UAAW,CAAA,KAAA,KAAU,WACxB,UAAW,CAAA,KAAA,GACX,IAAK,CAAA,OAAA,CAAQ,IAAK,CAAA,KAAA;AAAA,SACzB,KAAK,EAAC,CAAA;AAET,QACE,IAAA,QAAA,CAAS,IAAS,KAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,IACpC,IAAA,QAAA,CAAS,KAAU,KAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,KACrC,EAAA;AACA,UAAO,OAAA,IAAA,CAAA;AAAA,SACT;AAEA,QAAA,IAAA,CAAK,QAAQ,IAAO,GAAA,QAAA,CAAA;AAEpB,QAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,KAAS,KAAW,CAAA,EAAA;AACnC,UAAA,MAAM,EAAE,MAAA,EAAQ,IAAK,EAAA,GAAI,OAAO,KAAM,CAAA,SAAA,CAAA;AACtC,UAAA,IAAA,CAAK,QAAQ,IAAK,CAAA,cAAA;AAAA,YAChB,aAAc,CAAA;AAAA,cACZ,KAAA,EAAO,KAAK,OAAQ,CAAA,KAAA;AAAA,cACpB,MAAA;AAAA,cACA,IAAA;AAAA,cACA,IAAA,EAAM,KAAK,OAAQ,CAAA,IAAA;AAAA,aACpB,CAAA;AAAA,WACH,CAAA;AAAA,SACF;AACA,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,MACF,MACE,CAAC,UAAA,KACD,CAAC,EAAE,QAAa,KAAA;AACd,QAAO,OAAA,MAAA,CAAO,QAAS,CAAA,UAAA,CAAW,UAAU,CAAA,CAAA;AAAA,OAC9C;AAAA,KACJ,CAAA;AAAA,GACF;AAAA,EAEA,qBAAwB,GAAA;AACtB,IAAO,OAAA;AAAA,MACL,wCAAyC,CAAA,IAAA,CAAK,OAAS,EAAA,IAAA,CAAK,OAAO,CAAA;AAAA,KACrE,CAAA;AAAA,GACF;AACF,CAAC;;;;"}
|