@blocknote/core 0.11.2 → 0.12.1

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 (138) hide show
  1. package/README.md +13 -17
  2. package/dist/blocknote.js +1662 -1447
  3. package/dist/blocknote.js.map +1 -1
  4. package/dist/blocknote.umd.cjs +6 -6
  5. package/dist/blocknote.umd.cjs.map +1 -1
  6. package/dist/style.css +1 -1
  7. package/dist/webpack-stats.json +1 -1
  8. package/package.json +7 -3
  9. package/src/api/blockManipulation/blockManipulation.test.ts +19 -15
  10. package/src/api/blockManipulation/blockManipulation.ts +107 -17
  11. package/src/api/exporters/html/externalHTMLExporter.ts +3 -7
  12. package/src/api/exporters/html/htmlConversion.test.ts +6 -3
  13. package/src/api/exporters/html/internalHTMLSerializer.ts +3 -7
  14. package/src/api/exporters/html/util/sharedHTMLConversion.ts +3 -3
  15. package/src/api/exporters/markdown/markdownExporter.test.ts +7 -3
  16. package/src/api/exporters/markdown/markdownExporter.ts +2 -6
  17. package/src/api/getCurrentBlockContentType.ts +14 -0
  18. package/src/api/nodeConversions/nodeConversions.test.ts +14 -7
  19. package/src/api/nodeConversions/nodeConversions.ts +1 -2
  20. package/src/api/parsers/html/parseHTML.test.ts +5 -1
  21. package/src/api/parsers/html/parseHTML.ts +2 -6
  22. package/src/api/parsers/html/util/nestedLists.ts +11 -1
  23. package/src/api/parsers/markdown/parseMarkdown.test.ts +3 -0
  24. package/src/api/parsers/markdown/parseMarkdown.ts +2 -6
  25. package/src/api/testUtil/cases/customBlocks.ts +18 -16
  26. package/src/api/testUtil/cases/customInlineContent.ts +12 -13
  27. package/src/api/testUtil/cases/customStyles.ts +12 -10
  28. package/src/api/testUtil/index.ts +4 -2
  29. package/src/api/testUtil/partialBlockTestUtil.ts +2 -6
  30. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +50 -21
  31. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +1 -2
  32. package/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +8 -1
  33. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +18 -5
  34. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +7 -1
  35. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +18 -5
  36. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +14 -5
  37. package/src/blocks/defaultBlockHelpers.ts +3 -3
  38. package/src/blocks/defaultBlockTypeGuards.ts +84 -0
  39. package/src/blocks/defaultBlocks.ts +29 -3
  40. package/src/editor/Block.css +2 -31
  41. package/src/editor/BlockNoteEditor.ts +223 -267
  42. package/src/editor/BlockNoteExtensions.ts +5 -2
  43. package/src/editor/BlockNoteSchema.ts +98 -0
  44. package/src/editor/BlockNoteTipTapEditor.ts +162 -0
  45. package/src/editor/cursorPositionTypes.ts +2 -6
  46. package/src/editor/editor.css +0 -1
  47. package/src/editor/selectionTypes.ts +2 -6
  48. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +22 -29
  49. package/src/extensions/{ImageToolbar → ImagePanel}/ImageToolbarPlugin.ts +54 -60
  50. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +330 -0
  51. package/src/extensions/Placeholder/PlaceholderExtension.ts +81 -88
  52. package/src/extensions/SideMenu/SideMenuPlugin.ts +55 -56
  53. package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +8 -0
  54. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +353 -0
  55. package/src/extensions/{SlashMenu/defaultSlashMenuItems.ts → SuggestionMenu/getDefaultSlashMenuItems.ts} +119 -89
  56. package/src/extensions/TableHandles/TableHandlesPlugin.ts +62 -45
  57. package/src/extensions-shared/UiElementPosition.ts +4 -0
  58. package/src/index.ts +8 -8
  59. package/src/pm-nodes/BlockContainer.ts +5 -5
  60. package/src/schema/blocks/types.ts +15 -15
  61. package/src/schema/inlineContent/createSpec.ts +2 -2
  62. package/src/schema/inlineContent/types.ts +1 -1
  63. package/src/util/browser.ts +6 -4
  64. package/src/util/typescript.ts +7 -4
  65. package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -1
  66. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +2 -1
  67. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +2 -1
  68. package/types/src/api/exporters/markdown/markdownExporter.d.ts +2 -1
  69. package/types/src/api/getCurrentBlockContentType.d.ts +2 -0
  70. package/types/src/api/nodeConversions/nodeConversions.d.ts +2 -1
  71. package/types/src/api/parsers/html/parseHTML.d.ts +2 -1
  72. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -1
  73. package/types/src/api/testUtil/cases/customBlocks.d.ts +72 -13
  74. package/types/src/api/testUtil/cases/customInlineContent.d.ts +281 -6
  75. package/types/src/api/testUtil/cases/customStyles.d.ts +247 -13
  76. package/types/src/api/testUtil/index.d.ts +4 -2
  77. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +2 -1
  78. package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +6 -1
  79. package/types/src/blocks/defaultBlockHelpers.d.ts +2 -2
  80. package/types/src/blocks/defaultBlockTypeGuards.d.ts +24 -0
  81. package/types/src/blocks/defaultBlocks.d.ts +21 -15
  82. package/types/src/editor/BlockNoteEditor.d.ts +51 -56
  83. package/types/src/editor/BlockNoteExtensions.d.ts +1 -0
  84. package/types/src/editor/BlockNoteSchema.d.ts +34 -0
  85. package/types/src/editor/BlockNoteTipTapEditor.d.ts +28 -0
  86. package/types/src/editor/cursorPositionTypes.d.ts +2 -1
  87. package/types/src/editor/selectionTypes.d.ts +2 -1
  88. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -6
  89. package/types/src/extensions/ImagePanel/ImageToolbarPlugin.d.ts +32 -0
  90. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +40 -0
  91. package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +2 -15
  92. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +8 -7
  93. package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +8 -0
  94. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +31 -0
  95. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +10 -0
  96. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +7 -7
  97. package/types/src/extensions-shared/UiElementPosition.d.ts +4 -0
  98. package/types/src/index.d.ts +8 -8
  99. package/types/src/pm-nodes/BlockContainer.d.ts +3 -2
  100. package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
  101. package/types/src/schema/blocks/types.d.ts +15 -15
  102. package/types/src/schema/inlineContent/types.d.ts +1 -1
  103. package/types/src/util/browser.d.ts +1 -0
  104. package/types/src/util/typescript.d.ts +1 -0
  105. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +0 -335
  106. package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +0 -12
  107. package/src/extensions/SlashMenu/SlashMenuPlugin.ts +0 -53
  108. package/src/extensions-shared/BaseUiElementTypes.ts +0 -8
  109. package/src/extensions-shared/README.md +0 -3
  110. package/src/extensions-shared/suggestion/SuggestionItem.ts +0 -3
  111. package/src/extensions-shared/suggestion/SuggestionPlugin.ts +0 -448
  112. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +0 -38
  113. package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +0 -31
  114. package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +0 -7
  115. package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +0 -13
  116. package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +0 -3
  117. package/types/src/extensions-shared/BaseUiElementTypes.d.ts +0 -7
  118. package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +0 -3
  119. package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +0 -36
  120. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff +0 -0
  121. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
  122. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff +0 -0
  123. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
  124. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff +0 -0
  125. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
  126. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff +0 -0
  127. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
  128. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff +0 -0
  129. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
  130. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff +0 -0
  131. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
  132. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff +0 -0
  133. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
  134. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff +0 -0
  135. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
  136. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
  137. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
  138. /package/src/{assets/fonts-inter.css → fonts/inter.css} +0 -0
