@blocknote/core 0.3.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/blocknote.js +12698 -1341
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +50 -1
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +16 -5
  7. package/src/BlockNoteEditor.test.ts +12 -0
  8. package/src/BlockNoteEditor.ts +39 -15
  9. package/src/BlockNoteExtensions.ts +36 -32
  10. package/src/api/Editor.ts +226 -0
  11. package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +616 -0
  12. package/src/api/blockManipulation/blockManipulation.test.ts +172 -0
  13. package/src/api/blockManipulation/blockManipulation.ts +125 -0
  14. package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +346 -0
  15. package/src/api/formatConversions/formatConversions.test.ts +766 -0
  16. package/src/api/formatConversions/formatConversions.ts +86 -0
  17. package/src/api/formatConversions/removeUnderlinesRehypePlugin.ts +39 -0
  18. package/src/api/formatConversions/simplifyBlocksRehypePlugin.ts +125 -0
  19. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +268 -0
  20. package/src/api/nodeConversions/nodeConversions.test.ts +244 -0
  21. package/src/api/nodeConversions/nodeConversions.ts +279 -0
  22. package/src/api/nodeConversions/testUtil.ts +61 -0
  23. package/src/api/util/nodeUtil.ts +38 -0
  24. package/src/editor.module.css +8 -1
  25. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +7 -1
  26. package/src/extensions/Blocks/api/blockTypes.ts +90 -0
  27. package/src/extensions/Blocks/api/cursorPositionTypes.ts +5 -0
  28. package/src/extensions/Blocks/api/inlineContentTypes.ts +35 -0
  29. package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +4 -4
  30. package/src/extensions/Blocks/nodes/Block.module.css +39 -36
  31. package/src/extensions/Blocks/nodes/BlockContainer.ts +74 -23
  32. package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +23 -5
  33. package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +28 -6
  34. package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +149 -87
  35. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +2 -2
  36. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +3 -3
  37. package/src/extensions/SlashMenu/SlashMenuExtension.ts +7 -12
  38. package/src/extensions/SlashMenu/SlashMenuItem.ts +4 -1
  39. package/src/extensions/SlashMenu/{defaultCommands.tsx → defaultSlashCommands.tsx} +34 -17
  40. package/src/extensions/SlashMenu/index.ts +7 -4
  41. package/src/extensions/UniqueID/UniqueID.ts +1 -1
  42. package/src/index.ts +4 -2
  43. package/src/shared/utils.ts +6 -0
  44. package/types/src/BlockNoteEditor.d.ts +13 -4
  45. package/types/src/BlockNoteEditor.test.d.ts +1 -0
  46. package/types/src/BlockNoteExtensions.d.ts +7 -3
  47. package/types/src/api/Editor.d.ts +93 -0
  48. package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -0
  49. package/types/src/api/blockManipulation/blockManipulation.test.d.ts +1 -0
  50. package/types/src/api/formatConversions/formatConversions.d.ts +6 -0
  51. package/types/src/api/formatConversions/formatConversions.test.d.ts +1 -0
  52. package/types/src/api/formatConversions/removeUnderlinesRehypePlugin.d.ts +6 -0
  53. package/types/src/api/formatConversions/simplifyBlocksRehypePlugin.d.ts +16 -0
  54. package/types/src/api/nodeConversions/nodeConversions.d.ts +15 -0
  55. package/types/src/api/nodeConversions/nodeConversions.test.d.ts +1 -0
  56. package/types/src/api/nodeConversions/testUtil.d.ts +2 -0
  57. package/types/src/api/util/nodeUtil.d.ts +8 -0
  58. package/types/src/extensions/Blocks/api/blockTypes.d.ts +37 -0
  59. package/types/src/extensions/Blocks/api/cursorPositionTypes.d.ts +4 -0
  60. package/types/src/extensions/Blocks/api/inlineContentTypes.d.ts +29 -0
  61. package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +3 -3
  62. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +15 -0
  63. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +2 -2
  64. package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +1 -3
  65. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +4 -1
  66. package/types/src/extensions/SlashMenu/index.d.ts +3 -3
  67. package/types/src/index.d.ts +4 -2
  68. package/types/src/shared/utils.d.ts +3 -0
  69. package/src/extensions/Blocks/apiTypes.ts +0 -48
  70. package/types/src/EditorElement.d.ts +0 -7
  71. package/types/src/api/Document.d.ts +0 -5
  72. package/types/src/extensions/Blocks/BlockAttributes.d.ts +0 -2
  73. package/types/src/extensions/Blocks/MultipleNodeSelection.d.ts +0 -24
  74. package/types/src/extensions/Blocks/apiTypes.d.ts +0 -16
  75. package/types/src/extensions/Blocks/nodes/Block.d.ts +0 -24
  76. package/types/src/extensions/Blocks/nodes/BlockContent/BlockContentTypes.d.ts +0 -4
  77. package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContentTypes.d.ts +0 -4
  78. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContentTypes.d.ts +0 -2
  79. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContentTypes.d.ts +0 -2
  80. package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContentTypes.d.ts +0 -2
  81. package/types/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.d.ts +0 -8
  82. package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.d.ts +0 -8
  83. package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.d.ts +0 -2
  84. package/types/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.d.ts +0 -6
  85. package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +0 -8
  86. package/types/src/extensions/BubbleMenu/BubbleMenuFactoryTypes.d.ts +0 -27
  87. package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +0 -44
  88. package/types/src/extensions/DraggableBlocks/BlockMenuFactoryTypes.d.ts +0 -12
  89. package/types/src/extensions/DraggableBlocks/DragMenuFactoryTypes.d.ts +0 -18
  90. package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +0 -8
  91. package/types/src/extensions/Hyperlinks/HyperlinkMenuFactoryTypes.d.ts +0 -11
  92. package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +0 -11
  93. package/types/src/extensions/Paragraph/FixedParagraph.d.ts +0 -1
  94. package/types/src/extensions/SlashMenu/defaultCommands.d.ts +0 -8
  95. package/types/src/utils.d.ts +0 -2
