@blocknote/core 0.29.1 → 0.30.0
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/README.md +125 -0
- package/dist/blocknote.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1479 -1339
- package/dist/blocknote.js.map +1 -1
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +751 -9
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +3 -6
- package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +0 -7
- package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +0 -5
- package/src/api/blockManipulation/commands/moveBlocks/__snapshots__/moveBlocks.test.ts.snap +0 -20
- package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +0 -12
- package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +0 -6
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +0 -17
- package/src/api/clipboard/fromClipboard/pasteExtension.ts +19 -1
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +5 -0
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +32 -18
- package/src/blocks/FileBlockContent/FileBlockContent.ts +5 -0
- package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +9 -2
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +3 -0
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +10 -2
- package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +9 -25
- package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +14 -3
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +9 -26
- package/src/blocks/ListItemBlockContent/getListItemContent.ts +115 -0
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +6 -2
- package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +6 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +71 -14
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +10 -2
- package/src/blocks/defaultBlockHelpers.ts +16 -0
- package/src/editor/Block.css +2 -1
- package/src/editor/BlockNoteEditor.ts +103 -60
- package/src/editor/BlockNoteExtensions.ts +14 -5
- package/src/extensions/Collaboration/CursorPlugin.ts +152 -0
- package/src/extensions/Collaboration/SyncPlugin.ts +15 -0
- package/src/extensions/Collaboration/UndoPlugin.ts +14 -0
- package/src/extensions/FilePanel/FilePanelPlugin.ts +31 -22
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +2 -4
- package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +3 -0
- package/src/i18n/locales/index.ts +2 -0
- package/src/i18n/locales/ru.ts +2 -2
- package/src/i18n/locales/sk.ts +355 -0
- package/src/i18n/locales/zh-tw.ts +390 -0
- package/src/pm-nodes/BlockContainer.ts +7 -6
- package/src/schema/blocks/createSpec.ts +1 -1
- package/src/schema/blocks/internal.ts +0 -1
- package/src/schema/blocks/types.ts +2 -1
- package/types/src/api/blockManipulation/setupTestEnv.d.ts +8 -4
- package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +8 -4
- package/types/src/blocks/ListItemBlockContent/getListItemContent.d.ts +28 -0
- package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +8 -4
- package/types/src/blocks/defaultBlockHelpers.d.ts +1 -0
- package/types/src/blocks/defaultBlocks.d.ts +16 -8
- package/types/src/editor/BlockNoteEditor.d.ts +18 -1
- package/types/src/extensions/Collaboration/CursorPlugin.d.ts +31 -0
- package/types/src/extensions/Collaboration/SyncPlugin.d.ts +7 -0
- package/types/src/extensions/Collaboration/UndoPlugin.d.ts +6 -0
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +1 -1
- package/types/src/i18n/locales/index.d.ts +2 -0
- package/types/src/i18n/locales/sk.d.ts +313 -0
- package/types/src/i18n/locales/zh-tw.d.ts +2 -0
- package/types/src/schema/blocks/types.d.ts +2 -1
- package/src/extensions/Collaboration/createCollaborationExtensions.ts +0 -147
- package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +0 -17
|
@@ -26,6 +26,7 @@ import { EventEmitter } from "../util/EventEmitter.js";
|
|
|
26
26
|
export type BlockNoteExtensionFactory = (editor: BlockNoteEditor<any, any, any>) => BlockNoteExtension;
|
|
27
27
|
export type BlockNoteExtension = AnyExtension | {
|
|
28
28
|
plugin: Plugin;
|
|
29
|
+
priority?: number;
|
|
29
30
|
};
|
|
30
31
|
export type BlockCache<BSchema extends BlockSchema = any, ISchema extends InlineContentSchema = any, SSchema extends StyleSchema = any> = WeakMap<Node, Block<BSchema, ISchema, SSchema>>;
|
|
31
32
|
export type BlockNoteEditorOptions<BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema> = {
|
|
@@ -289,6 +290,7 @@ export declare class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockS
|
|
|
289
290
|
readonly tableHandles?: TableHandlesProsemirrorPlugin<ISchema, SSchema>;
|
|
290
291
|
readonly comments?: CommentsPlugin;
|
|
291
292
|
private readonly showSelectionPlugin;
|
|
293
|
+
private readonly cursorPlugin;
|
|
292
294
|
/**
|
|
293
295
|
* The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
|
|
294
296
|
* This method should set when creating the editor as this is application-specific.
|
|
@@ -378,8 +380,15 @@ export declare class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockS
|
|
|
378
380
|
* @warning Not needed to call manually when using React, use BlockNoteView to take care of mounting
|
|
379
381
|
*/
|
|
380
382
|
mount: (parentElement?: HTMLElement | null, contentComponent?: any) => void;
|
|
383
|
+
/**
|
|
384
|
+
* Get the underlying prosemirror state
|
|
385
|
+
* @note Prefer using `editor.transact` to read the current editor state, as that will ensure the state is up to date
|
|
386
|
+
* @see https://prosemirror.net/docs/ref/#state.EditorState
|
|
387
|
+
*/
|
|
388
|
+
get prosemirrorState(): import("prosemirror-state").EditorState;
|
|
381
389
|
/**
|
|
382
390
|
* Get the underlying prosemirror view
|
|
391
|
+
* @see https://prosemirror.net/docs/ref/#view.EditorView
|
|
383
392
|
*/
|
|
384
393
|
get prosemirrorView(): EditorView | undefined;
|
|
385
394
|
get domElement(): HTMLDivElement | undefined;
|
|
@@ -441,7 +450,7 @@ export declare class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockS
|
|
|
441
450
|
* Executes a callback whenever the editor's contents change.
|
|
442
451
|
* @param callback The callback to execute.
|
|
443
452
|
*
|
|
444
|
-
* @deprecated use
|
|
453
|
+
* @deprecated use {@link BlockNoteEditor.onChange} instead
|
|
445
454
|
*/
|
|
446
455
|
onEditorContentChange(callback: () => void): void;
|
|
447
456
|
/**
|
|
@@ -516,6 +525,14 @@ export declare class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockS
|
|
|
516
525
|
insertedBlocks: Block<BSchema, ISchema, SSchema>[];
|
|
517
526
|
removedBlocks: Block<BSchema, ISchema, SSchema>[];
|
|
518
527
|
};
|
|
528
|
+
/**
|
|
529
|
+
* Undo the last action.
|
|
530
|
+
*/
|
|
531
|
+
undo(): boolean;
|
|
532
|
+
/**
|
|
533
|
+
* Redo the last action.
|
|
534
|
+
*/
|
|
535
|
+
redo(): boolean;
|
|
519
536
|
/**
|
|
520
537
|
* Insert a piece of content at the current cursor position.
|
|
521
538
|
*
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Plugin } from "prosemirror-state";
|
|
2
|
+
import { Awareness } from "y-protocols/awareness.js";
|
|
3
|
+
import * as Y from "yjs";
|
|
4
|
+
export type CollaborationUser = {
|
|
5
|
+
name: string;
|
|
6
|
+
color: string;
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class CursorPlugin {
|
|
10
|
+
private collaboration;
|
|
11
|
+
plugin: Plugin;
|
|
12
|
+
private provider;
|
|
13
|
+
private recentlyUpdatedCursors;
|
|
14
|
+
constructor(collaboration: {
|
|
15
|
+
fragment: Y.XmlFragment;
|
|
16
|
+
user: CollaborationUser;
|
|
17
|
+
provider: {
|
|
18
|
+
awareness: Awareness;
|
|
19
|
+
};
|
|
20
|
+
renderCursor?: (user: CollaborationUser) => HTMLElement;
|
|
21
|
+
showCursorLabels?: "always" | "activity";
|
|
22
|
+
});
|
|
23
|
+
get priority(): number;
|
|
24
|
+
private renderCursor;
|
|
25
|
+
updateUser: (user: {
|
|
26
|
+
name: string;
|
|
27
|
+
color: string;
|
|
28
|
+
[key: string]: string;
|
|
29
|
+
}) => void;
|
|
30
|
+
static defaultCursorRender: (user: CollaborationUser) => HTMLSpanElement;
|
|
31
|
+
}
|
|
@@ -13,7 +13,7 @@ export declare class FilePanelView<I extends InlineContentSchema, S extends Styl
|
|
|
13
13
|
private readonly pmView;
|
|
14
14
|
state?: FilePanelState<I, S>;
|
|
15
15
|
emitUpdate: () => void;
|
|
16
|
-
constructor(editor: BlockNoteEditor<Record<string, FileBlockConfig>, I, S>, pluginKey: PluginKey, pmView: EditorView, emitUpdate: (state: FilePanelState<I, S>) => void);
|
|
16
|
+
constructor(editor: BlockNoteEditor<Record<string, FileBlockConfig>, I, S>, pluginKey: PluginKey<FilePanelState<I, S>>, pmView: EditorView, emitUpdate: (state: FilePanelState<I, S>) => void);
|
|
17
17
|
mouseDownHandler: () => void;
|
|
18
18
|
dragstartHandler: () => void;
|
|
19
19
|
scrollHandler: () => void;
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
export declare const sk: {
|
|
2
|
+
slash_menu: {
|
|
3
|
+
heading: {
|
|
4
|
+
title: string;
|
|
5
|
+
subtext: string;
|
|
6
|
+
aliases: string[];
|
|
7
|
+
group: string;
|
|
8
|
+
};
|
|
9
|
+
heading_2: {
|
|
10
|
+
title: string;
|
|
11
|
+
subtext: string;
|
|
12
|
+
aliases: string[];
|
|
13
|
+
group: string;
|
|
14
|
+
};
|
|
15
|
+
heading_3: {
|
|
16
|
+
title: string;
|
|
17
|
+
subtext: string;
|
|
18
|
+
aliases: string[];
|
|
19
|
+
group: string;
|
|
20
|
+
};
|
|
21
|
+
quote: {
|
|
22
|
+
title: string;
|
|
23
|
+
subtext: string;
|
|
24
|
+
aliases: string[];
|
|
25
|
+
group: string;
|
|
26
|
+
};
|
|
27
|
+
numbered_list: {
|
|
28
|
+
title: string;
|
|
29
|
+
subtext: string;
|
|
30
|
+
aliases: string[];
|
|
31
|
+
group: string;
|
|
32
|
+
};
|
|
33
|
+
bullet_list: {
|
|
34
|
+
title: string;
|
|
35
|
+
subtext: string;
|
|
36
|
+
aliases: string[];
|
|
37
|
+
group: string;
|
|
38
|
+
};
|
|
39
|
+
check_list: {
|
|
40
|
+
title: string;
|
|
41
|
+
subtext: string;
|
|
42
|
+
aliases: string[];
|
|
43
|
+
group: string;
|
|
44
|
+
};
|
|
45
|
+
paragraph: {
|
|
46
|
+
title: string;
|
|
47
|
+
subtext: string;
|
|
48
|
+
aliases: string[];
|
|
49
|
+
group: string;
|
|
50
|
+
};
|
|
51
|
+
code_block: {
|
|
52
|
+
title: string;
|
|
53
|
+
subtext: string;
|
|
54
|
+
aliases: string[];
|
|
55
|
+
group: string;
|
|
56
|
+
};
|
|
57
|
+
page_break: {
|
|
58
|
+
title: string;
|
|
59
|
+
subtext: string;
|
|
60
|
+
aliases: string[];
|
|
61
|
+
group: string;
|
|
62
|
+
};
|
|
63
|
+
table: {
|
|
64
|
+
title: string;
|
|
65
|
+
subtext: string;
|
|
66
|
+
aliases: string[];
|
|
67
|
+
group: string;
|
|
68
|
+
};
|
|
69
|
+
image: {
|
|
70
|
+
title: string;
|
|
71
|
+
subtext: string;
|
|
72
|
+
aliases: string[];
|
|
73
|
+
group: string;
|
|
74
|
+
};
|
|
75
|
+
video: {
|
|
76
|
+
title: string;
|
|
77
|
+
subtext: string;
|
|
78
|
+
aliases: string[];
|
|
79
|
+
group: string;
|
|
80
|
+
};
|
|
81
|
+
audio: {
|
|
82
|
+
title: string;
|
|
83
|
+
subtext: string;
|
|
84
|
+
aliases: string[];
|
|
85
|
+
group: string;
|
|
86
|
+
};
|
|
87
|
+
file: {
|
|
88
|
+
title: string;
|
|
89
|
+
subtext: string;
|
|
90
|
+
aliases: string[];
|
|
91
|
+
group: string;
|
|
92
|
+
};
|
|
93
|
+
emoji: {
|
|
94
|
+
title: string;
|
|
95
|
+
subtext: string;
|
|
96
|
+
aliases: string[];
|
|
97
|
+
group: string;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
placeholders: Record<string | "default" | "emptyDocument", string | undefined>;
|
|
101
|
+
file_blocks: {
|
|
102
|
+
image: {
|
|
103
|
+
add_button_text: string;
|
|
104
|
+
};
|
|
105
|
+
video: {
|
|
106
|
+
add_button_text: string;
|
|
107
|
+
};
|
|
108
|
+
audio: {
|
|
109
|
+
add_button_text: string;
|
|
110
|
+
};
|
|
111
|
+
file: {
|
|
112
|
+
add_button_text: string;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
side_menu: {
|
|
116
|
+
add_block_label: string;
|
|
117
|
+
drag_handle_label: string;
|
|
118
|
+
};
|
|
119
|
+
drag_handle: {
|
|
120
|
+
delete_menuitem: string;
|
|
121
|
+
colors_menuitem: string;
|
|
122
|
+
header_row_menuitem: string;
|
|
123
|
+
header_column_menuitem: string;
|
|
124
|
+
};
|
|
125
|
+
table_handle: {
|
|
126
|
+
delete_column_menuitem: string;
|
|
127
|
+
delete_row_menuitem: string;
|
|
128
|
+
add_left_menuitem: string;
|
|
129
|
+
add_right_menuitem: string;
|
|
130
|
+
add_above_menuitem: string;
|
|
131
|
+
add_below_menuitem: string;
|
|
132
|
+
split_cell_menuitem: string;
|
|
133
|
+
merge_cells_menuitem: string;
|
|
134
|
+
background_color_menuitem: string;
|
|
135
|
+
};
|
|
136
|
+
suggestion_menu: {
|
|
137
|
+
no_items_title: string;
|
|
138
|
+
loading: string;
|
|
139
|
+
};
|
|
140
|
+
color_picker: {
|
|
141
|
+
text_title: string;
|
|
142
|
+
background_title: string;
|
|
143
|
+
colors: {
|
|
144
|
+
default: string;
|
|
145
|
+
gray: string;
|
|
146
|
+
brown: string;
|
|
147
|
+
red: string;
|
|
148
|
+
orange: string;
|
|
149
|
+
yellow: string;
|
|
150
|
+
green: string;
|
|
151
|
+
blue: string;
|
|
152
|
+
purple: string;
|
|
153
|
+
pink: string;
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
formatting_toolbar: {
|
|
157
|
+
bold: {
|
|
158
|
+
tooltip: string;
|
|
159
|
+
secondary_tooltip: string;
|
|
160
|
+
};
|
|
161
|
+
italic: {
|
|
162
|
+
tooltip: string;
|
|
163
|
+
secondary_tooltip: string;
|
|
164
|
+
};
|
|
165
|
+
underline: {
|
|
166
|
+
tooltip: string;
|
|
167
|
+
secondary_tooltip: string;
|
|
168
|
+
};
|
|
169
|
+
strike: {
|
|
170
|
+
tooltip: string;
|
|
171
|
+
secondary_tooltip: string;
|
|
172
|
+
};
|
|
173
|
+
code: {
|
|
174
|
+
tooltip: string;
|
|
175
|
+
secondary_tooltip: string;
|
|
176
|
+
};
|
|
177
|
+
colors: {
|
|
178
|
+
tooltip: string;
|
|
179
|
+
};
|
|
180
|
+
link: {
|
|
181
|
+
tooltip: string;
|
|
182
|
+
secondary_tooltip: string;
|
|
183
|
+
};
|
|
184
|
+
file_caption: {
|
|
185
|
+
tooltip: string;
|
|
186
|
+
input_placeholder: string;
|
|
187
|
+
};
|
|
188
|
+
file_replace: {
|
|
189
|
+
tooltip: {
|
|
190
|
+
image: string;
|
|
191
|
+
video: string;
|
|
192
|
+
audio: string;
|
|
193
|
+
file: string;
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
file_rename: {
|
|
197
|
+
tooltip: {
|
|
198
|
+
image: string;
|
|
199
|
+
video: string;
|
|
200
|
+
audio: string;
|
|
201
|
+
file: string;
|
|
202
|
+
};
|
|
203
|
+
input_placeholder: {
|
|
204
|
+
image: string;
|
|
205
|
+
video: string;
|
|
206
|
+
audio: string;
|
|
207
|
+
file: string;
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
file_download: {
|
|
211
|
+
tooltip: {
|
|
212
|
+
image: string;
|
|
213
|
+
video: string;
|
|
214
|
+
audio: string;
|
|
215
|
+
file: string;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
file_delete: {
|
|
219
|
+
tooltip: {
|
|
220
|
+
image: string;
|
|
221
|
+
video: string;
|
|
222
|
+
audio: string;
|
|
223
|
+
file: string;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
file_preview_toggle: {
|
|
227
|
+
tooltip: string;
|
|
228
|
+
};
|
|
229
|
+
nest: {
|
|
230
|
+
tooltip: string;
|
|
231
|
+
secondary_tooltip: string;
|
|
232
|
+
};
|
|
233
|
+
unnest: {
|
|
234
|
+
tooltip: string;
|
|
235
|
+
secondary_tooltip: string;
|
|
236
|
+
};
|
|
237
|
+
align_left: {
|
|
238
|
+
tooltip: string;
|
|
239
|
+
};
|
|
240
|
+
align_center: {
|
|
241
|
+
tooltip: string;
|
|
242
|
+
};
|
|
243
|
+
align_right: {
|
|
244
|
+
tooltip: string;
|
|
245
|
+
};
|
|
246
|
+
align_justify: {
|
|
247
|
+
tooltip: string;
|
|
248
|
+
};
|
|
249
|
+
table_cell_merge: {
|
|
250
|
+
tooltip: string;
|
|
251
|
+
};
|
|
252
|
+
comment: {
|
|
253
|
+
tooltip: string;
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
file_panel: {
|
|
257
|
+
upload: {
|
|
258
|
+
title: string;
|
|
259
|
+
file_placeholder: {
|
|
260
|
+
image: string;
|
|
261
|
+
video: string;
|
|
262
|
+
audio: string;
|
|
263
|
+
file: string;
|
|
264
|
+
};
|
|
265
|
+
upload_error: string;
|
|
266
|
+
};
|
|
267
|
+
embed: {
|
|
268
|
+
title: string;
|
|
269
|
+
embed_button: {
|
|
270
|
+
image: string;
|
|
271
|
+
video: string;
|
|
272
|
+
audio: string;
|
|
273
|
+
file: string;
|
|
274
|
+
};
|
|
275
|
+
url_placeholder: string;
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
link_toolbar: {
|
|
279
|
+
delete: {
|
|
280
|
+
tooltip: string;
|
|
281
|
+
};
|
|
282
|
+
edit: {
|
|
283
|
+
text: string;
|
|
284
|
+
tooltip: string;
|
|
285
|
+
};
|
|
286
|
+
open: {
|
|
287
|
+
tooltip: string;
|
|
288
|
+
};
|
|
289
|
+
form: {
|
|
290
|
+
title_placeholder: string;
|
|
291
|
+
url_placeholder: string;
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
comments: {
|
|
295
|
+
actions: {
|
|
296
|
+
add_reaction: string;
|
|
297
|
+
resolve: string;
|
|
298
|
+
edit_comment: string;
|
|
299
|
+
delete_comment: string;
|
|
300
|
+
more_actions: string;
|
|
301
|
+
};
|
|
302
|
+
reactions: {
|
|
303
|
+
reacted_by: string;
|
|
304
|
+
};
|
|
305
|
+
sidebar: {
|
|
306
|
+
marked_as_resolved: string;
|
|
307
|
+
more_replies: (count: number) => string;
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
generic: {
|
|
311
|
+
ctrl_shortcut: string;
|
|
312
|
+
};
|
|
313
|
+
};
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import Collaboration from "@tiptap/extension-collaboration";
|
|
2
|
-
import CollaborationCursor from "@tiptap/extension-collaboration-cursor";
|
|
3
|
-
import { Awareness } from "y-protocols/awareness";
|
|
4
|
-
import * as Y from "yjs";
|
|
5
|
-
|
|
6
|
-
export const createCollaborationExtensions = (collaboration: {
|
|
7
|
-
fragment: Y.XmlFragment;
|
|
8
|
-
user: {
|
|
9
|
-
name: string;
|
|
10
|
-
color: string;
|
|
11
|
-
[key: string]: string;
|
|
12
|
-
};
|
|
13
|
-
provider: any;
|
|
14
|
-
renderCursor?: (user: any) => HTMLElement;
|
|
15
|
-
showCursorLabels?: "always" | "activity";
|
|
16
|
-
}) => {
|
|
17
|
-
const tiptapExtensions = [];
|
|
18
|
-
|
|
19
|
-
tiptapExtensions.push(
|
|
20
|
-
Collaboration.configure({
|
|
21
|
-
fragment: collaboration.fragment,
|
|
22
|
-
})
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const awareness = collaboration.provider?.awareness as Awareness | undefined;
|
|
26
|
-
|
|
27
|
-
if (awareness) {
|
|
28
|
-
const cursors = new Map<
|
|
29
|
-
number,
|
|
30
|
-
{ element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }
|
|
31
|
-
>();
|
|
32
|
-
|
|
33
|
-
if (collaboration.showCursorLabels !== "always") {
|
|
34
|
-
awareness.on(
|
|
35
|
-
"change",
|
|
36
|
-
({
|
|
37
|
-
updated,
|
|
38
|
-
}: {
|
|
39
|
-
added: Array<number>;
|
|
40
|
-
updated: Array<number>;
|
|
41
|
-
removed: Array<number>;
|
|
42
|
-
}) => {
|
|
43
|
-
for (const clientID of updated) {
|
|
44
|
-
const cursor = cursors.get(clientID);
|
|
45
|
-
|
|
46
|
-
if (cursor) {
|
|
47
|
-
cursor.element.setAttribute("data-active", "");
|
|
48
|
-
|
|
49
|
-
if (cursor.hideTimeout) {
|
|
50
|
-
clearTimeout(cursor.hideTimeout);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
cursors.set(clientID, {
|
|
54
|
-
element: cursor.element,
|
|
55
|
-
hideTimeout: setTimeout(() => {
|
|
56
|
-
cursor.element.removeAttribute("data-active");
|
|
57
|
-
}, 2000),
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const renderCursor = (user: { name: string; color: string }) => {
|
|
66
|
-
const cursorElement = document.createElement("span");
|
|
67
|
-
|
|
68
|
-
cursorElement.classList.add("bn-collaboration-cursor__base");
|
|
69
|
-
|
|
70
|
-
const caretElement = document.createElement("span");
|
|
71
|
-
caretElement.setAttribute("contentedEditable", "false");
|
|
72
|
-
caretElement.classList.add("bn-collaboration-cursor__caret");
|
|
73
|
-
caretElement.setAttribute("style", `background-color: ${user.color}`);
|
|
74
|
-
|
|
75
|
-
const labelElement = document.createElement("span");
|
|
76
|
-
|
|
77
|
-
labelElement.classList.add("bn-collaboration-cursor__label");
|
|
78
|
-
labelElement.setAttribute("style", `background-color: ${user.color}`);
|
|
79
|
-
labelElement.insertBefore(document.createTextNode(user.name), null);
|
|
80
|
-
|
|
81
|
-
caretElement.insertBefore(labelElement, null);
|
|
82
|
-
|
|
83
|
-
cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
|
|
84
|
-
cursorElement.insertBefore(caretElement, null);
|
|
85
|
-
cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
|
|
86
|
-
|
|
87
|
-
return cursorElement;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const render = (
|
|
91
|
-
user: { color: string; name: string },
|
|
92
|
-
clientID: number
|
|
93
|
-
) => {
|
|
94
|
-
let cursorData = cursors.get(clientID);
|
|
95
|
-
|
|
96
|
-
if (!cursorData) {
|
|
97
|
-
const cursorElement =
|
|
98
|
-
collaboration?.renderCursor?.(user) || renderCursor(user);
|
|
99
|
-
|
|
100
|
-
if (collaboration?.showCursorLabels !== "always") {
|
|
101
|
-
cursorElement.addEventListener("mouseenter", () => {
|
|
102
|
-
const cursor = cursors.get(clientID)!;
|
|
103
|
-
cursor.element.setAttribute("data-active", "");
|
|
104
|
-
|
|
105
|
-
if (cursor.hideTimeout) {
|
|
106
|
-
clearTimeout(cursor.hideTimeout);
|
|
107
|
-
cursors.set(clientID, {
|
|
108
|
-
element: cursor.element,
|
|
109
|
-
hideTimeout: undefined,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
cursorElement.addEventListener("mouseleave", () => {
|
|
115
|
-
const cursor = cursors.get(clientID)!;
|
|
116
|
-
|
|
117
|
-
cursors.set(clientID, {
|
|
118
|
-
element: cursor.element,
|
|
119
|
-
hideTimeout: setTimeout(() => {
|
|
120
|
-
cursor.element.removeAttribute("data-active");
|
|
121
|
-
}, 2000),
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
cursorData = {
|
|
127
|
-
element: cursorElement,
|
|
128
|
-
hideTimeout: undefined,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
cursors.set(clientID, cursorData);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return cursorData.element;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
tiptapExtensions.push(
|
|
138
|
-
CollaborationCursor.configure({
|
|
139
|
-
user: collaboration.user,
|
|
140
|
-
render: render as any, // tiptap type not compatible with latest y-prosemirror
|
|
141
|
-
provider: collaboration.provider,
|
|
142
|
-
})
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return tiptapExtensions;
|
|
147
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import * as Y from "yjs";
|
|
2
|
-
export declare const createCollaborationExtensions: (collaboration: {
|
|
3
|
-
fragment: Y.XmlFragment;
|
|
4
|
-
user: {
|
|
5
|
-
name: string;
|
|
6
|
-
color: string;
|
|
7
|
-
[key: string]: string;
|
|
8
|
-
};
|
|
9
|
-
provider: any;
|
|
10
|
-
renderCursor?: (user: any) => HTMLElement;
|
|
11
|
-
showCursorLabels?: "always" | "activity";
|
|
12
|
-
}) => (import("@tiptap/core").Extension<import("@tiptap/extension-collaboration").CollaborationOptions, import("@tiptap/extension-collaboration").CollaborationStorage> | import("@tiptap/core").Extension<import("@tiptap/extension-collaboration-cursor").CollaborationCursorOptions, {
|
|
13
|
-
users: {
|
|
14
|
-
clientId: number;
|
|
15
|
-
[key: string]: any;
|
|
16
|
-
}[];
|
|
17
|
-
}>)[];
|