@blocknote/core 0.42.2 → 0.43.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.
Files changed (200) hide show
  1. package/dist/BlockNoteExtension-BWw0r8Gy.cjs +2 -0
  2. package/dist/BlockNoteExtension-BWw0r8Gy.cjs.map +1 -0
  3. package/dist/BlockNoteExtension-C2X7LW-V.js +25 -0
  4. package/dist/BlockNoteExtension-C2X7LW-V.js.map +1 -0
  5. package/dist/BlockNoteSchema-CbSavEwr.js +270 -0
  6. package/dist/BlockNoteSchema-CbSavEwr.js.map +1 -0
  7. package/dist/BlockNoteSchema-D8TyvlfU.cjs +2 -0
  8. package/dist/BlockNoteSchema-D8TyvlfU.cjs.map +1 -0
  9. package/dist/EventEmitter-CLwfmbqG.cjs +2 -0
  10. package/dist/EventEmitter-CLwfmbqG.cjs.map +1 -0
  11. package/dist/EventEmitter-CjSwpTbz.js +27 -0
  12. package/dist/EventEmitter-CjSwpTbz.js.map +1 -0
  13. package/dist/ShowSelection-BW37oJ6h.cjs +2 -0
  14. package/dist/ShowSelection-BW37oJ6h.cjs.map +1 -0
  15. package/dist/ShowSelection-Dz-NEase.js +43 -0
  16. package/dist/ShowSelection-Dz-NEase.js.map +1 -0
  17. package/dist/TrailingNode-BUhuMJrB.js +2096 -0
  18. package/dist/TrailingNode-BUhuMJrB.js.map +1 -0
  19. package/dist/TrailingNode-CaT_wbho.cjs +2 -0
  20. package/dist/TrailingNode-CaT_wbho.cjs.map +1 -0
  21. package/dist/{blockToNode-DIfPWLH8.js → blockToNode-DBNbhwwC.js} +33 -33
  22. package/dist/blockToNode-DBNbhwwC.js.map +1 -0
  23. package/dist/blockToNode-w7H99R6p.cjs.map +1 -1
  24. package/dist/blocknote.cjs +4 -4
  25. package/dist/blocknote.cjs.map +1 -1
  26. package/dist/blocknote.js +2401 -5592
  27. package/dist/blocknote.js.map +1 -1
  28. package/dist/blocks.cjs +1 -1
  29. package/dist/blocks.js +71 -70
  30. package/dist/blocks.js.map +1 -1
  31. package/dist/comments.cjs +1 -1
  32. package/dist/comments.cjs.map +1 -1
  33. package/dist/comments.js +451 -137
  34. package/dist/comments.js.map +1 -1
  35. package/dist/{BlockNoteSchema-Bi-eeHal.js → defaultBlocks-BJtxTOM2.js} +991 -1047
  36. package/dist/defaultBlocks-BJtxTOM2.js.map +1 -0
  37. package/dist/defaultBlocks-BxFclIGP.cjs +6 -0
  38. package/dist/defaultBlocks-BxFclIGP.cjs.map +1 -0
  39. package/dist/extensions.cjs +2 -0
  40. package/dist/extensions.cjs.map +1 -0
  41. package/dist/extensions.js +57 -0
  42. package/dist/extensions.js.map +1 -0
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/dist/webpack-stats.json +1 -1
  45. package/dist/yjs.js +1 -1
  46. package/package.json +12 -6
  47. package/src/api/nodeConversions/blockToNode.ts +1 -1
  48. package/src/api/nodeConversions/nodeToBlock.ts +1 -1
  49. package/src/blocks/Code/block.ts +4 -4
  50. package/src/blocks/Divider/block.ts +2 -2
  51. package/src/blocks/File/helpers/render/createAddFileButton.ts +7 -5
  52. package/src/blocks/Heading/block.ts +23 -20
  53. package/src/blocks/ListItem/BulletListItem/block.ts +2 -2
  54. package/src/blocks/ListItem/CheckListItem/block.ts +2 -2
  55. package/src/blocks/ListItem/NumberedListItem/block.ts +3 -3
  56. package/src/blocks/ListItem/ToggleListItem/block.ts +2 -2
  57. package/src/blocks/PageBreak/getPageBreakSlashMenuItems.ts +2 -2
  58. package/src/blocks/Paragraph/block.ts +2 -2
  59. package/src/blocks/Quote/block.ts +2 -2
  60. package/src/blocks/Table/block.ts +4 -3
  61. package/src/blocks/ToggleWrapper/createToggleWrapper.ts +2 -1
  62. package/src/comments/extension.ts +353 -0
  63. package/src/comments/index.ts +2 -1
  64. package/src/comments/types.ts +8 -0
  65. package/src/{extensions/Comments → comments}/userstore/UserStore.ts +2 -2
  66. package/src/editor/BlockNoteEditor.test.ts +2 -23
  67. package/src/editor/BlockNoteEditor.ts +66 -453
  68. package/src/editor/BlockNoteExtension.test.ts +103 -0
  69. package/src/editor/BlockNoteExtension.ts +174 -56
  70. package/src/editor/managers/EventManager.ts +64 -35
  71. package/src/editor/managers/ExtensionManager/extensions.ts +214 -0
  72. package/src/editor/managers/ExtensionManager/index.ts +514 -0
  73. package/src/editor/managers/ExtensionManager/symbol.ts +6 -0
  74. package/src/editor/managers/SelectionManager.ts +5 -1
  75. package/src/editor/managers/StateManager.ts +29 -17
  76. package/src/editor/managers/index.ts +1 -5
  77. package/src/extensions/BlockChange/{BlockChangePlugin.ts → BlockChange.ts} +27 -29
  78. package/src/extensions/Collaboration/{ForkYDocPlugin.test.ts → ForkYDoc.test.ts} +6 -5
  79. package/src/extensions/Collaboration/ForkYDoc.ts +158 -0
  80. package/src/extensions/Collaboration/YCursorPlugin.ts +183 -0
  81. package/src/extensions/Collaboration/YSync.ts +16 -0
  82. package/src/extensions/Collaboration/YUndo.ts +12 -0
  83. package/src/extensions/Collaboration/schemaMigration/SchemaMigration.ts +59 -0
  84. package/src/extensions/DropCursor/DropCursor.ts +26 -0
  85. package/src/extensions/FilePanel/FilePanel.ts +41 -0
  86. package/src/extensions/FormattingToolbar/FormattingToolbar.ts +119 -0
  87. package/src/extensions/History/History.ts +11 -0
  88. package/src/extensions/LinkToolbar/LinkToolbar.ts +121 -0
  89. package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboard.ts +74 -0
  90. package/src/extensions/Placeholder/Placeholder.ts +148 -0
  91. package/src/extensions/PreviousBlockType/{PreviousBlockTypePlugin.ts → PreviousBlockType.ts} +9 -13
  92. package/src/extensions/ShowSelection/{ShowSelectionPlugin.ts → ShowSelection.ts} +27 -33
  93. package/src/extensions/SideMenu/{SideMenuPlugin.ts → SideMenu.ts} +63 -83
  94. package/src/extensions/SuggestionMenu/{SuggestionPlugin.ts → SuggestionMenu.ts} +71 -77
  95. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +29 -44
  96. package/src/extensions/TableHandles/{TableHandlesPlugin.ts → TableHandles.ts} +416 -437
  97. package/src/extensions/TrailingNode/{TrailingNodeExtension.ts → TrailingNode.ts} +8 -17
  98. package/src/extensions/index.ts +24 -0
  99. package/src/extensions/{BackgroundColor → tiptap-extensions/BackgroundColor}/BackgroundColorExtension.ts +1 -1
  100. package/src/extensions/{KeyboardShortcuts → tiptap-extensions/KeyboardShortcuts}/KeyboardShortcutsExtension.ts +21 -16
  101. package/src/extensions/{TextColor → tiptap-extensions/TextColor}/TextColorExtension.ts +1 -1
  102. package/src/extensions/tiptap-extensions/index.ts +31 -0
  103. package/src/index.ts +1 -13
  104. package/src/schema/blocks/createSpec.ts +14 -11
  105. package/src/schema/blocks/internal.ts +2 -2
  106. package/src/schema/blocks/types.ts +8 -5
  107. package/src/schema/schema.ts +11 -36
  108. package/src/util/topo-sort.ts +46 -0
  109. package/types/src/comments/extension.d.ts +70 -0
  110. package/types/src/comments/index.d.ts +2 -1
  111. package/types/src/comments/types.d.ts +8 -0
  112. package/types/src/{extensions/Comments → comments}/userstore/UserStore.d.ts +2 -2
  113. package/types/src/editor/BlockNoteEditor.d.ts +34 -105
  114. package/types/src/editor/BlockNoteExtension.d.ts +87 -22
  115. package/types/src/editor/managers/EventManager.d.ts +25 -16
  116. package/types/src/editor/managers/ExtensionManager/extensions.d.ts +8 -0
  117. package/types/src/editor/managers/ExtensionManager/index.d.ts +83 -0
  118. package/types/src/editor/managers/ExtensionManager/symbol.d.ts +5 -0
  119. package/types/src/editor/managers/StateManager.d.ts +1 -12
  120. package/types/src/editor/managers/index.d.ts +1 -2
  121. package/types/src/extensions/BlockChange/BlockChange.d.ts +16 -0
  122. package/types/src/extensions/Collaboration/ForkYDoc.d.ts +34 -0
  123. package/types/src/extensions/Collaboration/ForkYDoc.test.d.ts +1 -0
  124. package/types/src/extensions/Collaboration/YCursorPlugin.d.ts +24 -0
  125. package/types/src/extensions/Collaboration/YSync.d.ts +8 -0
  126. package/types/src/extensions/Collaboration/YUndo.d.ts +12 -0
  127. package/types/src/extensions/Collaboration/schemaMigration/SchemaMigration.d.ts +8 -0
  128. package/types/src/extensions/DropCursor/DropCursor.d.ts +5 -0
  129. package/types/src/extensions/FilePanel/FilePanel.d.ts +11 -0
  130. package/types/src/extensions/FormattingToolbar/FormattingToolbar.d.ts +9 -0
  131. package/types/src/extensions/History/History.d.ts +6 -0
  132. package/types/src/extensions/LinkToolbar/LinkToolbar.d.ts +24 -0
  133. package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboard.d.ts +5 -0
  134. package/types/src/extensions/Placeholder/Placeholder.d.ts +6 -0
  135. package/types/src/extensions/PreviousBlockType/{PreviousBlockTypePlugin.d.ts → PreviousBlockType.d.ts} +9 -5
  136. package/types/src/extensions/ShowSelection/ShowSelection.d.ts +21 -0
  137. package/types/src/extensions/SideMenu/{SideMenuPlugin.d.ts → SideMenu.d.ts} +11 -15
  138. package/types/src/extensions/SuggestionMenu/SuggestionMenu.d.ts +54 -0
  139. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +1 -1
  140. package/types/src/extensions/TableHandles/{TableHandlesPlugin.d.ts → TableHandles.d.ts} +28 -31
  141. package/types/src/extensions/TrailingNode/TrailingNode.d.ts +8 -0
  142. package/types/src/extensions/index.d.ts +24 -0
  143. package/types/src/extensions/{KeyboardShortcuts → tiptap-extensions/KeyboardShortcuts}/KeyboardShortcutsExtension.d.ts +1 -1
  144. package/types/src/extensions/tiptap-extensions/index.d.ts +11 -0
  145. package/types/src/index.d.ts +1 -13
  146. package/types/src/schema/blocks/createSpec.d.ts +4 -4
  147. package/types/src/schema/blocks/internal.d.ts +2 -2
  148. package/types/src/schema/blocks/types.d.ts +5 -5
  149. package/types/src/util/topo-sort.d.ts +8 -0
  150. package/dist/BlockNoteSchema-Bi-eeHal.js.map +0 -1
  151. package/dist/BlockNoteSchema-DjDaA2C3.cjs +0 -6
  152. package/dist/BlockNoteSchema-DjDaA2C3.cjs.map +0 -1
  153. package/dist/blockToNode-DIfPWLH8.js.map +0 -1
  154. package/src/comments/models/User.ts +0 -8
  155. package/src/editor/BlockNoteExtensions.ts +0 -325
  156. package/src/editor/managers/CollaborationManager.ts +0 -212
  157. package/src/editor/managers/ExtensionManager.ts +0 -130
  158. package/src/extensions/Collaboration/CursorPlugin.ts +0 -189
  159. package/src/extensions/Collaboration/ForkYDocPlugin.ts +0 -192
  160. package/src/extensions/Collaboration/SyncPlugin.ts +0 -18
  161. package/src/extensions/Collaboration/UndoPlugin.ts +0 -18
  162. package/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.ts +0 -59
  163. package/src/extensions/Comments/CommentsPlugin.ts +0 -392
  164. package/src/extensions/FilePanel/FilePanelPlugin.ts +0 -206
  165. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +0 -363
  166. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +0 -380
  167. package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +0 -75
  168. package/src/extensions/Placeholder/PlaceholderPlugin.ts +0 -147
  169. package/types/src/comments/models/User.d.ts +0 -8
  170. package/types/src/editor/BlockNoteExtensions.d.ts +0 -43
  171. package/types/src/editor/managers/CollaborationManager.d.ts +0 -115
  172. package/types/src/editor/managers/ExtensionManager.d.ts +0 -68
  173. package/types/src/extensions/BlockChange/BlockChangePlugin.d.ts +0 -15
  174. package/types/src/extensions/Collaboration/CursorPlugin.d.ts +0 -37
  175. package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +0 -41
  176. package/types/src/extensions/Collaboration/SyncPlugin.d.ts +0 -7
  177. package/types/src/extensions/Collaboration/UndoPlugin.d.ts +0 -9
  178. package/types/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.d.ts +0 -7
  179. package/types/src/extensions/Comments/CommentsPlugin.d.ts +0 -66
  180. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +0 -31
  181. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +0 -41
  182. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +0 -42
  183. package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +0 -5
  184. package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +0 -6
  185. package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +0 -15
  186. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +0 -31
  187. package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +0 -13
  188. /package/src/{extensions/Comments/CommentMark.ts → comments/mark.ts} +0 -0
  189. /package/src/extensions/{HardBreak → tiptap-extensions/HardBreak}/HardBreak.ts +0 -0
  190. /package/src/extensions/{Suggestions → tiptap-extensions/Suggestions}/SuggestionMarks.ts +0 -0
  191. /package/src/extensions/{TextAlignment → tiptap-extensions/TextAlignment}/TextAlignmentExtension.ts +0 -0
  192. /package/src/extensions/{UniqueID → tiptap-extensions/UniqueID}/UniqueID.ts +0 -0
  193. /package/types/src/{extensions/Comments/CommentMark.d.ts → comments/mark.d.ts} +0 -0
  194. /package/types/src/{extensions/Collaboration/ForkYDocPlugin.test.d.ts → editor/BlockNoteExtension.test.d.ts} +0 -0
  195. /package/types/src/extensions/{BackgroundColor → tiptap-extensions/BackgroundColor}/BackgroundColorExtension.d.ts +0 -0
  196. /package/types/src/extensions/{HardBreak → tiptap-extensions/HardBreak}/HardBreak.d.ts +0 -0
  197. /package/types/src/extensions/{Suggestions → tiptap-extensions/Suggestions}/SuggestionMarks.d.ts +0 -0
  198. /package/types/src/extensions/{TextAlignment → tiptap-extensions/TextAlignment}/TextAlignmentExtension.d.ts +0 -0
  199. /package/types/src/extensions/{TextColor → tiptap-extensions/TextColor}/TextColorExtension.d.ts +0 -0
  200. /package/types/src/extensions/{UniqueID → tiptap-extensions/UniqueID}/UniqueID.d.ts +0 -0
