@blocknote/core 0.8.1 → 0.8.3

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 (71) hide show
  1. package/README.md +4 -0
  2. package/dist/blocknote.js +1787 -1834
  3. package/dist/blocknote.js.map +1 -1
  4. package/dist/blocknote.umd.cjs +4 -4
  5. package/dist/blocknote.umd.cjs.map +1 -1
  6. package/dist/style.css +1 -1
  7. package/package.json +3 -3
  8. package/src/BlockNoteEditor.ts +102 -38
  9. package/src/BlockNoteExtensions.ts +1 -58
  10. package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +10 -10
  11. package/src/api/formatConversions/formatConversions.test.ts +587 -605
  12. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +15 -15
  13. package/src/api/nodeConversions/nodeConversions.test.ts +90 -94
  14. package/src/extensions/Blocks/api/blockTypes.ts +3 -2
  15. package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +6 -0
  16. package/src/extensions/Blocks/nodes/BlockContainer.ts +12 -3
  17. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +92 -104
  18. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +178 -134
  19. package/src/extensions/Placeholder/PlaceholderExtension.ts +2 -2
  20. package/src/extensions/{DraggableBlocks/DraggableBlocksPlugin.ts → SideMenu/SideMenuPlugin.ts} +173 -163
  21. package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +7 -30
  22. package/src/extensions/SlashMenu/SlashMenuPlugin.ts +51 -0
  23. package/src/extensions/SlashMenu/defaultSlashMenuItems.ts +109 -0
  24. package/src/extensions/UniqueID/UniqueID.ts +29 -30
  25. package/src/index.ts +9 -8
  26. package/src/node_modules/.vitest/results.json +1 -0
  27. package/src/shared/BaseUiElementTypes.ts +8 -0
  28. package/src/shared/EditorElement.ts +0 -16
  29. package/src/shared/EventEmitter.ts +58 -0
  30. package/src/shared/plugins/suggestion/SuggestionItem.ts +3 -6
  31. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +333 -389
  32. package/types/src/BlockNoteEditor.d.ts +18 -10
  33. package/types/src/BlockNoteExtensions.d.ts +0 -19
  34. package/types/src/EventEmitter.d.ts +11 -0
  35. package/types/src/extensions/Blocks/api/blockTypes.d.ts +3 -2
  36. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +0 -17
  37. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +25 -19
  38. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +2 -3
  39. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +17 -24
  40. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +0 -12
  41. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +37 -10
  42. package/types/src/extensions/SideMenu/MultipleNodeSelection.d.ts +24 -0
  43. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +79 -0
  44. package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +5 -18
  45. package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +13 -0
  46. package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +1 -69
  47. package/types/src/extensions/SlashMenu/index.d.ts +2 -3
  48. package/types/src/index.d.ts +9 -8
  49. package/types/src/shared/BaseUiElementTypes.d.ts +7 -0
  50. package/types/src/shared/EditorElement.d.ts +0 -10
  51. package/types/src/shared/EventEmitter.d.ts +11 -0
  52. package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +2 -7
  53. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +12 -43
  54. package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +1 -1
  55. package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +0 -29
  56. package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +0 -37
  57. package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +0 -37
  58. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +0 -20
  59. package/src/extensions/HyperlinkToolbar/HyperlinkMark.ts +0 -28
  60. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +0 -19
  61. package/src/extensions/SlashMenu/SlashMenuExtension.ts +0 -53
  62. package/src/extensions/SlashMenu/defaultSlashMenuItems.tsx +0 -195
  63. package/src/extensions/SlashMenu/index.ts +0 -5
  64. package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +0 -21
  65. package/types/src/CustomBlock.d.ts +0 -15
  66. package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableCol.d.ts +0 -2
  67. package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableContent.d.ts +0 -2
  68. package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableRow.d.ts +0 -2
  69. package/types/src/extensions/Placeholder/localisation/index.d.ts +0 -2
  70. package/types/src/extensions/Placeholder/localisation/translation.d.ts +0 -51
  71. /package/src/extensions/{DraggableBlocks → SideMenu}/MultipleNodeSelection.ts +0 -0