@@ -150,8 +150,10 @@ function setDragImage(view: EditorView, from: number, to = from) {
150
150
  }
151
151
 
152
152
  // dataTransfer.setDragImage(element) only works if element is attached to the DOM.
153
+ unsetDragImage();
153
154
  dragImageElement = parentClone;
154
- dragImageElement.className = styles.dragPreview;
155
+ dragImageElement.className =
156
+ dragImageElement.className + " " + styles.dragPreview;
155
157
  document.body.appendChild(dragImageElement);
156
158
  }
157
159
 
@@ -245,104 +247,164 @@ export class BlockMenuView {
245
247
 
246
248
  this.blockMenu = blockMenuFactory(this.getStaticParams());
247
249
 
250
+ document.body.addEventListener("drop", this.onDrop, true);
251
+ document.body.addEventListener("dragover", this.onDragOver);
252
+
248
253
  // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
249
- document.body.addEventListener(
250
- "mousemove",
251
- (event) => {
252
- if (this.menuFrozen) {
253
- return;
254
- }
255
-
256
- // Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of
257
- // the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.
258
- const editorBoundingBox = (
259
- this.editor.view.dom.firstChild! as HTMLElement
260
- ).getBoundingClientRect();
261
-
262
- this.horizontalPosAnchor = editorBoundingBox.x;
263
-
264
- // Gets block at mouse cursor's vertical position.
265
- const coords = {
266
- left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
267
- top: event.clientY,
268
- };
269
- const block = getDraggableBlockFromCoords(coords, this.editor.view);
270
-
271
- // Closes the menu if the mouse cursor is beyond the editor vertically.
272
- if (!block) {
273
- if (this.menuOpen) {
274
- this.menuOpen = false;
275
- this.blockMenu.hide();
276
- }
277
-
278
- return;
279
- }
280
-
281
- // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.
282
- if (
283
- this.menuOpen &&
284
- this.hoveredBlockContent?.hasAttribute("data-id") &&
285
- this.hoveredBlockContent?.getAttribute("data-id") === block.id
286
- ) {
287
- return;
288
- }
289
-
290
- // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.
291
- const blockContent = block.node.firstChild as HTMLElement;
292
- this.hoveredBlockContent = blockContent;
293
-
294
- if (!blockContent) {
295
- return;
296
- }
297
-
298
- // Shows or updates elements.
299
- if (!this.menuOpen) {
300
- this.menuOpen = true;
301
- this.blockMenu.render(this.getDynamicParams(), true);
302
- } else {
303
- this.blockMenu.render(this.getDynamicParams(), false);
304
- }
305
- },
306
- true
307
- );
254
+ document.body.addEventListener("mousemove", this.onMouseMove, true);
308
255
 
309
256
  // Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.
310
257
  // TODO: Better integration with suggestions menu and only editor scope?
311
- document.body.addEventListener(
312
- "mousedown",
313
- (event) => {
314
- if (this.blockMenu.element?.contains(event.target as HTMLElement)) {
315
- return;
316
- }
317
-
318
- if (this.menuOpen) {
319
- this.menuOpen = false;
320
- this.blockMenu.hide();
321
- }
258
+ document.body.addEventListener("mousedown", this.onMouseDown, true);
259
+ document.body.addEventListener("keydown", this.onKeyDown, true);
260
+ }
322
261
 
323
- this.menuFrozen = false;
324
- },
325
- true
326
- );
327
- document.body.addEventListener(
328
- "keydown",
329
- () => {
330
- if (this.menuOpen) {
331
- this.menuOpen = false;
332
- this.blockMenu.hide();
333
- }
262
+ /**
263
+ * If the event is outside of the editor contents,
264
+ * we dispatch a fake event, so that we can still drop the content
265
+ * when dragging / dropping to the side of the editor
266
+ */
267
+ onDrop = (event: DragEvent) => {
268
+ if ((event as any).synthetic) {
269
+ return;
270
+ }
271
+ let pos = this.editor.view.posAtCoords({
272
+ left: event.clientX,
273
+ top: event.clientY,
274
+ });
334
275
 
335
- this.menuFrozen = false;
336
- },
337
- true
338
- );
339
- }
276
+ if (!pos || pos.inside === -1) {
277
+ const evt = new Event("drop", event) as any;
278
+ const editorBoundingBox = (
279
+ this.editor.view.dom.firstChild! as HTMLElement
280
+ ).getBoundingClientRect();
281
+ evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;
282
+ evt.clientY = event.clientY;
283
+ evt.dataTransfer = event.dataTransfer;
284
+ evt.preventDefault = () => event.preventDefault();
285
+ evt.synthetic = true; // prevent recursion
286
+ // console.log("dispatch fake drop");
287
+ this.editor.view.dom.dispatchEvent(evt);
288
+ }
289
+ };
290
+
291
+ /**
292
+ * If the event is outside of the editor contents,
293
+ * we dispatch a fake event, so that we can still drop the content
294
+ * when dragging / dropping to the side of the editor
295
+ */
296
+ onDragOver = (event: DragEvent) => {
297
+ if ((event as any).synthetic) {
298
+ return;
299
+ }
300
+ let pos = this.editor.view.posAtCoords({
301
+ left: event.clientX,
302
+ top: event.clientY,
303
+ });
304
+
305
+ if (!pos || pos.inside === -1) {
306
+ const evt = new Event("dragover", event) as any;
307
+ const editorBoundingBox = (
308
+ this.editor.view.dom.firstChild! as HTMLElement
309
+ ).getBoundingClientRect();
310
+ evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;
311
+ evt.clientY = event.clientY;
312
+ evt.dataTransfer = event.dataTransfer;
313
+ evt.preventDefault = () => event.preventDefault();
314
+ evt.synthetic = true; // prevent recursion
315
+ // console.log("dispatch fake dragover");
316
+ this.editor.view.dom.dispatchEvent(evt);
317
+ }
318
+ };
319
+
320
+ onKeyDown = (_event: KeyboardEvent) => {
321
+ if (this.menuOpen) {
322
+ this.menuOpen = false;
323
+ this.blockMenu.hide();
324
+ }
325
+
326
+ this.menuFrozen = false;
327
+ };
328
+
329
+ onMouseDown = (event: MouseEvent) => {
330
+ if (this.blockMenu.element?.contains(event.target as HTMLElement)) {
331
+ return;
332
+ }
333
+
334
+ if (this.menuOpen) {
335
+ this.menuOpen = false;
336
+ this.blockMenu.hide();
337
+ }
338
+
339
+ this.menuFrozen = false;
340
+ };
341
+
342
+ onMouseMove = (event: MouseEvent) => {
343
+ if (this.menuFrozen) {
344
+ return;
345
+ }
346
+
347
+ // Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of
348
+ // the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.
349
+ const editorBoundingBox = (
350
+ this.editor.view.dom.firstChild! as HTMLElement
351
+ ).getBoundingClientRect();
352
+
353
+ this.horizontalPosAnchor = editorBoundingBox.x;
354
+
355
+ // Gets block at mouse cursor's vertical position.
356
+ const coords = {
357
+ left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
358
+ top: event.clientY,
359
+ };
360
+ const block = getDraggableBlockFromCoords(coords, this.editor.view);
361
+
362
+ // Closes the menu if the mouse cursor is beyond the editor vertically.
363
+ if (!block) {
364
+ if (this.menuOpen) {
365
+ this.menuOpen = false;
366
+ this.blockMenu.hide();
367
+ }
368
+
369
+ return;
370
+ }
371
+
372
+ // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.
373
+ if (
374
+ this.menuOpen &&
375
+ this.hoveredBlockContent?.hasAttribute("data-id") &&
376
+ this.hoveredBlockContent?.getAttribute("data-id") === block.id
377
+ ) {
378
+ return;
379
+ }
380
+
381
+ // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.
382
+ const blockContent = block.node.firstChild as HTMLElement;
383
+ this.hoveredBlockContent = blockContent;
384
+
385
+ if (!blockContent) {
386
+ return;
387
+ }
388
+
389
+ // Shows or updates elements.
390
+ if (!this.menuOpen) {
391
+ this.menuOpen = true;
392
+ this.blockMenu.render(this.getDynamicParams(), true);
393
+ } else {
394
+ this.blockMenu.render(this.getDynamicParams(), false);
395
+ }
396
+ };
340
397
 