@@ -0,0 +1,353 @@
1
+ import { Node } from "prosemirror-model";
2
+ import { Plugin, PluginKey } from "prosemirror-state";
3
+ import { Decoration, DecorationSet } from "prosemirror-view";
4
+ import { getRelativeSelection, ySyncPluginKey } from "y-prosemirror";
5
+ import {
6
+ createExtension,
7
+ createStore,
8
+ ExtensionOptions,
9
+ } from "../editor/BlockNoteExtension.js";
10
+ import { ShowSelectionExtension } from "../extensions/ShowSelection/ShowSelection.js";
11
+ import { CustomBlockNoteSchema } from "../schema/schema.js";
12
+ import { CommentMark } from "./mark.js";
13
+ import type { ThreadStore } from "./threadstore/ThreadStore.js";
14
+ import type { CommentBody, ThreadData } from "./types.js";
15
+ import { User } from "./types.js";
16
+ import { UserStore } from "./userstore/UserStore.js";
17
+
18
+ const PLUGIN_KEY = new PluginKey("blocknote-comments");
19
+
20
+ type CommentsPluginState = {
21
+ /**
22
+ * Decorations to be rendered, specifically to indicate the selected thread
23
+ */
24
+ decorations: DecorationSet;
25
+ };
26
+
27
+ /**
28
+ * Calculate the thread positions from the current document state
29
+ */
30
+ function getUpdatedThreadPositions(doc: Node, markType: string) {
31
+ const threadPositions = new Map<string, { from: number; to: number }>();
32
+
33
+ // find all thread marks and store their position + create decoration for selected thread
34
+ doc.descendants((node, pos) => {
35
+ node.marks.forEach((mark) => {
36
+ if (mark.type.name === markType) {
37
+ const thisThreadId = (mark.attrs as { threadId: string | undefined })
38
+ .threadId;
39
+ if (!thisThreadId) {
40
+ return;
41
+ }
42
+ const from = pos;
43
+ const to = from + node.nodeSize;
44
+
45
+ // FloatingThreads component uses "to" as the position, so always store the largest "to" found
46
+ // AnchoredThreads component uses "from" as the position, so always store the smallest "from" found
47
+ const currentPosition = threadPositions.get(thisThreadId) ?? {
48
+ from: Infinity,
49
+ to: 0,
50
+ };
51
+ threadPositions.set(thisThreadId, {
52
+ from: Math.min(from, currentPosition.from),
53
+ to: Math.max(to, currentPosition.to),
54
+ });
55
+ }
56
+ });
57
+ });
58
+ return threadPositions;
59
+ }
60
+
61
+ export const CommentsExtension = createExtension(
62
+ ({
63
+ editor,
64
+ options: { schema: commentEditorSchema, threadStore, resolveUsers },
65
+ }: ExtensionOptions<{
66
+ /**
67
+ * The thread store implementation to use for storing and retrieving comment threads
68
+ */
69
+ threadStore: ThreadStore;
70
+ /**
71
+ * Resolve user information for comments.
72
+ *
73
+ * See [Comments](https://www.blocknotejs.org/docs/features/collaboration/comments) for more info.
74
+ */
75
+ resolveUsers: (userIds: string[]) => Promise<User[]>;
76
+ /**
77
+ * A schema to use for the comment editor (which allows you to customize the blocks and styles that are available in the comment editor)
78
+ */
79
+ schema?: CustomBlockNoteSchema<any, any, any>;
80
+ }>) => {
81
+ if (!resolveUsers) {
82
+ throw new Error(
83
+ "resolveUsers is required to be defined when using comments",
84
+ );
85
+ }
86
+ if (!threadStore) {
87
+ throw new Error(
88
+ "threadStore is required to be defined when using comments",
89
+ );
90
+ }
91
+ const markType = CommentMark.name;
92
+
93
+ const userStore = new UserStore<User>(resolveUsers);
94
+ const store = createStore(
95
+ {
96
+ pendingComment: false,
97
+ selectedThreadId: undefined as string | undefined,
98
+ threadPositions: new Map<string, { from: number; to: number }>(),
99
+ },
100
+ {
101
+ onUpdate() {
102
+ // If the selected thread id changed, we need to update the decorations
103
+ if (
104
+ store.state.selectedThreadId !== store.prevState.selectedThreadId
105
+ ) {
106
+ // So, we issue a transaction to update the decorations
107
+ editor.transact((tr) => tr.setMeta(PLUGIN_KEY, true));
108
+ }
109
+ },
110
+ },
111
+ );
112
+
113
+ const updateMarksFromThreads = (threads: Map<string, ThreadData>) => {
114
+ editor.transact((tr) => {
115
+ tr.doc.descendants((node, pos) => {
116
+ node.marks.forEach((mark) => {
117
+ if (mark.type.name === markType) {
118
+ const markTypeInstance = mark.type;
119
+ const markThreadId = mark.attrs.threadId as string;
120
+ const thread = threads.get(markThreadId);
121
+ const isOrphan = !!(
122
+ !thread ||
123
+ thread.resolved ||
124
+ thread.deletedAt
125
+ );
126
+
127
+ if (isOrphan !== mark.attrs.orphan) {
128
+ const trimmedFrom = Math.max(pos, 0);
129
+ const trimmedTo = Math.min(
130
+ pos + node.nodeSize,
131
+ tr.doc.content.size - 1,
132
+ tr.doc.content.size - 1,
133
+ );
134
+ tr.removeMark(trimmedFrom, trimmedTo, mark);
135
+ tr.addMark(
136
+ trimmedFrom,
137
+ trimmedTo,
138
+ markTypeInstance.create({
139
+ ...mark.attrs,
140
+ orphan: isOrphan,
141
+ }),
142
+ );
143
+
144
+ if (isOrphan && store.state.selectedThreadId === markThreadId) {
145
+ // unselect
146
+ store.setState((prev) => ({
147
+ ...prev,
148
+ selectedThreadId: undefined,
149
+ }));
150
+ }
151
+ }
152
+ }
153
+ });
154
+ });
155
+ });
156
+ };
157
+
158
+ return {
159
+ key: "comments",
160
+ store,
161
+ prosemirrorPlugins: [
162
+ new Plugin<CommentsPluginState>({
163
+ key: PLUGIN_KEY,
164
+ state: {
165
+ init() {
166
+ return {
167
+ decorations: DecorationSet.empty,
168
+ };
169
+ },
170
+ apply(tr, state) {
171
+ const action = tr.getMeta(PLUGIN_KEY);
172
+
173
+ if (!tr.docChanged && !action) {
174
+ return state;
175
+ }
176
+
177
+ // only update threadPositions if the doc changed
178
+ const newThreadPositions = tr.docChanged
179
+ ? getUpdatedThreadPositions(tr.doc, markType)
180
+ : store.state.threadPositions;
181
+
182
+ if (
183
+ newThreadPositions.size > 0 ||
184
+ store.state.threadPositions.size > 0
185
+ ) {
186
+ // small optimization; don't emit event if threadPositions before / after were both empty
187
+ store.setState((prev) => ({
188
+ ...prev,
189
+ threadPositions: newThreadPositions,
190
+ }));
191
+ }
192
+
193
+ // update decorations if doc or selected thread changed
194
+ const decorations = [] as any[];
195
+
196
+ if (store.state.selectedThreadId) {
197
+ const selectedThreadPosition = newThreadPositions.get(
198
+ store.state.selectedThreadId,
199
+ );
200
+
201
+ if (selectedThreadPosition) {
202
+ decorations.push(
203
+ Decoration.inline(
204
+ selectedThreadPosition.from,
205
+ selectedThreadPosition.to,
206
+ {
207
+ class: "bn-thread-mark-selected",
208
+ },
209
+ ),
210
+ );
211
+ }
212
+ }
213
+
214
+ return {
215
+ decorations: DecorationSet.create(tr.doc, decorations),
216
+ };
217
+ },
218
+ },
219
+ props: {
220
+ decorations(state) {
221
+ return (
222
+ PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty
223
+ );
224
+ },
225
+ handleClick: (view, pos, event) => {
226
+ if (event.button !== 0) {
227
+ return;
228
+ }
229
+
230
+ const node = view.state.doc.nodeAt(pos);
231
+
232
+ if (!node) {
233
+ // unselect
234
+ store.setState((prev) => ({
235
+ ...prev,
236
+ selectedThreadId: undefined,
237
+ }));
238
+ return;
239
+ }
240
+
241
+ const commentMark = node.marks.find(
242
+ (mark) =>
243
+ mark.type.name === markType && mark.attrs.orphan !== true,
244
+ );
245
+
246
+ const threadId = commentMark?.attrs.threadId as
247
+ | string
248
+ | undefined;
249
+ if (threadId !== store.state.selectedThreadId) {
250
+ store.setState((prev) => ({
251
+ ...prev,
252
+ selectedThreadId: threadId,
253
+ }));
254
+ }
255
+ },
256
+ },
257
+ }),
258
+ ],
259
+ threadStore: threadStore,
260
+ mount() {
261
+ const unsubscribe = threadStore.subscribe(updateMarksFromThreads);
262
+ updateMarksFromThreads(threadStore.getThreads());
263
+
264
+ const unsubscribeOnSelectionChange = editor.onSelectionChange(() => {
265
+ if (store.state.pendingComment) {
266
+ store.setState((prev) => ({
267
+ ...prev,
268
+ pendingComment: false,
269
+ }));
270
+ }
271
+ });
272
+
273
+ return () => {
274
+ unsubscribe();
275
+ unsubscribeOnSelectionChange();
276
+ };
277
+ },
278
+ selectThread(threadId: string | undefined, scrollToThread = true) {
279
+ if (store.state.selectedThreadId === threadId) {
280
+ return;
281
+ }
282
+ store.setState((prev) => ({
283
+ ...prev,
284
+ pendingComment: false,
285
+ selectedThreadId: threadId,
286
+ }));
287
+
288
+ if (threadId && scrollToThread) {
289
+ const selectedThreadPosition =
290
+ store.state.threadPositions.get(threadId);
291
+ if (!selectedThreadPosition) {
292
+ return;
293
+ }
294
+ (
295
+ editor.prosemirrorView?.domAtPos(selectedThreadPosition.from)
296
+ .node as Element | undefined
297
+ )?.scrollIntoView({
298
+ behavior: "smooth",
299
+ block: "center",
300
+ });
301
+ }
302
+ },
303
+ startPendingComment() {
304
+ store.setState((prev) => ({
305
+ ...prev,
306
+ selectedThreadId: undefined,
307
+ pendingComment: true,
308
+ }));
309
+ editor.getExtension(ShowSelectionExtension)?.showSelection(true);
310
+ },
311
+ stopPendingComment() {
312
+ store.setState((prev) => ({
313
+ ...prev,
314
+ selectedThreadId: undefined,
315
+ pendingComment: false,
316
+ }));
317
+ editor.getExtension(ShowSelectionExtension)?.showSelection(false);
318
+ },
319
+ async createThread(options: {
320
+ initialComment: { body: CommentBody; metadata?: any };
321
+ metadata?: any;
322
+ }) {
323
+ const thread = await threadStore.createThread(options);
324
+ if (threadStore.addThreadToDocument) {
325
+ const view = editor.prosemirrorView!;
326
+ const pmSelection = view.state.selection;
327
+ const ystate = ySyncPluginKey.getState(view.state);
328
+ const selection = {
329
+ prosemirror: {
330
+ head: pmSelection.head,
331
+ anchor: pmSelection.anchor,
332
+ },
333
+ yjs: ystate
334
+ ? getRelativeSelection(ystate.binding, view.state)
335
+ : undefined,
336
+ };
337
+ await threadStore.addThreadToDocument({
338
+ threadId: thread.id,
339
+ selection,
340
+ });
341
+ } else {
342
+ (editor as any)._tiptapEditor.commands.setMark(markType, {
343
+ orphan: false,
344
+ threadId: thread.id,
345
+ });
346
+ }
347
+ },
348
+ userStore,
349
+ commentEditorSchema,
350
+ tiptapExtensions: [CommentMark],
351
+ } as const;
352
+ },
353
+ );
@@ -1,4 +1,5 @@
1
- export * from "./models/User.js";
1
+ export * from "./extension.js";
2
+ export * from "./mark.js";
2
3
  export * from "./threadstore/DefaultThreadStoreAuth.js";