@@ -0,0 +1,109 @@
1
+ import { BlockNoteEditor } from "../../BlockNoteEditor";
2
+ import { BlockSchema, PartialBlock } from "../Blocks/api/blockTypes";
3
+ import { BaseSlashMenuItem } from "./BaseSlashMenuItem";
4
+ import { defaultBlockSchema } from "../Blocks/api/defaultBlocks";
5
+
6
+ function insertOrUpdateBlock<BSchema extends BlockSchema>(
7
+ editor: BlockNoteEditor<BSchema>,
8
+ block: PartialBlock<BSchema>
9
+ ) {
10
+ const currentBlock = editor.getTextCursorPosition().block;
11
+
12
+ if (
13
+ (currentBlock.content.length === 1 &&
14
+ currentBlock.content[0].type === "text" &&
15
+ currentBlock.content[0].text === "/") ||
16
+ currentBlock.content.length === 0
17
+ ) {
18
+ editor.updateBlock(currentBlock, block);
19
+ } else {
20
+ editor.insertBlocks([block], currentBlock, "after");
21
+ editor.setTextCursorPosition(editor.getTextCursorPosition().nextBlock!);
22
+ }
23
+ }
24
+
25
+ export const getDefaultSlashMenuItems = <BSchema extends BlockSchema>(
26
+ // This type casting is weird, but it's the best way of doing it, as it allows
27
+ // the schema type to be automatically inferred if it is defined, or be
28
+ // inferred as any if it is not defined. I don't think it's possible to make it
29
+ // infer to DefaultBlockSchema if it is not defined.
30
+ schema: BSchema = defaultBlockSchema as unknown as BSchema
31
+ ) => {
32
+ const slashMenuItems: BaseSlashMenuItem<BSchema>[] = [];
33
+
34
+ if ("heading" in schema && "level" in schema.heading.propSchema) {
35
+ // Command for creating a level 1 heading
36
+ if (schema.heading.propSchema.level.values?.includes("1")) {
37
+ slashMenuItems.push({
38
+ name: "Heading",
39
+ aliases: ["h", "heading1", "h1"],
40
+ execute: (editor) =>
41
+ insertOrUpdateBlock(editor, {
42
+ type: "heading",
43
+ props: { level: "1" },
44
+ } as PartialBlock<BSchema>),
45
+ });
46
+ }
47
+
48
+ // Command for creating a level 2 heading
49
+ if (schema.heading.propSchema.level.values?.includes("2")) {
50
+ slashMenuItems.push({
51
+ name: "Heading 2",
52
+ aliases: ["h2", "heading2", "subheading"],
53
+ execute: (editor) =>
54
+ insertOrUpdateBlock(editor, {
55
+ type: "heading",
56
+ props: { level: "2" },
57
+ } as PartialBlock<BSchema>),
58
+ });
59
+ }
60
+
61
+ // Command for creating a level 3 heading
62
+ if (schema.heading.propSchema.level.values?.includes("3")) {
63
+ slashMenuItems.push({
64
+ name: "Heading 3",
65
+ aliases: ["h3", "heading3", "subheading"],
66
+ execute: (editor) =>
67
+ insertOrUpdateBlock(editor, {
68
+ type: "heading",
69
+ props: { level: "3" },
70
+ } as PartialBlock<BSchema>),
71
+ });
72
+ }
73
+ }
74
+
75
+ if ("bulletListItem" in schema) {
76
+ slashMenuItems.push({
77
+ name: "Bullet List",
78
+ aliases: ["ul", "list", "bulletlist", "bullet list"],
79
+ execute: (editor) =>
80
+ insertOrUpdateBlock(editor, {
81
+ type: "bulletListItem",
82
+ } as PartialBlock<BSchema>),
83
+ });
84
+ }
85
+
86
+ if ("numberedListItem" in schema) {
87
+ slashMenuItems.push({
88
+ name: "Numbered List",
89
+ aliases: ["li", "list", "numberedlist", "numbered list"],
90
+ execute: (editor) =>
91
+ insertOrUpdateBlock(editor, {
92
+ type: "numberedListItem",
93
+ } as PartialBlock<BSchema>),
94
+ });
95
+ }
96
+
97
+ if ("paragraph" in schema) {
98
+ slashMenuItems.push({
99
+ name: "Paragraph",
100
+ aliases: ["p"],
101
+ execute: (editor) =>
102
+ insertOrUpdateBlock(editor, {
103
+ type: "paragraph",
104
+ } as PartialBlock<BSchema>),
105
+ });
106
+ }
107
+
108
+ return slashMenuItems;
109
+ };
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  combineTransactionSteps,
3
3
  Extension,