341
398
  destroy() {
342
399
  if (this.menuOpen) {
343
400
  this.menuOpen = false;
344
401
  this.blockMenu.hide();
345
402
  }
403
+ document.body.removeEventListener("mousemove", this.onMouseMove);
404
+ document.body.removeEventListener("dragover", this.onDragOver);
405
+ document.body.removeEventListener("drop", this.onDrop);
406
+ document.body.removeEventListener("mousedown", this.onMouseDown);
407
+ document.body.removeEventListener("keydown", this.onKeyDown);
346
408
  }
347
409
 
348
410
  addBlock() {
@@ -1,5 +1,5 @@
1
1
  import { EditorElement, ElementFactory } from "../../shared/EditorElement";
2
- import { Block, BlockUpdate } from "../Blocks/apiTypes";
2
+ import { Block, PartialBlock } from "../Blocks/api/blockTypes";
3
3
 
4
4
  export type FormattingToolbarStaticParams = {
5
5
  toggleBold: () => void;
@@ -17,7 +17,7 @@ export type FormattingToolbarStaticParams = {
17
17
  increaseBlockIndent: () => void;
18
18
  decreaseBlockIndent: () => void;
19
19
 
20
- updateBlock: (blockUpdate: BlockUpdate) => void;
20
+ updateBlock: (updatedBlock: PartialBlock) => void;
21
21
  };
22
22
 
23
23
  export type FormattingToolbarDynamicParams = {
@@ -6,7 +6,7 @@ import {
6
6
  } from "@tiptap/core";
7
7
  import { EditorState, Plugin, PluginKey } from "prosemirror-state";
8
8
  import { EditorView } from "prosemirror-view";
9
- import { Block, BlockUpdate } from "../Blocks/apiTypes";
9
+ import { Block, PartialBlock } from "../Blocks/api/blockTypes";
10
10
  import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
11
11
  import {
12
12
  FormattingToolbar,
@@ -288,11 +288,11 @@ export class FormattingToolbarView {
288
288
  this.editor.view.focus();
289
289
  this.editor.commands.liftListItem("blockContainer");
290
290
  },
291
- updateBlock: (blockUpdate: BlockUpdate) => {
291
+ updateBlock: (updatedBlock: PartialBlock) => {
292
292
  this.editor.view.focus();
293
293
  this.editor.commands.BNUpdateBlock(
294
294
  this.editor.state.selection.from,
295
- blockUpdate
295
+ updatedBlock
296
296
  );
297
297
  },
298
298
  };
@@ -2,11 +2,10 @@ import { Extension } from "@tiptap/core";
2
2
  import { PluginKey } from "prosemirror-state";
3
3
  import { createSuggestionPlugin } from "../../shared/plugins/suggestion/SuggestionPlugin";
4
4
  import { SuggestionsMenuFactory } from "../../shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
5
- import defaultCommands from "./defaultCommands";
6
5
  import { SlashMenuItem } from "./SlashMenuItem";
7
6
 
8
7
  export type SlashMenuOptions = {
9
- commands: { [key: string]: SlashMenuItem };
8
+ commands: SlashMenuItem[] | undefined;
10
9
  slashMenuFactory: SuggestionsMenuFactory<any> | undefined;
11
10
  };
12
11
 
@@ -17,16 +16,18 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
17
16
 
18
17
  addOptions() {
19
18
  return {
20
- commands: defaultCommands,
21
- slashMenuFactory: undefined, // TODO: fix undefined
19
+ commands: undefined,
20
+ slashMenuFactory: undefined,
22
21
  };
23
22
  },
24
23
 
25
24
  addProseMirrorPlugins() {
26
- if (!this.options.slashMenuFactory) {
27
- throw new Error("UI Element factory not defined for SlashMenuExtension");
25
+ if (!this.options.slashMenuFactory || !this.options.commands) {
26
+ throw new Error("required args not defined for SlashMenuExtension");
28
27
  }
29
28
 
29
+ const commands = this.options.commands;
30
+
30
31
  return [
31
32
  createSuggestionPlugin<SlashMenuItem>({
32
33
  pluginKey: SlashMenuPluginKey,
@@ -34,12 +35,6 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
34
35
  defaultTriggerCharacter: "/",
35
36
  suggestionsMenuFactory: this.options.slashMenuFactory!,
36
37
  items: (query) => {
37
- const commands = [];
38
-
39
- for (const key in this.options.commands) {
40
- commands.push(this.options.commands[key]);
41
- }
42
-
43
38
  return commands.filter((cmd: SlashMenuItem) => cmd.match(query));
44
39
  },
45
40
  onSelectItem: ({ item, editor, range }) => {
@@ -17,7 +17,10 @@ export class SlashMenuItem implements SuggestionItem {
17
17
  constructor(
18
18
  public readonly name: string,
19
19
  public readonly execute: (editor: Editor, range: Range) => void,
20
- public readonly aliases: string[] = []
20
+ public readonly aliases: string[] = [],
21
+ public readonly group: string,
22
+ public readonly hint?: string,
23
+ public readonly shortcut?: string
21
24
  ) {}
22
25
 
23
26
  match(query: string): boolean {
@@ -1,12 +1,13 @@
1
- import { SlashMenuItem } from "./SlashMenuItem";
2
1
  import { Editor, Range } from "@tiptap/core";
2
+ import { formatKeyboardShortcut } from "../../shared/utils";
3
+ import { SlashMenuItem } from "./SlashMenuItem";
3
4
 
4
5
  /**
5
6
  * An array containing commands for creating all default blocks.
6
7
  */
7
- const defaultCommands: { [key: string]: SlashMenuItem } = {
8
+ export const defaultSlashCommands: SlashMenuItem[] = [
8
9
  // Command for creating a level 1 heading
9
- heading: new SlashMenuItem(
10
+ new SlashMenuItem(
10
11
  "Heading",
11
12
  (editor: Editor, range: Range) => {
12
13
  return editor
@@ -21,11 +22,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
21
22
  })
22
23
  .run();
23
24
  },
24
- ["h", "heading1", "h1"]
25
+ ["h", "heading1", "h1"],
26
+ "Headings",
27
+ "Used for a top-level heading",
28
+ formatKeyboardShortcut("Mod-Alt-1")
25
29
  ),
26
30
 
27
31
  // Command for creating a level 2 heading
28
- heading2: new SlashMenuItem(
32
+ new SlashMenuItem(
29
33
  "Heading 2",
30
34
  (editor: Editor, range: Range) => {
31
35
  return editor
@@ -40,11 +44,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
40
44
  })
41
45
  .run();
42
46
  },
43
- ["h2", "heading2", "subheading"]
47
+ ["h2", "heading2", "subheading"],
48
+ "Headings",
49
+ "Used for key sections",
50
+ formatKeyboardShortcut("Mod-Alt-2")
44
51
  ),
45
52
 
46
53
  // Command for creating a level 3 heading
47
- heading3: new SlashMenuItem(
54
+ new SlashMenuItem(
48
55
  "Heading 3",
49
56
  (editor: Editor, range: Range) => {
50
57
  return editor
@@ -59,11 +66,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
59
66
  })
60
67
  .run();
61
68
  },
62
- ["h3", "heading3", "subheading"]
69
+ ["h3", "heading3", "subheading"],
70
+ "Headings",
71
+ "Used for subsections and group headings",
72
+ formatKeyboardShortcut("Mod-Alt-3")
63
73
  ),
64
74
 
65
75
  // Command for creating an ordered list
66
- numberedList: new SlashMenuItem(
76
+ new SlashMenuItem(
67
77
  "Numbered List",
68
78
  (editor: Editor, range: Range) => {
69
79
  return editor
@@ -76,11 +86,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
76
86
  })
77
87
  .run();
78
88
  },
79
- ["li", "list", "numberedlist", "numbered list"]
89
+ ["li", "list", "numberedlist", "numbered list"],
90
+ "Basic blocks",
91
+ "Used to display a numbered list",
92
+ "Mod-Alt-7"
80
93
  ),
81
94
 
82
95
  // Command for creating a bullet list
83
- bulletList: new SlashMenuItem(
96
+ new SlashMenuItem(
84
97
  "Bullet List",
85
98
  (editor: Editor, range: Range) => {
86
99
  return editor
@@ -93,11 +106,14 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
93
106
  })
94
107
  .run();
95
108
  },
96
- ["ul", "list", "bulletlist", "bullet list"]
109
+ ["ul", "list", "bulletlist", "bullet list"],
110
+ "Basic blocks",
111
+ "Used to display an unordered list",
112
+ "Mod-Alt-9"
97
113
  ),
98
114
 
99
115
  // Command for creating a paragraph (pretty useless)
100
- paragraph: new SlashMenuItem(
116
+ new SlashMenuItem(
101
117
  "Paragraph",
102
118
  (editor: Editor, range: Range) => {
103
119
  return editor
@@ -110,7 +126,10 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
110
126
  })
111
127
  .run();
112
128
  },
113
- ["p"]
129
+ ["p"],
130
+ "Basic blocks",
131
+ "Used for the body of your document",
132
+ "Mod-Alt-0"
114
133
  ),
115
134
 
116
135
  // replaceRangeWithNode(editor, range, node);
@@ -216,6 +235,4 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
216
235
  // TableIcon,
217
236
  // "Used to create a simple table"
218
237
  // ),
219
- };
220
-
221
- export default defaultCommands;
238
+ ];
@@ -1,6 +1,9 @@
1
+ import { defaultSlashCommands } from "./defaultSlashCommands";
1
2
  import { SlashMenuExtension } from "./SlashMenuExtension";
2
- import defaultCommands from "./defaultCommands";
3
+ import { SlashMenuItem } from "./SlashMenuItem";
3
4
 
4
- export { defaultCommands };
5
-
6
- export default SlashMenuExtension;
5
+ export {
6
+ defaultSlashCommands,
7
+ SlashMenuItem as SlashCommand,
8
+ SlashMenuExtension,
9
+ };
@@ -123,7 +123,7 @@ const UniqueID = Extension.create({
123
123
  new Plugin({
124
124
  key: new PluginKey("uniqueID"),
125
125
  appendTransaction: (transactions, oldState, newState) => {
126
- console.log("appendTransaction");
126
+ // console.log("appendTransaction");
127
127
  const docChanges =
128
128
  transactions.some((transaction) => transaction.docChanged) &&
129
129
  !oldState.doc.eq(newState.doc);
package/src/index.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export * from "./BlockNoteEditor";
2
2
  export * from "./BlockNoteExtensions";
3
- export type { Block, BlockUpdate } from "./extensions/Blocks/apiTypes";
4
- export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
3
+ export * from "./extensions/Blocks/api/blockTypes";
5
4
  export * from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
5
+ export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
6
6
  export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
7
+ export { defaultSlashCommands } from "./extensions/SlashMenu/defaultSlashCommands";
7
8
  export * from "./extensions/SlashMenu/SlashMenuItem";
8
9
  export * from "./shared/EditorElement";
9
10
  export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
10
11
  export * from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
12
+ export * from "../src/api/Editor";
@@ -10,3 +10,9 @@ export function formatKeyboardShortcut(shortcut: string) {
10
10
  return shortcut.replace("Mod", "Ctrl");
11
11
  }
12
12
  }
13
+
14
+ export class UnreachableCaseError extends Error {
15
+ constructor(val: never) {
16
+ super(`Unreachable case: ${val}`);
17
+ }
18
+ }
@@ -1,13 +1,22 @@
1
- import { Editor, EditorOptions } from "@tiptap/core";
1
+ import { Editor } from "@tiptap/core";
2
+ import { Editor as EditorAPI } from "./api/Editor";
2
3
  import { UiFactories } from "./BlockNoteExtensions";
3
- export type BlockNoteEditorOptions = EditorOptions & {
4
+ import { SlashCommand } from "./extensions/SlashMenu";
5
+ export type BlockNoteEditorOptions = {
4
6
  enableBlockNoteExtensions: boolean;
5
7
  disableHistoryExtension: boolean;
6
8
  uiFactories: UiFactories;
9
+ slashCommands: SlashCommand[];
10
+ parentElement: HTMLElement;
11
+ editorDOMAttributes: Record<string, string>;
12
+ onUpdate: (editor: BlockNoteEditor) => void;
13
+ onCreate: (editor: BlockNoteEditor) => void;
14
+ _tiptapOptions: any;
7
15
  };
8
- export declare class BlockNoteEditor {
9
- readonly tiptapEditor: Editor & {
16
+ export declare class BlockNoteEditor extends EditorAPI {
17
+ readonly _tiptapEditor: Editor & {
10
18
  contentComponent: any;
11
19
  };
20
+ get domElement(): HTMLDivElement;
12
21
  constructor(options?: Partial<BlockNoteEditorOptions>);
13
22
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,9 +1,10 @@
1
1
  import { Extensions } from "@tiptap/core";
2
+ import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
2
3
  import { FormattingToolbarFactory } from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
3
4
  import { HyperlinkToolbarFactory } from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
4
- import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
5
- import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
5
+ import { SlashCommand } from "./extensions/SlashMenu";
6
6
  import { SlashMenuItem } from "./extensions/SlashMenu/SlashMenuItem";
7
+ import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
7
8
  export type UiFactories = Partial<{
8
9
  formattingToolbarFactory: FormattingToolbarFactory;
9
10
  hyperlinkToolbarFactory: HyperlinkToolbarFactory;
@@ -13,4 +14,7 @@ export type UiFactories = Partial<{
13
14
  /**
14
15
  * Get all the Tiptap extensions BlockNote is configured with by default
15
16
  */
16
- export declare const getBlockNoteExtensions: (uiFactories: UiFactories) => Extensions;
17
+ export declare const getBlockNoteExtensions: (opts: {
18
+ uiFactories: UiFactories;
19
+ slashCommands: SlashCommand[];
20
+ }) => Extensions;