@@ -1,448 +0,0 @@
1
- import { findParentNode } from "@tiptap/core";
2
- import { EditorState, Plugin, PluginKey } from "prosemirror-state";
3
- import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
4
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
5
- import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
6
- import { BaseUiElementState } from "../BaseUiElementTypes";
7
- import { SuggestionItem } from "./SuggestionItem";
8
-
9
- const findBlock = findParentNode((node) => node.type.name === "blockContainer");
10
-
11
- export type SuggestionsMenuState<T extends SuggestionItem> =
12
- BaseUiElementState & {
13
- // The suggested items to display.
14
- filteredItems: T[];
15
- // The index of the suggested item that's currently hovered by the keyboard.
16
- keyboardHoveredItemIndex: number;
17
- };
18
-
19
- class SuggestionsMenuView<
20
- T extends SuggestionItem,
21
- BSchema extends BlockSchema,
22
- I extends InlineContentSchema,
23
- S extends StyleSchema
24
- > {
25
- private suggestionsMenuState?: SuggestionsMenuState<T>;
26
- public updateSuggestionsMenu: () => void;
27
-
28
- pluginState: SuggestionPluginState<T>;
29
-
30
- constructor(
31
- private readonly editor: BlockNoteEditor<BSchema, I, S>,
32
- private readonly pluginKey: PluginKey,
33
- updateSuggestionsMenu: (
34
- suggestionsMenuState: SuggestionsMenuState<T>
35
- ) => void = () => {
36
- // noop
37
- }
38
- ) {
39
- this.pluginState = getDefaultPluginState<T>();
40
-
41
- this.updateSuggestionsMenu = () => {
42
- if (!this.suggestionsMenuState) {
43
- throw new Error("Attempting to update uninitialized suggestions menu");
44
- }
45
-
46
- updateSuggestionsMenu(this.suggestionsMenuState);
47
- };
48
-
49
- document.addEventListener("scroll", this.handleScroll);
50
- }
51
-
52
- handleScroll = () => {
53
- if (this.suggestionsMenuState?.show) {
54
- const decorationNode = document.querySelector(
55
- `[data-decoration-id="${this.pluginState.decorationId}"]`
56
- );
57
- this.suggestionsMenuState.referencePos =
58
- decorationNode!.getBoundingClientRect();
59
- this.updateSuggestionsMenu();
60
- }
61
- };
62
-
63
- update(view: EditorView, prevState: EditorState) {
64
- const prev = this.pluginKey.getState(prevState);
65
- const next = this.pluginKey.getState(view.state);
66
-
67
- // See how the state changed
68
- const started = !prev.active && next.active;
69
- const stopped = prev.active && !next.active;
70
- // TODO: Currently also true for cases in which an update isn't needed so selected list item index updates still
71
- // cause the view to update. May need to be more strict.
72
- const changed = prev.active && next.active;
73
-
74
- // Cancel when suggestion isn't active
75
- if (!started && !changed && !stopped) {
76
- return;
77
- }
78
-
79
- this.pluginState = stopped ? prev : next;
80
-
81
- if (stopped || !this.editor.isEditable) {
82
- this.suggestionsMenuState!.show = false;
83
- this.updateSuggestionsMenu();
84
-
85
- return;
86
- }
87
-
88
- const decorationNode = document.querySelector(
89
- `[data-decoration-id="${this.pluginState.decorationId}"]`
90
- );
91
-
92
- if (this.editor.isEditable) {
93
- this.suggestionsMenuState = {
94
- show: true,
95
- referencePos: decorationNode!.getBoundingClientRect(),
96
- filteredItems: this.pluginState.items,
97
- keyboardHoveredItemIndex: this.pluginState.keyboardHoveredItemIndex!,
98
- };
99
-
100
- this.updateSuggestionsMenu();
101
- }
102
- }
103
-
104
- destroy() {
105
- document.removeEventListener("scroll", this.handleScroll);
106
- }
107
- }
108
-
109
- type SuggestionPluginState<T extends SuggestionItem> = {
110
- // True when the menu is shown, false when hidden.
111
- active: boolean;
112
- // The character that triggered the menu being shown. Allowing the trigger to be different to the default
113
- // trigger allows other extensions to open it programmatically.
114
- triggerCharacter: string | undefined;
115
- // The editor position just after the trigger character, i.e. where the user query begins. Used to figure out
116
- // which menu items to show and can also be used to delete the trigger character.
117
- queryStartPos: number | undefined;
118
- // The items that should be shown in the menu.
119
- items: T[];
120
- // The index of the item in the menu that's currently hovered using the keyboard.
121
- keyboardHoveredItemIndex: number | undefined;
122
- // The number of characters typed after the last query that matched with at least 1 item. Used to close the
123
- // menu if the user keeps entering queries that don't return any results.
124
- notFoundCount: number | undefined;
125
- decorationId: string | undefined;
126
- };
127
-
128
- function getDefaultPluginState<
129
- T extends SuggestionItem
130
- >(): SuggestionPluginState<T> {
131
- return {
132
- active: false,
133
- triggerCharacter: undefined,
134
- queryStartPos: undefined,
135
- items: [] as T[],
136
- keyboardHoveredItemIndex: undefined,
137
- notFoundCount: 0,
138
- decorationId: undefined,
139
- };
140
- }
141
-
142
- /**
143
- * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.
144
- *
145
- * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.
146
- *
147
- * This version is adapted from the aforementioned version in the following ways:
148
- * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)
149
- * - This version hides some unnecessary complexity from the user of the plugin.
150
- * - This version handles key events differently
151
- */
152
- export const setupSuggestionsMenu = <
153
- T extends SuggestionItem,
154
- BSchema extends BlockSchema,
155
- I extends InlineContentSchema,
156
- S extends StyleSchema
157
- >(
158
- editor: BlockNoteEditor<BSchema, I, S>,
159
- updateSuggestionsMenu: (
160
- suggestionsMenuState: SuggestionsMenuState<T>
161
- ) => void,
162
-
163
- pluginKey: PluginKey,
164
- defaultTriggerCharacter: string,
165
- items: (query: string) => T[] = () => [],
166
- onSelectItem: (props: {
167
- item: T;
168
- editor: BlockNoteEditor<BSchema, I, S>;
169
- }) => void = () => {
170
- // noop
171
- }
172
- ) => {
173
- // Assertions
174
- if (defaultTriggerCharacter.length !== 1) {
175
- throw new Error("'char' should be a single character");
176
- }
177
-
178
- let suggestionsPluginView: SuggestionsMenuView<T, BSchema, I, S>;
179
-
180
- const deactivate = (view: EditorView) => {
181
- view.dispatch(view.state.tr.setMeta(pluginKey, { deactivate: true }));
182
- };
183
-
184
- return {
185
- plugin: new Plugin({
186
- key: pluginKey,
187
-
188
- view: () => {
189
- suggestionsPluginView = new SuggestionsMenuView<T, BSchema, I, S>(
190
- editor,
191
- pluginKey,
192
-
193
- updateSuggestionsMenu
194
- );
195
- return suggestionsPluginView;
196
- },
197
-
198
- state: {
199
- // Initialize the plugin's internal state.
200
- init(): SuggestionPluginState<T> {
201
- return getDefaultPluginState<T>();
202
- },
203
-
204
- // Apply changes to the plugin state from an editor transaction.
205
- apply(transaction, prev, oldState, newState): SuggestionPluginState<T> {
206
- // TODO: More clearly define which transactions should be ignored.
207
- if (transaction.getMeta("orderedListIndexing") !== undefined) {
208
- return prev;
209
- }
210
-
211
- // Checks if the menu should be shown.
212
- if (transaction.getMeta(pluginKey)?.activate) {
213
- return {
214
- active: true,
215
- triggerCharacter:
216
- transaction.getMeta(pluginKey)?.triggerCharacter || "",
217
- queryStartPos: newState.selection.from,
218
- items: items(""),
219
- keyboardHoveredItemIndex: 0,
220
- // TODO: Maybe should be 1 if the menu has no possible items? Probably redundant since a menu with no items
221
- // is useless in practice.
222
- notFoundCount: 0,
223
- decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,
224
- };
225
- }
226
-
227
- // Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.
228
- if (!prev.active) {
229
- return prev;
230
- }
231
-
232
- const next = { ...prev };
233
-
234
- // Updates which menu items to show by checking which items the current query (the text between the trigger
235
- // character and caret) matches with.
236
- next.items = items(
237
- newState.doc.textBetween(
238
- prev.queryStartPos!,
239
- newState.selection.from
240
- )
241
- );
242
-
243
- // Updates notFoundCount if the query doesn't match any items.
244
- next.notFoundCount = 0;
245
- if (next.items.length === 0) {
246
- // Checks how many characters were typed or deleted since the last transaction, and updates the notFoundCount
247
- // accordingly. Also ensures the notFoundCount does not become negative.
248
- next.notFoundCount = Math.max(
249
- 0,
250
- prev.notFoundCount! +
251
- (newState.selection.from - oldState.selection.from)
252
- );
253
- }
254
-
255
- // Hides the menu. This is done after items and notFoundCount are already updated as notFoundCount is needed to
256
- // check if the menu should be hidden.
257
- if (
258
- // Highlighting text should hide the menu.
259
- newState.selection.from !== newState.selection.to ||
260
- // Transactions with plugin metadata {deactivate: true} should hide the menu.
261
- transaction.getMeta(pluginKey)?.deactivate ||
262
- // Certain mouse events should hide the menu.
263
- // TODO: Change to global mousedown listener.
264
- transaction.getMeta("focus") ||
265
- transaction.getMeta("blur") ||
266
- transaction.getMeta("pointer") ||
267
- // Moving the caret before the character which triggered the menu should hide it.
268
- (prev.active && newState.selection.from < prev.queryStartPos!) ||
269
- // Entering more than 3 characters, after the last query that matched with at least 1 menu item, should hide
270
- // the menu.
271
- next.notFoundCount > 3
272
- ) {
273
- return getDefaultPluginState<T>();
274
- }
275
-
276
- // Updates keyboardHoveredItemIndex if the up or down arrow key was
277
- // pressed, or resets it if the keyboard cursor moved.
278
- if (
279
- transaction.getMeta(pluginKey)?.selectedItemIndexChanged !==
280
- undefined
281
- ) {
282
- let newIndex =
283
- transaction.getMeta(pluginKey).selectedItemIndexChanged;
284
-
285
- // Allows selection to jump between first and last items.
286
- if (newIndex < 0) {
287
- newIndex = prev.items.length - 1;
288
- } else if (newIndex >= prev.items.length) {
289
- newIndex = 0;
290
- }
291
-
292
- next.keyboardHoveredItemIndex = newIndex;
293
- } else if (oldState.selection.from !== newState.selection.from) {
294
- next.keyboardHoveredItemIndex = 0;
295
- }
296
-
297
- return next;
298
- },
299
- },
300
-
301
- props: {
302
- handleKeyDown(view, event) {
303
- const menuIsActive = (this as Plugin).getState(view.state).active;
304
-
305
- // Shows the menu if the default trigger character was pressed and the menu isn't active.
306
- if (event.key === defaultTriggerCharacter && !menuIsActive) {
307
- view.dispatch(
308
- view.state.tr
309
- .insertText(defaultTriggerCharacter)
310
- .scrollIntoView()
311
- .setMeta(pluginKey, {
312
- activate: true,
313
- triggerCharacter: defaultTriggerCharacter,
314
- })
315
- );
316
-
317
- return true;
318
- }
319
-
320
- // Doesn't handle other keystrokes if the menu isn't active.
321
- if (!menuIsActive) {
322
- return false;
323
- }
324
-
325
- // Handles keystrokes for navigating the menu.
326
- const {
327
- triggerCharacter,
328
- queryStartPos,
329
- items,
330
- keyboardHoveredItemIndex,
331
- } = pluginKey.getState(view.state);
332
-
333
- // Moves the keyboard selection to the previous item.
334
- if (event.key === "ArrowUp") {
335
- view.dispatch(
336
- view.state.tr.setMeta(pluginKey, {
337
- selectedItemIndexChanged: keyboardHoveredItemIndex - 1,
338
- })
339
- );
340
- return true;
341
- }
342
-
343
- // Moves the keyboard selection to the next item.
344
- if (event.key === "ArrowDown") {
345
- view.dispatch(
346
- view.state.tr.setMeta(pluginKey, {
347
- selectedItemIndexChanged: keyboardHoveredItemIndex + 1,
348
- })
349
- );
350
- return true;
351
- }
352
-
353
- // Selects an item and closes the menu.
354
- if (event.key === "Enter") {
355
- if (items.length === 0) {
356
- return true;
357
- }
358
-
359
- deactivate(view);
360
- editor._tiptapEditor
361
- .chain()
362
- .focus()
363
- .deleteRange({
364
- from: queryStartPos! - triggerCharacter!.length,
365
- to: editor._tiptapEditor.state.selection.from,
366
- })
367
- .run();
368
-
369
- onSelectItem({
370
- item: items[keyboardHoveredItemIndex],
371
- editor: editor,
372
- });
373
-
374
- return true;
375
- }
376
-
377
- // Closes the menu.
378
- if (event.key === "Escape") {
379
- deactivate(view);
380
- return true;
381
- }
382
-
383
- return false;
384
- },
385
-
386
- // Setup decorator on the currently active suggestion.
387
- decorations(state) {
388
- const { active, decorationId, queryStartPos, triggerCharacter } = (
389
- this as Plugin
390
- ).getState(state);
391
-
392
- if (!active) {
393
- return null;
394
- }
395
-
396
- // If the menu was opened programmatically by another extension, it may not use a trigger character. In this
397
- // case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.
398
- if (triggerCharacter === "") {
399
- const blockNode = findBlock(state.selection);
400
- if (blockNode) {
401
- return DecorationSet.create(state.doc, [
402
- Decoration.node(
403
- blockNode.pos,
404
- blockNode.pos + blockNode.node.nodeSize,
405
- {
406
- nodeName: "span",
407
- class: "bn-suggestion-decorator",
408
- "data-decoration-id": decorationId,
409
- }
410
- ),
411
- ]);
412
- }
413
- }
414
- // Creates an inline decoration around the trigger character.
415
- return DecorationSet.create(state.doc, [
416
- Decoration.inline(
417
- queryStartPos - triggerCharacter.length,
418
- queryStartPos,
419
- {
420
- nodeName: "span",
421
- class: "bn-suggestion-decorator",
422
- "data-decoration-id": decorationId,
423
- }
424
- ),
425
- ]);
426
- },
427
- },
428
- }),
429
- itemCallback: (item: T) => {
430
- deactivate(editor._tiptapEditor.view);
431
- editor._tiptapEditor
432
- .chain()
433
- .focus()
434
- .deleteRange({
435
- from:
436
- suggestionsPluginView.pluginState.queryStartPos! -
437
- suggestionsPluginView.pluginState.triggerCharacter!.length,
438
- to: editor._tiptapEditor.state.selection.from,
439
- })
440
- .run();
441
-
442
- onSelectItem({
443
- item: item,
444
- editor: editor,
445
- });
446
- },
447
- };
448
- };
@@ -1,38 +0,0 @@
1
- import { Plugin, PluginKey } from "prosemirror-state";
2
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
3
- import { BaseUiElementState } from "../../extensions-shared/BaseUiElementTypes";
4
- import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
5
- import { EventEmitter } from "../../util/EventEmitter";
6
- export type HyperlinkToolbarState = BaseUiElementState & {
7
- url: string;
8
- text: string;
9
- };
10
- export declare const hyperlinkToolbarPluginKey: PluginKey<any>;
11
- export declare class HyperlinkToolbarProsemirrorPlugin<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> extends EventEmitter<any> {
12
- private view;
13
- readonly plugin: Plugin;
14
- constructor(editor: BlockNoteEditor<BSchema, I, S>);
15
- onUpdate(callback: (state: HyperlinkToolbarState) => void): () => void;
16
- /**
17
- * Edit the currently hovered hyperlink.
18
- */
19
- editHyperlink: (url: string, text: string) => void;
20
- /**
21
- * Delete the currently hovered hyperlink.
22
- */
23
- deleteHyperlink: () => void;
24
- /**
25
- * When hovering on/off hyperlinks using the mouse cursor, the hyperlink
26
- * toolbar will open & close with a delay.
27
- *
28
- * This function starts the delay timer, and should be used for when the mouse cursor enters the hyperlink toolbar.
29
- */
30
- startHideTimer: () => void;
31
- /**
32
- * When hovering on/off hyperlinks using the mouse cursor, the hyperlink
33
- * toolbar will open & close with a delay.
34
- *
35
- * This function stops the delay timer, and should be used for when the mouse cursor exits the hyperlink toolbar.
36
- */
37
- stopHideTimer: () => void;
38
- }
@@ -1,31 +0,0 @@
1
- import { EditorState, Plugin, PluginKey } from "prosemirror-state";
2
- import { EditorView } from "prosemirror-view";
3
- import { EventEmitter } from "../../util/EventEmitter";
4
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
5
- import { BlockSchema, InlineContentSchema, SpecificBlock, StyleSchema } from "../../schema";
6
- import { BaseUiElementCallbacks, BaseUiElementState } from "../../extensions-shared/BaseUiElementTypes";
7
- export type ImageToolbarCallbacks = BaseUiElementCallbacks;
8
- export type ImageToolbarState<B extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema = StyleSchema> = BaseUiElementState & {
9
- block: SpecificBlock<B, "image", I, S>;
10
- };
11
- export declare class ImageToolbarView<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> {
12
- private readonly pluginKey;
13
- private readonly pmView;
14
- private imageToolbarState?;
15
- updateImageToolbar: () => void;
16
- prevWasEditable: boolean | null;
17
- constructor(pluginKey: PluginKey, pmView: EditorView, updateImageToolbar: (imageToolbarState: ImageToolbarState<BSchema, I, S>) => void);
18
- mouseDownHandler: () => void;
19
- dragstartHandler: () => void;
20
- blurHandler: (event: FocusEvent) => void;
21
- scrollHandler: () => void;
22
- update(view: EditorView, prevState: EditorState): void;
23
- destroy(): void;
24
- }
25
- export declare const imageToolbarPluginKey: PluginKey<any>;
26
- export declare class ImageToolbarProsemirrorPlugin<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> extends EventEmitter<any> {
27
- private view;
28
- readonly plugin: Plugin;
29
- constructor(_editor: BlockNoteEditor<BSchema, I, S>);
30
- onUpdate(callback: (state: ImageToolbarState<BSchema, I, S>) => void): () => void;
31
- }
@@ -1,7 +0,0 @@
1
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
2
- import { SuggestionItem } from "../../extensions-shared/suggestion/SuggestionItem";
3
- import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
4
- export type BaseSlashMenuItem<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> = SuggestionItem & {
5
- execute: (editor: BlockNoteEditor<BSchema, I, S>) => void;
6
- aliases?: string[];
7
- };
@@ -1,13 +0,0 @@
1
- import { Plugin, PluginKey } from "prosemirror-state";
2
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
3
- import { SuggestionsMenuState } from "../../extensions-shared/suggestion/SuggestionPlugin";
4
- import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
5
- import { EventEmitter } from "../../util/EventEmitter";
6
- import { BaseSlashMenuItem } from "./BaseSlashMenuItem";
7
- export declare const slashMenuPluginKey: PluginKey<any>;
8
- export declare class SlashMenuProsemirrorPlugin<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema, SlashMenuItem extends BaseSlashMenuItem<BSchema, I, S>> extends EventEmitter<any> {
9
- readonly plugin: Plugin;
10
- readonly itemCallback: (item: SlashMenuItem) => void;
11
- constructor(editor: BlockNoteEditor<BSchema, I, S>, items: SlashMenuItem[]);
12
- onUpdate(callback: (state: SuggestionsMenuState<SlashMenuItem>) => void): () => void;
13
- }
@@ -1,3 +0,0 @@
1
- import { InlineContentSchema, StyleSchema } from "../../schema";
2
- import { BaseSlashMenuItem } from "./BaseSlashMenuItem";
3
- export declare const getDefaultSlashMenuItems: <BSchema extends Record<string, import("../../schema").BlockConfig>, I extends InlineContentSchema, S extends StyleSchema>(schema?: BSchema) => BaseSlashMenuItem<BSchema, I, S>[];
@@ -1,7 +0,0 @@
1
- export type BaseUiElementCallbacks = {
2
- destroy: () => void;
3
- };
4
- export type BaseUiElementState = {
5
- show: boolean;
6
- referencePos: DOMRect;
7
- };
@@ -1,3 +0,0 @@
1
- export type SuggestionItem = {
2
- name: string;
3
- };
@@ -1,36 +0,0 @@
1
- import { Plugin, PluginKey } from "prosemirror-state";
2
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
3
- import { InlineContentSchema, StyleSchema } from "../../schema";
4
- import { BaseUiElementState } from "../BaseUiElementTypes";
5
- import { SuggestionItem } from "./SuggestionItem";
6
- export type SuggestionsMenuState<T extends SuggestionItem> = BaseUiElementState & {
7
- filteredItems: T[];
8
- keyboardHoveredItemIndex: number;
9
- };
10
- type SuggestionPluginState<T extends SuggestionItem> = {
11
- active: boolean;
12
- triggerCharacter: string | undefined;
13
- queryStartPos: number | undefined;
14
- items: T[];
15
- keyboardHoveredItemIndex: number | undefined;
16
- notFoundCount: number | undefined;
17
- decorationId: string | undefined;
18
- };
19
- /**
20
- * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.
21
- *
22
- * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.
23
- *
24
- * This version is adapted from the aforementioned version in the following ways:
25
- * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)
26
- * - This version hides some unnecessary complexity from the user of the plugin.
27
- * - This version handles key events differently
28
- */
29
- export declare const setupSuggestionsMenu: <T extends SuggestionItem, BSchema extends Record<string, import("../../schema").BlockConfig>, I extends InlineContentSchema, S extends StyleSchema>(editor: BlockNoteEditor<BSchema, I, S>, updateSuggestionsMenu: (suggestionsMenuState: SuggestionsMenuState<T>) => void, pluginKey: PluginKey, defaultTriggerCharacter: string, items?: (query: string) => T[], onSelectItem?: (props: {
30
- item: T;
31
- editor: BlockNoteEditor<BSchema, I, S>;
32
- }) => void) => {
33
- plugin: Plugin<SuggestionPluginState<T>>;
34
- itemCallback: (item: T) => void;
35
- };
36
- export {};
File without changes