4
- findChildren,
5
4
  findChildrenInRange,
6
5
  getChangedRanges,
7
6
  } from "@tiptap/core";
@@ -87,35 +86,35 @@ const UniqueID = Extension.create({
87
86
  ];
88
87
  },
89
88
  // check initial content for missing ids
90
- onCreate() {
91
- // Don’t do this when the collaboration extension is active
92
- // because this may update the content, so Y.js tries to merge these changes.
93
- // This leads to empty block nodes.
94
- // See: https://github.com/ueberdosis/tiptap/issues/2400
95
- if (
96
- this.editor.extensionManager.extensions.find(
97
- (extension) => extension.name === "collaboration"
98
- )
99
- ) {
100
- return;
101
- }
102
- const { view, state } = this.editor;
103
- const { tr, doc } = state;
104
- const { types, attributeName, generateID } = this.options;
105
- const nodesWithoutId = findChildren(doc, (node) => {
106
- return (
107
- types.includes(node.type.name) && node.attrs[attributeName] === null
108
- );
109
- });
110
- nodesWithoutId.forEach(({ node, pos }) => {
111
- tr.setNodeMarkup(pos, undefined, {
112
- ...node.attrs,
113
- [attributeName]: generateID(),
114
- });
115
- });
116
- tr.setMeta("addToHistory", false);
117
- view.dispatch(tr);
118
- },
89
+ // onCreate() {
90
+ // // Don’t do this when the collaboration extension is active
91
+ // // because this may update the content, so Y.js tries to merge these changes.
92
+ // // This leads to empty block nodes.
93
+ // // See: https://github.com/ueberdosis/tiptap/issues/2400
94
+ // if (
95
+ // this.editor.extensionManager.extensions.find(
96
+ // (extension) => extension.name === "collaboration"
97
+ // )
98
+ // ) {
99
+ // return;
100
+ // }
101
+ // const { view, state } = this.editor;
102
+ // const { tr, doc } = state;
103
+ // const { types, attributeName, generateID } = this.options;
104
+ // const nodesWithoutId = findChildren(doc, (node) => {
105
+ // return (
106
+ // types.includes(node.type.name) && node.attrs[attributeName] === null
107
+ // );
108
+ // });
109
+ // nodesWithoutId.forEach(({ node, pos }) => {
110
+ // tr.setNodeMarkup(pos, undefined, {
111
+ // ...node.attrs,
112
+ // [attributeName]: generateID(),
113
+ // });
114
+ // });
115
+ // tr.setMeta("addToHistory", false);
116
+ // view.dispatch(tr);
117
+ // },
119
118
  addProseMirrorPlugins() {
120
119
  let dragSourceElement: any = null;
121
120
  let transformPasted = false;
package/src/index.ts CHANGED
@@ -3,14 +3,15 @@ export * from "./BlockNoteExtensions";
3
3
  export * from "./extensions/Blocks/api/block";
4
4
  export * from "./extensions/Blocks/api/blockTypes";
5
5
  export * from "./extensions/Blocks/api/defaultBlocks";
6
- export * from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
7
- export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
8
- export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
9
- export { defaultSlashMenuItems } from "./extensions/SlashMenu/defaultSlashMenuItems";
10
- export * from "./extensions/SlashMenu/BaseSlashMenuItem";
11
- export * from "./shared/EditorElement";
12
- export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
13
- export * from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
14
6
  export * from "./extensions/Blocks/api/inlineContentTypes";
15
7
  export * from "./extensions/Blocks/api/serialization";
16
8
  export * as blockStyles from "./extensions/Blocks/nodes/Block.module.css";
9
+ export * from "./extensions/FormattingToolbar/FormattingToolbarPlugin";
10
+ export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin";
11
+ export * from "./extensions/SideMenu/SideMenuPlugin";
12
+ export * from "./extensions/SlashMenu/BaseSlashMenuItem";
13
+ export * from "./extensions/SlashMenu/SlashMenuPlugin";
14
+ export { getDefaultSlashMenuItems } from "./extensions/SlashMenu/defaultSlashMenuItems";
15
+ export * from "./shared/BaseUiElementTypes";
16
+ export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
17
+ export * from "./shared/plugins/suggestion/SuggestionPlugin";
@@ -0,0 +1 @@
1
+ {"version":"0.28.5","results":[["/api/formatConversions/formatConversions.test.ts",{"duration":109,"failed":false}],["/api/nodeConversions/nodeConversions.test.ts",{"duration":32,"failed":false}],["/api/blockManipulation/blockManipulation.test.ts",{"duration":38,"failed":false}],["/BlockNoteEditor.test.ts",{"duration":4,"failed":false}]]}
@@ -0,0 +1,8 @@
1
+ export type BaseUiElementCallbacks = {
2
+ destroy: () => void;
3
+ };
4
+
5
+ export type BaseUiElementState = {
6
+ show: boolean;
7
+ referencePos: DOMRect;
8
+ };
@@ -1,16 +0,0 @@
1
- export type RequiredStaticParams = Record<string, any>;
2
- export type RequiredDynamicParams = Record<string, any> & {
3
- referenceRect: DOMRect;
4
- };
5
-
6
- export type EditorElement<ElementDynamicParams extends RequiredDynamicParams> =
7
- {
8
- element: HTMLElement | undefined;
9
- render: (params: ElementDynamicParams, isHidden: boolean) => void;
10
- hide: () => void;
11
- };
12
-
13
- export type ElementFactory<
14
- ElementStaticParams extends RequiredStaticParams,
15
- ElementDynamicParams extends RequiredDynamicParams
16
- > = (staticParams: ElementStaticParams) => EditorElement<ElementDynamicParams>;
@@ -0,0 +1,58 @@
1
+ // from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)
2
+
3
+ type StringKeyOf<T> = Extract<keyof T, string>;
4
+ type CallbackType<
5
+ T extends Record<string, any>,
6
+ EventName extends StringKeyOf<T>
7
+ > = T[EventName] extends any[] ? T[EventName] : [T[EventName]];
8
+ type CallbackFunction<
9
+ T extends Record<string, any>,
10
+ EventName extends StringKeyOf<T>
11
+ > = (...props: CallbackType<T, EventName>) => any;
12
+
13
+ export class EventEmitter<T extends Record<string, any>> {
14
+ private callbacks: { [key: string]: Function[] } = {};
15
+
16
+ public on<EventName extends StringKeyOf<T>>(
17
+ event: EventName,
18
+ fn: CallbackFunction<T, EventName>
19
+ ) {
20
+ if (!this.callbacks[event]) {
21
+ this.callbacks[event] = [];
22
+ }
23
+
24
+ this.callbacks[event].push(fn);
25
+
26
+ return () => this.off(event, fn);
27
+ }
28
+
29
+ protected emit<EventName extends StringKeyOf<T>>(
30
+ event: EventName,
31
+ ...args: CallbackType<T, EventName>
32
+ ) {
33
+ const callbacks = this.callbacks[event];
34
+
35
+ if (callbacks) {
36
+ callbacks.forEach((callback) => callback.apply(this, args));
37
+ }
38
+ }
39
+
40
+ public off<EventName extends StringKeyOf<T>>(
41
+ event: EventName,
42
+ fn?: CallbackFunction<T, EventName>
43
+ ) {
44
+ const callbacks = this.callbacks[event];
45
+
46
+ if (callbacks) {
47
+ if (fn) {
48
+ this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
49
+ } else {
50
+ delete this.callbacks[event];
51
+ }
52
+ }
53
+ }
54
+
55
+ protected removeAllListeners(): void {
56
+ this.callbacks = {};
57
+ }
58
+ }
@@ -1,6 +1,3 @@
1
- /**
2
- * A generic interface used in all suggestion menus (slash menu, mentions, etc)
3
- */
4
- export class SuggestionItem {
5
- constructor(public name: string, public match: (query: string) => boolean) {}
6
- }
1
+ export type SuggestionItem = {
2
+ name: string;
3
+ };