@blocknote/core 0.2.3 → 0.3.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 (44) hide show
  1. package/dist/blocknote.js +753 -633
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +1 -1
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +19 -28
  7. package/src/BlockNoteExtensions.ts +10 -0
  8. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +61 -0
  9. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +62 -0
  10. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +107 -97
  11. package/src/extensions/Blocks/nodes/Block.module.css +91 -6
  12. package/src/extensions/Blocks/nodes/BlockContainer.ts +39 -26
  13. package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +4 -4
  14. package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +8 -0
  15. package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +80 -35
  16. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +16 -0
  17. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +34 -3
  18. package/src/extensions/Placeholder/PlaceholderExtension.ts +1 -1
  19. package/src/extensions/SlashMenu/SlashMenuExtension.ts +1 -1
  20. package/src/extensions/SlashMenu/SlashMenuItem.ts +3 -28
  21. package/src/extensions/SlashMenu/defaultCommands.tsx +14 -32
  22. package/src/extensions/SlashMenu/index.ts +1 -6
  23. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +75 -0
  24. package/src/extensions/TextColor/TextColorExtension.ts +54 -0
  25. package/src/extensions/TextColor/TextColorMark.ts +62 -0
  26. package/src/shared/plugins/suggestion/SuggestionItem.ts +0 -9
  27. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +191 -228
  28. package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +1 -1
  29. package/types/src/api/Document.d.ts +5 -0
  30. package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +9 -0
  31. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +9 -0
  32. package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +3 -2
  33. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +4 -0
  34. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +4 -9
  35. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +10 -0
  36. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -19
  37. package/types/src/extensions/SlashMenu/defaultSlashCommands.d.ts +5 -0
  38. package/types/src/extensions/SlashMenu/index.d.ts +1 -2
  39. package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +9 -0
  40. package/types/src/extensions/TextColor/TextColorExtension.d.ts +9 -0
  41. package/types/src/extensions/TextColor/TextColorMark.d.ts +9 -0
  42. package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +0 -6
  43. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +9 -23
  44. package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  import { mergeAttributes, Node } from "@tiptap/core";
2
- import { Slice } from "prosemirror-model";
2
+ import { Fragment, Slice } from "prosemirror-model";
3
3
  import { TextSelection } from "prosemirror-state";
4
4
  import { BlockUpdate } from "../apiTypes";
5
5
  import { getBlockInfoFromPos } from "../helpers/getBlockInfoFromPos";
@@ -49,17 +49,6 @@ export const BlockContainer = Node.create<IBlock>({
49
49
  };
50
50
  },
51
51
 