3
4
  export * from "./threadstore/ThreadStore.js";
4
5
  export * from "./threadstore/ThreadStoreAuth.js";
@@ -119,3 +119,11 @@ export type ThreadData = {
119
119
  */
120
120
  deletedAt?: Date;
121
121
  };
122
+ /**
123
+ * A collaborator of the document.
124
+ */
125
+ export type User = {
126
+ id: string;
127
+ username: string;
128
+ avatarUrl: string;
129
+ };
@@ -1,5 +1,5 @@
1
- import type { User } from "../../../comments/index.js";
2
- import { EventEmitter } from "../../../util/EventEmitter.js";
1
+ import type { User } from "../types.js";
2
+ import { EventEmitter } from "../../util/EventEmitter.js";
3
3
 
4
4
  /**
5
5
  * The `UserStore` is used to retrieve and cache information about users.
@@ -1,11 +1,11 @@
1
1
  import { expect, it } from "vitest";
2
+ import * as Y from "yjs";
3
+
2
4
  import {
3
5
  getBlockInfo,
4
6
  getNearestBlockPos,
5
7
  } from "../api/getBlockInfoFromPos.js";
6
8
  import { BlockNoteEditor } from "./BlockNoteEditor.js";
7
- import { BlockNoteExtension } from "./BlockNoteExtension.js";
8
- import * as Y from "yjs";
9
9
 
10
10
  /**
11
11
  * @vitest-environment jsdom
@@ -127,27 +127,6 @@ it("onMount and onUnmount", async () => {
127
127
  expect(unmounted).toBe(true);
128
128
  });
129
129
 
130
- it("onCreate event", () => {
131
- let created = false;
132
- BlockNoteEditor.create({
133
- extensions: [
134
- (e) =>
135
- new (class extends BlockNoteExtension {
136
- public static key() {
137
- return "test";
138
- }
139
- constructor(editor: BlockNoteEditor) {
140
- super(editor);
141
- editor.onCreate(() => {
142
- created = true;
143
- });
144
- }
145
- })(e),
146
- ],
147
- });
148
- expect(created).toBe(true);
149
- });
150
-
151
130
  it("sets an initial block id when using Y.js", async () => {
152
131
  const doc = new Y.Doc();
153
132
  const fragment = doc.getXmlFragment("doc");