52
- addAttributes() {
53
- return {
54
- blockColor: {
55
- default: undefined,
56
- },
57
- blockStyle: {
58
- default: undefined,
59
- },
60
- };
61
- },
62
-
63
52
  parseHTML() {
64
53
  return [
65
54
  {
@@ -233,20 +222,36 @@ export const BlockContainer = Node.create<IBlock>({
233
222
  const { contentNode, contentType, startPos, endPos, depth } =
234
223
  blockInfo;
235
224
 
236
- const newBlockInsertionPos = endPos + 1;
237
-
238
- // Creates new block first, otherwise positions get changed due to the original block's content changing.
239
- // Only text content is transferred to the new block.
240
- const secondBlockContent = state.doc.textBetween(posInBlock, endPos);
225
+ const originalBlockContent = state.doc.cut(startPos + 1, posInBlock);
226
+ const newBlockContent = state.doc.cut(posInBlock, endPos - 1);
241
227
 
242
228
  const newBlock =
243
229
  state.schema.nodes["blockContainer"].createAndFill()!;
230
+
231
+ const newBlockInsertionPos = endPos + 1;
244
232
  const newBlockContentPos = newBlockInsertionPos + 2;
245
233
 
246
234
  if (dispatch) {
235
+ // Creates a new block. Since the schema requires it to have a content node, a paragraph node is created
236
+ // automatically, spanning newBlockContentPos to newBlockContentPos + 1.
247
237
  state.tr.insert(newBlockInsertionPos, newBlock);
248
- state.tr.insertText(secondBlockContent, newBlockContentPos);
249
238
 
239
+ // Replaces the content of the newly created block's content node. Doesn't replace the whole content node so
240
+ // its type doesn't change.
241
+ state.tr.replace(
242
+ newBlockContentPos,
243
+ newBlockContentPos + 1,
244
+ newBlockContent.content.size > 0
245
+ ? new Slice(
246
+ Fragment.from(newBlockContent),
247
+ depth + 2,
248
+ depth + 2
249
+ )
250
+ : undefined
251
+ );
252
+
253
+ // Changes the type of the content node. The range doesn't matter as long as both from and to positions are
254
+ // within the content node.
250
255
  if (keepType) {
251
256
  state.tr.setBlockType(
252
257
  newBlockContentPos,
@@ -255,22 +260,30 @@ export const BlockContainer = Node.create<IBlock>({
255
260
  contentNode.attrs
256
261
  );
257
262
  }
258
- }
259
263
 
260
- // Updates content of original block.
261
- const firstBlockContent = state.doc.content.cut(startPos, posInBlock);
264
+ // Sets the selection to the start of the new block's content node.
265
+ state.tr.setSelection(
266
+ new TextSelection(state.doc.resolve(newBlockContentPos))
267
+ );
262
268
 
263
- if (dispatch) {
269
+ // Replaces the content of the original block's content node. Doesn't replace the whole content node so its
270
+ // type doesn't change.
264
271
  state.tr.replace(
265
- startPos,
266
- endPos,
267
- new Slice(firstBlockContent, depth, depth)
272
+ startPos + 1,
273
+ endPos - 1,
274
+ originalBlockContent.content.size > 0
275
+ ? new Slice(
276
+ Fragment.from(originalBlockContent),
277
+ depth + 2,
278
+ depth + 2
279
+ )
280
+ : undefined
268
281
  );
269
282
  }
270
283
 
271
284
  return true;
272
285
  },
273
- // Changes the content of a block at a given position to a given type.
286
+ // Updates the type and attributes of a block at a given position.
274
287
  BNUpdateBlock:
275
288
  (posInBlock, blockUpdate) =>
276
289
  ({ state, dispatch }) => {
@@ -1,4 +1,4 @@
1
- import { Node } from "@tiptap/core";
1
+ import { mergeAttributes, Node } from "@tiptap/core";
2
2
  import styles from "../../Block.module.css";
3
3
 
4
4
  export const ParagraphBlockContent = Node.create({
@@ -16,13 +16,13 @@ export const ParagraphBlockContent = Node.create({
16
16
  ];
17
17
  },
18
18
 
19
- renderHTML() {
19
+ renderHTML({ HTMLAttributes }) {
20
20
  return [
21
21
  "div",
22
- {
22
+ mergeAttributes(HTMLAttributes, {
23
23
  class: styles.blockContent,
24
24
  "data-content-type": this.name,
25
- },
25
+ }),
26
26
  ["p", 0],
27
27
  ];
28
28
  },
@@ -3,13 +3,21 @@ import { EditorElement, ElementFactory } from "../../shared/EditorElement";
3
3
  export type BlockSideMenuStaticParams = {
4
4
  addBlock: () => void;
5
5
  deleteBlock: () => void;
6
+
6
7
  blockDragStart: (event: DragEvent) => void;
7
8
  blockDragEnd: () => void;
9
+
8
10
  freezeMenu: () => void;
9
11
  unfreezeMenu: () => void;
12
+
13
+ setBlockTextColor: (color: string) => void;
14
+ setBlockBackgroundColor: (color: string) => void;
10
15
  };
11
16
 
12
17
  export type BlockSideMenuDynamicParams = {
18
+ blockTextColor: string;
19
+ blockBackgroundColor: string;
20
+
13
21
  referenceRect: DOMRect;
14
22
  };
15
23
 
@@ -18,21 +18,8 @@ import { MultipleNodeSelection } from "./MultipleNodeSelection";
18
18
  const serializeForClipboard = (pv as any).__serializeForClipboard;
19
19
  // code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799
20
20
 
21
- let horizontalAnchor: number;
22
21
  let dragImageElement: Element | undefined;
23
22
 
24
- function getHorizontalAnchor() {
25
- if (!horizontalAnchor) {
26
- const firstBlockGroup = document.querySelector(
27
- ".ProseMirror > [class*='blockGroup']"
28
- ) as HTMLElement | undefined; // first block group node
29
- if (firstBlockGroup) {
30
- horizontalAnchor = absoluteRect(firstBlockGroup).left;
31
- } // Anchor to the left of the first block group
32
- }
33
- return horizontalAnchor;
34
- }
35
-
36
23
  export function createRect(rect: DOMRect) {
37
24
  let newRect = {
38
25
  left: rect.left + document.body.scrollLeft,
@@ -47,10 +34,6 @@ export function createRect(rect: DOMRect) {
47
34
  return newRect;
48
35
  }
49
36
 
50
- export function absoluteRect(element: HTMLElement) {
51
- return createRect(element.getBoundingClientRect());
52
- }
53
-
54
37
  function getDraggableBlockFromCoords(
55
38
  coords: { left: number; top: number },
56
39
  view: EditorView
@@ -184,8 +167,10 @@ function dragStart(e: DragEvent, view: EditorView) {
184
167
  return;
185
168
  }
186
169
 
170
+ const editorBoundingBox = view.dom.getBoundingClientRect();
171
+
187
172
  let coords = {
188
- left: view.dom.clientWidth / 2, // take middle of editor
173
+ left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
189
174
  top: e.clientY,
190
175
  };
191
176
 
@@ -238,9 +223,11 @@ export class BlockMenuView {
238
223
  // When false, the drag handle with be just to the left of the element
239
224
  horizontalPosAnchoredAtRoot: boolean;
240
225
 
226
+ horizontalPosAnchor: number;
227
+
241
228
  blockMenu: BlockSideMenu;
242
229
 
243
- hoveredBlock: HTMLElement | undefined;
230
+ hoveredBlockContent: HTMLElement | undefined;
244
231
 
245
232
  menuOpen = false;
246
233
  menuFrozen = false;
@@ -252,6 +239,9 @@ export class BlockMenuView {
252
239
  }: BlockMenuViewProps) {
253
240
  this.editor = editor;
254
241
  this.horizontalPosAnchoredAtRoot = horizontalPosAnchoredAtRoot;
242
+ this.horizontalPosAnchor = (
243
+ editor.view.dom.firstChild! as HTMLElement
244
+ ).getBoundingClientRect().x;
255
245
 
256
246
  this.blockMenu = blockMenuFactory(this.getStaticParams());
257
247
 
@@ -263,9 +253,17 @@ export class BlockMenuView {
263
253
  return;
264
254
  }
265
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
+
266
264
  // Gets block at mouse cursor's vertical position.
267
265
  const coords = {
268
- left: this.editor.view.dom.clientWidth / 2, // take middle of editor
266
+ left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
269
267
  top: event.clientY,
270
268
  };
271
269
  const block = getDraggableBlockFromCoords(coords, this.editor.view);
@@ -283,15 +281,15 @@ export class BlockMenuView {
283
281
  // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.
284
282
  if (
285
283
  this.menuOpen &&
286
- this.hoveredBlock?.hasAttribute("data-id") &&
287
- this.hoveredBlock?.getAttribute("data-id") === block.id
284
+ this.hoveredBlockContent?.hasAttribute("data-id") &&
285
+ this.hoveredBlockContent?.getAttribute("data-id") === block.id
288
286
  ) {
289
287
  return;
290
288
  }
291
289
 
292
290
  // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.
293
291
  const blockContent = block.node.firstChild as HTMLElement;
294
- this.hoveredBlock = blockContent;
292
+ this.hoveredBlockContent = blockContent;
295
293
 
296
294
  if (!blockContent) {
297
295
  return;
@@ -352,11 +350,12 @@ export class BlockMenuView {
352
350
  this.menuFrozen = true;
353
351
  this.blockMenu.hide();
354
352
 
355
- const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();
353
+ const blockContentBoundingBox =
354
+ this.hoveredBlockContent!.getBoundingClientRect();
356
355
 
357
356
  const pos = this.editor.view.posAtCoords({
358
- left: blockBoundingBox.left,
359
- top: blockBoundingBox.top,
357
+ left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,
358
+ top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,
360
359
  });
361
360
  if (!pos) {
362
361
  return;
@@ -380,6 +379,8 @@ export class BlockMenuView {
380
379
  .BNUpdateBlock(newBlockContentPos, { type: "paragraph", props: {} })
381
380
  .setTextSelection(newBlockContentPos)
382
381
  .run();
382
+ } else {
383
+ this.editor.commands.setTextSelection(endPos);
383
384
  }
384
385
 
385
386
  // Focuses and activates the suggestion menu.
@@ -397,11 +398,12 @@ export class BlockMenuView {
397
398
  this.menuOpen = false;
398
399
  this.blockMenu.hide();
399
400
 
400
- const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();
401
+ const blockContentBoundingBox =
402
+ this.hoveredBlockContent!.getBoundingClientRect();
401
403
 
402
404
  const pos = this.editor.view.posAtCoords({
403
- left: blockBoundingBox.left,
404
- top: blockBoundingBox.top,
405
+ left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,
406
+ top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,
405
407
  });
406
408
  if (!pos) {
407
409
  return;
@@ -410,6 +412,42 @@ export class BlockMenuView {
410
412
  this.editor.commands.BNDeleteBlock(pos.pos);
411
413
  }
412
414
 
415
+ setBlockBackgroundColor(color: string) {
416
+ this.menuOpen = false;
417
+ this.blockMenu.hide();
418
+
419
+ const blockContentBoundingBox =
420
+ this.hoveredBlockContent!.getBoundingClientRect();
421
+
422
+ const pos = this.editor.view.posAtCoords({
423
+ left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,
424
+ top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,
425
+ });
426
+ if (!pos) {
427
+ return;
428
+ }
429
+
430
+ this.editor.commands.setBlockBackgroundColor(pos.pos, color);
431
+ }
432
+
433
+ setBlockTextColor(color: string) {
434
+ this.menuOpen = false;
435
+ this.blockMenu.hide();
436
+
437
+ const blockContentBoundingBox =
438
+ this.hoveredBlockContent!.getBoundingClientRect();
439
+
440
+ const pos = this.editor.view.posAtCoords({
441
+ left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,
442
+ top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,
443
+ });
444
+ if (!pos) {
445
+ return;
446
+ }
447
+
448
+ this.editor.commands.setBlockTextColor(pos.pos, color);
449
+ }
450
+
413
451
  getStaticParams(): BlockSideMenuStaticParams {
414
452
  return {
415
453
  addBlock: () => this.addBlock(),
@@ -422,20 +460,27 @@ export class BlockMenuView {
422
460
  unfreezeMenu: () => {
423
461
  this.menuFrozen = false;
424
462
  },
463
+ setBlockBackgroundColor: (color: string) =>
464
+ this.setBlockBackgroundColor(color),
465
+ setBlockTextColor: (color: string) => this.setBlockTextColor(color),
425
466
  };
426
467
  }
427
468
 
428
469
  getDynamicParams(): BlockSideMenuDynamicParams {
429
- const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();
470
+ const blockContentBoundingBox =
471
+ this.hoveredBlockContent!.getBoundingClientRect();
430
472
 
431
473
  return {
474
+ blockBackgroundColor:
475
+ this.editor.getAttributes("blockContainer").backgroundColor,
476
+ blockTextColor: this.editor.getAttributes("blockContainer").textColor,
432
477
  referenceRect: new DOMRect(
433
478
  this.horizontalPosAnchoredAtRoot
434
- ? getHorizontalAnchor()
435
- : blockBoundingBox.x,
436
- blockBoundingBox.y,
437
- blockBoundingBox.width,
438
- blockBoundingBox.height
479
+ ? this.horizontalPosAnchor
480
+ : blockContentBoundingBox.x,
481
+ blockContentBoundingBox.y,
482
+ blockContentBoundingBox.width,
483
+ blockContentBoundingBox.height
439
484
  ),
440
485
  };
441
486
  }
@@ -8,6 +8,15 @@ export type FormattingToolbarStaticParams = {
8
8
  toggleStrike: () => void;
9
9
  setHyperlink: (url: string, text?: string) => void;
10
10
 
11
+ setTextColor: (color: string) => void;
12
+ setBackgroundColor: (color: string) => void;
13
+ setTextAlignment: (
14
+ textAlignment: "left" | "center" | "right" | "justify"
15
+ ) => void;
16
+
17
+ increaseBlockIndent: () => void;
18
+ decreaseBlockIndent: () => void;
19
+
11
20
  updateBlock: (blockUpdate: BlockUpdate) => void;
12
21
  };
13
22
 
@@ -20,6 +29,13 @@ export type FormattingToolbarDynamicParams = {
20
29
  activeHyperlinkUrl: string;
21
30
  activeHyperlinkText: string;
22
31
 
32
+ textColor: string;
33
+ backgroundColor: string;
34
+ textAlignment: "left" | "center" | "right" | "justify";
35
+
36
+ canIncreaseBlockIndent: boolean;
37
+ canDecreaseBlockIndent: boolean;
38
+
23
39
  block: Block;
24
40
 
25
41
  referenceRect: DOMRect;
@@ -266,6 +266,28 @@ export class FormattingToolbarView {
266
266
  );
267
267
  this.editor.view.focus();
268
268
  },
269
+ setTextColor: (color: string) => {
270
+ this.editor.view.focus();
271
+ this.editor.commands.setTextColor(color);
272
+ },
273
+ setBackgroundColor: (color: string) => {
274
+ this.editor.view.focus();
275
+ this.editor.commands.setBackgroundColor(color);
276
+ },
277
+ setTextAlignment: (
278
+ textAlignment: "left" | "center" | "right" | "justify"
279
+ ) => {
280
+ this.editor.view.focus();
281
+ this.editor.commands.setTextAlignment(textAlignment);
282
+ },
283
+ increaseBlockIndent: () => {
284
+ this.editor.view.focus();
285
+ this.editor.commands.sinkListItem("blockContainer");
286
+ },
287
+ decreaseBlockIndent: () => {
288
+ this.editor.view.focus();
289
+ this.editor.commands.liftListItem("blockContainer");
290
+ },
269
291
  updateBlock: (blockUpdate: BlockUpdate) => {
270
292
  this.editor.view.focus();
271
293
  this.editor.commands.BNUpdateBlock(
@@ -288,13 +310,22 @@ export class FormattingToolbarView {
288
310
  underlineIsActive: this.editor.isActive("underline"),
289
311
  strikeIsActive: this.editor.isActive("strike"),
290
312
  hyperlinkIsActive: this.editor.isActive("link"),
291
- activeHyperlinkUrl: this.editor.getAttributes("link").href
292
- ? this.editor.getAttributes("link").href
293
- : "",
313
+ activeHyperlinkUrl: this.editor.getAttributes("link").href || "",
294
314
  activeHyperlinkText: this.editor.state.doc.textBetween(
295
315
  this.editor.state.selection.from,
296
316
  this.editor.state.selection.to
297
317
  ),
318
+ textColor: this.editor.getAttributes("textColor").color || "default",
319
+ backgroundColor:
320
+ this.editor.getAttributes("backgroundColor").color || "default",
321
+ textAlignment:
322
+ this.editor.getAttributes(blockInfo.contentType).textAlignment ||
323
+ "left",
324
+ canIncreaseBlockIndent:
325
+ this.editor.state.doc
326
+ .resolve(blockInfo.startPos)
327
+ .index(blockInfo.depth - 1) > 0,
328
+ canDecreaseBlockIndent: blockInfo.depth > 2,
298
329
  // Needs type cast as there is no way to create a type that dynamically updates based on which extensions are
299
330
  // loaded by the editor.
300
331
  block: {
@@ -81,7 +81,7 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
81
81
  }
82
82
 
83
83
  // If slash menu is of drag type and active, show the filter placeholder
84
- if (menuState?.type === "drag" && menuState?.active) {
84
+ if (menuState?.triggerCharacter === "" && menuState?.active) {
85
85
  classes.push(this.options.isFilterClass);
86
86
  }
87
87
  // using widget, didn't work (caret position bug)
@@ -31,7 +31,7 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
31
31
  createSuggestionPlugin<SlashMenuItem>({
32
32
  pluginKey: SlashMenuPluginKey,
33
33
  editor: this.editor,
34
- char: "/",
34
+ defaultTriggerCharacter: "/",
35
35
  suggestionsMenuFactory: this.options.slashMenuFactory!,
36
36
  items: (query) => {
37
37
  const commands = [];
@@ -1,49 +1,24 @@
1
1
  import { Editor, Range } from "@tiptap/core";
2
2
  import { SuggestionItem } from "../../shared/plugins/suggestion/SuggestionItem";
3
3
 
4
- export type SlashMenuCallback = (editor: Editor, range: Range) => boolean;
5
-
6
- export enum SlashMenuGroups {
7
- HEADINGS = "Headings",
8
- BASIC_BLOCKS = "Basic Blocks",
9
- CODE = "Code Blocks",
10
-
11
- // Just some examples, that are not currently in use
12
- INLINE = "Inline",
13
- EMBED = "Embed",
14
- PLUGIN = "Plugin",
15
- }
16
-
17
4
  /**
18
5
  * A class that defines a slash command (/<command>).
19
6
  *
20
7
  * Not to be confused with ProseMirror commands nor TipTap commands.
21
8
  */
22
9
  export class SlashMenuItem implements SuggestionItem {
23
- groupName: string;
24
- // other parameters initialized in the constructor
25
-
26
10
  /**
27
11
  * Constructs a new slash-command.
28
12
  *
29
13
  * @param name The name of the command
30
- * @param group Used to organize the menu
31
14
  * @param execute The callback for creating a new node
32
15
  * @param aliases Aliases for this command
33
- * @param icon To be shown next to the name in the menu
34
- * @param hint Short description of command
35
- * @param shortcut Info about keyboard shortcut that would activate this command
36
16
  */
37
17
  constructor(
38
18
  public readonly name: string,
39
- public readonly group: SlashMenuGroups,
40
- public readonly execute: SlashMenuCallback,
41
- public readonly aliases: string[] = [],
42
- public readonly hint?: string,
43
- public readonly shortcut?: string
44
- ) {
45
- this.groupName = group;
46
- }
19
+ public readonly execute: (editor: Editor, range: Range) => void,
20
+ public readonly aliases: string[] = []
21
+ ) {}
47
22
 
48
23
  match(query: string): boolean {
49
24
  return (
@@ -1,5 +1,5 @@
1
- import { formatKeyboardShortcut } from "../../shared/utils";
2
- import { SlashMenuGroups, SlashMenuItem } from "./SlashMenuItem";
1
+ import { SlashMenuItem } from "./SlashMenuItem";
2
+ import { Editor, Range } from "@tiptap/core";
3
3
 
4
4
  /**
5
5
  * An array containing commands for creating all default blocks.
@@ -8,8 +8,7 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
8
8
  // Command for creating a level 1 heading
9
9
  heading: new SlashMenuItem(
10
10
  "Heading",
11
- SlashMenuGroups.HEADINGS,
12
- (editor, range) => {
11
+ (editor: Editor, range: Range) => {
13
12
  return editor
14
13
  .chain()
15
14
  .focus()
@@ -22,16 +21,13 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
22
21
  })
23
22
  .run();
24
23
  },
25
- ["h", "heading1", "h1"],
26
- "Used for a top-level heading",
27
- formatKeyboardShortcut("Mod-Alt-1")
24
+ ["h", "heading1", "h1"]
28
25
  ),
29
26
 
30
27
  // Command for creating a level 2 heading
31
28
  heading2: new SlashMenuItem(
32
29
  "Heading 2",
33
- SlashMenuGroups.HEADINGS,
34
- (editor, range) => {
30
+ (editor: Editor, range: Range) => {
35
31
  return editor
36
32
  .chain()
37
33
  .focus()
@@ -44,16 +40,13 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
44
40
  })
45
41
  .run();
46
42
  },
47
- ["h2", "heading2", "subheading"],
48
- "Used for key sections",
49
- formatKeyboardShortcut("Mod-Alt-2")
43
+ ["h2", "heading2", "subheading"]
50
44
  ),
51
45
 
52
46
  // Command for creating a level 3 heading
53
47
  heading3: new SlashMenuItem(
54
48
  "Heading 3",
55
- SlashMenuGroups.HEADINGS,
56
- (editor, range) => {
49
+ (editor: Editor, range: Range) => {
57
50
  return editor
58
51
  .chain()
59
52
  .focus()
@@ -66,16 +59,13 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
66
59
  })
67
60
  .run();
68
61
  },
69
- ["h3", "heading3", "subheading"],
70
- "Used for subsections and group headings",
71
- formatKeyboardShortcut("Mod-Alt-3")
62
+ ["h3", "heading3", "subheading"]
72
63
  ),
73
64
 
74
65
  // Command for creating an ordered list
75
66
  numberedList: new SlashMenuItem(
76
67
  "Numbered List",
77
- SlashMenuGroups.BASIC_BLOCKS,
78
- (editor, range) => {
68
+ (editor: Editor, range: Range) => {
79
69
  return editor
80
70
  .chain()
81
71
  .focus()
@@ -86,16 +76,13 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
86
76
  })
87
77
  .run();
88
78
  },
89
- ["li", "list", "numberedlist", "numbered list"],
90
- "Used to display a numbered list",
91
- formatKeyboardShortcut("Mod-Shift-7")
79
+ ["li", "list", "numberedlist", "numbered list"]
92
80
  ),
93
81
 
94
82
  // Command for creating a bullet list
95
83
  bulletList: new SlashMenuItem(
96
84
  "Bullet List",
97
- SlashMenuGroups.BASIC_BLOCKS,
98
- (editor, range) => {
85
+ (editor: Editor, range: Range) => {
99
86
  return editor
100
87
  .chain()
101
88
  .focus()
@@ -106,16 +93,13 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
106
93
  })
107
94
  .run();
108
95
  },
109
- ["ul", "list", "bulletlist", "bullet list"],
110
- "Used to display an unordered list",
111
- formatKeyboardShortcut("Mod-Shift-8")
96
+ ["ul", "list", "bulletlist", "bullet list"]
112
97
  ),
113
98
 
114
99
  // Command for creating a paragraph (pretty useless)
115
100
  paragraph: new SlashMenuItem(
116
101
  "Paragraph",
117
- SlashMenuGroups.BASIC_BLOCKS,
118
- (editor, range) => {
102
+ (editor: Editor, range: Range) => {
119
103
  return editor
120
104
  .chain()
121
105
  .focus()
@@ -126,9 +110,7 @@ const defaultCommands: { [key: string]: SlashMenuItem } = {
126
110
  })
127
111
  .run();
128
112
  },
129
- ["p"],
130
- "Used for the body of your document",
131
- formatKeyboardShortcut("Mod-Alt-0")
113
+ ["p"]
132
114
  ),
133
115
 
134
116
  // replaceRangeWithNode(editor, range, node);
@@ -1,11 +1,6 @@
1
1
  import { SlashMenuExtension } from "./SlashMenuExtension";
2
2
  import defaultCommands from "./defaultCommands";
3
- import { SlashMenuGroups, SlashMenuItem } from "./SlashMenuItem";
4
3
 
5
- export {
6
- defaultCommands,
7
- SlashMenuItem as SlashCommand,
8
- SlashMenuGroups as CommandGroup,
9
- };
4
+ export { defaultCommands };
10
5
 
11
6
  export default SlashMenuExtension;