@blocknote/core 0.1.2 → 0.2.1-alpha.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 (171) hide show
  1. package/README.md +12 -6
  2. package/dist/blocknote.js +1425 -5109
  3. package/dist/blocknote.js.map +1 -1
  4. package/dist/blocknote.umd.cjs +1 -53
  5. package/dist/blocknote.umd.cjs.map +1 -1
  6. package/dist/style.css +1 -1
  7. package/package.json +19 -32
  8. package/src/BlockNoteEditor.ts +54 -0
  9. package/src/BlockNoteExtensions.ts +52 -7
  10. package/src/assets/fonts-inter.css +92 -0
  11. package/src/editor.module.css +37 -0
  12. package/src/extensions/Blocks/BlockAttributes.ts +1 -3
  13. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +71 -18
  14. package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +66 -0
  15. package/src/extensions/Blocks/index.ts +7 -3
  16. package/src/extensions/Blocks/nodes/Block.module.css +116 -74
  17. package/src/extensions/Blocks/nodes/Block.ts +413 -292
  18. package/src/extensions/Blocks/nodes/BlockGroup.ts +6 -6
  19. package/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.ts +84 -0
  20. package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts +177 -0
  21. package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts +77 -0
  22. package/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.ts +34 -0
  23. package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +20 -0
  24. package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +27 -9
  25. package/src/extensions/DraggableBlocks/{DraggableBlocksPlugin.tsx → DraggableBlocksPlugin.ts} +227 -147
  26. package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +29 -0
  27. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +35 -0
  28. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +308 -0
  29. package/src/extensions/HyperlinkToolbar/HyperlinkMark.ts +28 -0
  30. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +19 -0
  31. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +251 -0
  32. package/src/extensions/Placeholder/PlaceholderExtension.ts +5 -2
  33. package/src/extensions/SlashMenu/SlashMenuExtension.ts +9 -1
  34. package/src/extensions/SlashMenu/SlashMenuItem.ts +1 -3
  35. package/src/extensions/SlashMenu/defaultCommands.tsx +33 -22
  36. package/src/extensions/TrailingNode/TrailingNodeExtension.ts +4 -4
  37. package/src/extensions/UniqueID/UniqueID.ts +14 -1
  38. package/src/index.ts +8 -4
  39. package/src/shared/EditorElement.ts +10 -0
  40. package/src/shared/plugins/suggestion/SuggestionItem.ts +1 -8
  41. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +222 -101
  42. package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +21 -0
  43. package/src/{utils.ts → shared/utils.ts} +0 -0
  44. package/types/src/BlockNoteEditor.d.ts +13 -0
  45. package/types/src/BlockNoteExtensions.d.ts +12 -1
  46. package/types/src/EditorElement.d.ts +7 -0
  47. package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +1 -1
  48. package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +19 -0
  49. package/types/src/extensions/Blocks/nodes/Block.d.ts +11 -19
  50. package/types/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.d.ts +8 -0
  51. package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.d.ts +8 -0
  52. package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.d.ts +2 -0
  53. package/types/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.d.ts +6 -0
  54. package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +4 -1
  55. package/types/src/extensions/BubbleMenu/BubbleMenuFactoryTypes.d.ts +27 -0
  56. package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +10 -12
  57. package/types/src/extensions/DraggableBlocks/BlockMenuFactoryTypes.d.ts +12 -0
  58. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +14 -0
  59. package/types/src/extensions/DraggableBlocks/DragMenuFactoryTypes.d.ts +18 -0
  60. package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +9 -3
  61. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +23 -1
  62. package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +8 -0
  63. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +23 -0
  64. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +43 -0
  65. package/types/src/extensions/HyperlinkToolbar/HyperlinkMark.d.ts +8 -0
  66. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +12 -0
  67. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +11 -0
  68. package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +2 -1
  69. package/types/src/extensions/Hyperlinks/HyperlinkMenuFactoryTypes.d.ts +11 -0
  70. package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +10 -1
  71. package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +3 -1
  72. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -4
  73. package/types/src/index.d.ts +8 -3
  74. package/types/src/shared/EditorElement.d.ts +6 -0
  75. package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +1 -6
  76. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +15 -10
  77. package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +12 -0
  78. package/types/src/shared/utils.d.ts +2 -0
  79. package/types/src/utils.d.ts +2 -2
  80. package/src/BlockNoteTheme.ts +0 -150
  81. package/src/EditorContent.tsx +0 -2
  82. package/src/extensions/Blocks/OrderedListPlugin.ts +0 -46
  83. package/src/extensions/Blocks/commands/joinBackward.ts +0 -274
  84. package/src/extensions/Blocks/helpers/setBlockHeading.ts +0 -30
  85. package/src/extensions/Blocks/nodes/Content.ts +0 -63
  86. package/src/extensions/Blocks/rule.ts +0 -48
  87. package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +0 -36
  88. package/src/extensions/BubbleMenu/BubbleMenuPlugin.ts +0 -245
  89. package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +0 -240
  90. package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +0 -67
  91. package/src/extensions/DraggableBlocks/components/DragHandle.tsx +0 -102
  92. package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +0 -19
  93. package/src/extensions/Hyperlinks/HyperlinkMark.tsx +0 -16
  94. package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +0 -165
  95. package/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.tsx +0 -44
  96. package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.tsx +0 -34
  97. package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.tsx +0 -31
  98. package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.tsx +0 -40
  99. package/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.tsx +0 -37
  100. package/src/extensions/Hyperlinks/menus/HyperlinkMenu.tsx +0 -63
  101. package/src/fonts-inter.css +0 -94
  102. package/src/globals.css +0 -28
  103. package/src/root.module.css +0 -19
  104. package/src/shared/components/toolbar/Toolbar.tsx +0 -10
  105. package/src/shared/components/toolbar/ToolbarButton.tsx +0 -57
  106. package/src/shared/components/toolbar/ToolbarDropdown.tsx +0 -35
  107. package/src/shared/components/toolbar/ToolbarDropdownItem.tsx +0 -35
  108. package/src/shared/components/toolbar/ToolbarDropdownTarget.tsx +0 -31
  109. package/src/shared/components/tooltip/TooltipContent.module.css +0 -15
  110. package/src/shared/components/tooltip/TooltipContent.tsx +0 -23
  111. package/src/shared/hooks/useEditorForceUpdate.tsx +0 -30
  112. package/src/shared/plugins/suggestion/SuggestionListReactRenderer.tsx +0 -236
  113. package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +0 -47
  114. package/src/shared/plugins/suggestion/components/SuggestionGroupItem.tsx +0 -82
  115. package/src/shared/plugins/suggestion/components/SuggestionList.tsx +0 -92
  116. package/src/useEditor.ts +0 -51
  117. package/types/src/BlockNoteTheme.d.ts +0 -2
  118. package/types/src/EditorContent.d.ts +0 -1
  119. package/types/src/commands/indentation.d.ts +0 -2
  120. package/types/src/extensions/Blocks/OrderedListPlugin.d.ts +0 -2
  121. package/types/src/extensions/Blocks/commands/joinBackward.d.ts +0 -14
  122. package/types/src/extensions/Blocks/helpers/setBlockHeading.d.ts +0 -5
  123. package/types/src/extensions/Blocks/nodes/Content.d.ts +0 -5
  124. package/types/src/extensions/Blocks/rule.d.ts +0 -16
  125. package/types/src/extensions/BubbleMenu/component/BubbleMenu.d.ts +0 -5
  126. package/types/src/extensions/BubbleMenu/component/DropdownBlockItem.d.ts +0 -10
  127. package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +0 -11
  128. package/types/src/extensions/DraggableBlocks/components/DragHandle.d.ts +0 -12
  129. package/types/src/extensions/DraggableBlocks/components/DragHandleMenu.d.ts +0 -6
  130. package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.d.ts +0 -11
  131. package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.d.ts +0 -13
  132. package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.d.ts +0 -8
  133. package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.d.ts +0 -9
  134. package/types/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.d.ts +0 -12
  135. package/types/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.d.ts +0 -12
  136. package/types/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.d.ts +0 -10
  137. package/types/src/extensions/Hyperlinks/menus/HyperlinkMenu.d.ts +0 -21
  138. package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.d.ts +0 -39
  139. package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.d.ts +0 -1
  140. package/types/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.d.ts +0 -11
  141. package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInput.d.ts +0 -39
  142. package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInputStyles.d.ts +0 -3
  143. package/types/src/extensions/Hyperlinks/menus/helpers/ToolbarComponent.d.ts +0 -13
  144. package/types/src/extensions/helpers/formatKeyboardShortcut.d.ts +0 -1
  145. package/types/src/lib/atlaskit/browser.d.ts +0 -12
  146. package/types/src/nodes/ChildgroupNode.d.ts +0 -28
  147. package/types/src/nodes/patchNodes.d.ts +0 -1
  148. package/types/src/plugins/TreeViewPlugin/index.d.ts +0 -2
  149. package/types/src/plugins/animation.d.ts +0 -2
  150. package/types/src/react/BlockNoteComposer.d.ts +0 -17
  151. package/types/src/react/BlockNotePlugin.d.ts +0 -1
  152. package/types/src/react/index.d.ts +0 -3
  153. package/types/src/react/useBlockNoteSetup.d.ts +0 -2
  154. package/types/src/registerBlockNote.d.ts +0 -2
  155. package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +0 -15
  156. package/types/src/shared/components/toolbar/SimpleToolbarDropdown.d.ts +0 -11
  157. package/types/src/shared/components/toolbar/SimpleToolbarDropdownItem.d.ts +0 -11
  158. package/types/src/shared/components/toolbar/Toolbar.d.ts +0 -4
  159. package/types/src/shared/components/toolbar/ToolbarButton.d.ts +0 -15
  160. package/types/src/shared/components/toolbar/ToolbarDropdown.d.ts +0 -17
  161. package/types/src/shared/components/toolbar/ToolbarDropdownItem.d.ts +0 -11
  162. package/types/src/shared/components/toolbar/ToolbarDropdownTarget.d.ts +0 -8
  163. package/types/src/shared/components/toolbar/ToolbarSeparator.d.ts +0 -2
  164. package/types/src/shared/components/tooltip/TooltipContent.d.ts +0 -15
  165. package/types/src/shared/hooks/useEditorForceUpdate.d.ts +0 -2
  166. package/types/src/shared/plugins/suggestion/SuggestionListReactRenderer.d.ts +0 -71
  167. package/types/src/shared/plugins/suggestion/components/SuggestionGroup.d.ts +0 -23
  168. package/types/src/shared/plugins/suggestion/components/SuggestionGroupItem.d.ts +0 -9
  169. package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +0 -11
  170. package/types/src/themes/BlockNoteEditorTheme.d.ts +0 -11
  171. package/types/src/useEditor.d.ts +0 -11
@@ -2,7 +2,7 @@ import { mergeAttributes, Node } from "@tiptap/core";
2
2
  import styles from "./Block.module.css";
3
3
 
4
4
  export const BlockGroup = Node.create({
5
- name: "blockgroup",
5
+ name: "blockGroup",
6
6
 
7
7
  addOptions() {
8
8
  return {
@@ -17,18 +17,18 @@ export const BlockGroup = Node.create({
17
17
  {
18
18
  tag: "div",
19
19
  getAttrs: (element) => {
20
- if(typeof element === "string") {
20
+ if (typeof element === "string") {
21
21
  return false;
22
22
  }
23
23
 
24
- if(element.getAttribute("data-node-type") === "block-group") {
24
+ if (element.getAttribute("data-node-type") === "block-group") {
25
25
  // Null means the element matches, but we don't want to add any attributes to the node.
26
26
  return null;
27
27
  }
28
28
 
29
29
  return false;
30
- }
31
- }
30
+ },
31
+ },
32
32
  ];
33
33
  },
34
34
 
@@ -37,7 +37,7 @@ export const BlockGroup = Node.create({
37
37
  "div",
38
38
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
39
39
  class: styles.blockGroup,
40
- "data-node-type": "block-group"
40
+ "data-node-type": "block-group",
41
41
  }),
42
42
  0,
43
43
  ];
@@ -0,0 +1,84 @@
1
+ import { InputRule, mergeAttributes, Node } from "@tiptap/core";
2
+ import styles from "../../Block.module.css";
3
+
4
+ export type HeadingContentType = {
5
+ name: "headingContent";
6
+ attrs?: {
7
+ headingLevel: string;
8
+ };
9
+ };
10
+
11
+ export const HeadingContent = Node.create({
12
+ name: "headingContent",
13
+ group: "blockContent",
14
+ content: "inline*",
15
+
16
+ addAttributes() {
17
+ return {
18
+ headingLevel: {
19
+ default: "1",
20
+ // instead of "level" attributes, use "data-level"
21
+ parseHTML: (element) => element.getAttribute("data-heading-level"),
22
+ renderHTML: (attributes) => {
23
+ return {
24
+ "data-heading-level": attributes.headingLevel,
25
+ };
26
+ },
27
+ },
28
+ };
29
+ },
30
+
31
+ addInputRules() {
32
+ return [
33
+ ...["1", "2", "3"].map((level) => {
34
+ // Creates a heading of appropriate level when starting with "#", "##", or "###".
35
+ return new InputRule({
36
+ find: new RegExp(`^(#{${parseInt(level)}})\\s$`),
37
+ handler: ({ state, chain, range }) => {
38
+ chain()
39
+ .BNSetContentType(state.selection.from, {
40
+ name: "headingContent",
41
+ attrs: {
42
+ headingLevel: level,
43
+ },
44
+ })
45
+ // Removes the "#" character(s) used to set the heading.
46
+ .deleteRange({ from: range.from, to: range.to });
47
+ },
48
+ });
49
+ }),
50
+ ];
51
+ },
52
+
53
+ parseHTML() {
54
+ return [
55
+ {
56
+ tag: "h1",
57
+ attrs: { headingLevel: "1" },
58
+ node: "block",
59
+ },
60
+ {
61
+ tag: "h2",
62
+ attrs: { headingLevel: "2" },
63
+ node: "block",
64
+ },
65
+ {
66
+ tag: "h3",
67
+ attrs: { headingLevel: "3" },
68
+ node: "block",
69
+ },
70
+ ];
71
+ },
72
+
73
+ renderHTML({ node, HTMLAttributes }) {
74
+ console.log(node.attrs);
75
+ return [
76
+ "div",
77
+ mergeAttributes(HTMLAttributes, {
78
+ class: styles.blockContent,
79
+ "data-content-type": this.name,
80
+ }),
81
+ ["h" + node.attrs["headingLevel"], 0],
82
+ ];
83
+ },
84
+ });
@@ -0,0 +1,177 @@
1
+ import { InputRule, mergeAttributes, Node } from "@tiptap/core";
2
+ import { OrderedListItemIndexPlugin } from "./OrderedListItemIndexPlugin";
3
+ import { getBlockInfoFromPos } from "../../../helpers/getBlockInfoFromPos";
4
+ import styles from "../../Block.module.css";
5
+
6
+ export type ListItemContentType = {
7
+ name: "listItemContent";
8
+ attrs?: {
9
+ listItemType: string;
10
+ };
11
+ };
12
+
13
+ export const ListItemContent = Node.create({
14
+ name: "listItemContent",
15
+ group: "blockContent",
16
+ content: "inline*",
17
+
18
+ addAttributes() {
19
+ return {
20
+ listItemType: {
21
+ default: "unordered",
22
+ parseHTML: (element) => element.getAttribute("data-list-item-type"),
23
+ renderHTML: (attributes) => {
24
+ return {
25
+ "data-list-item-type": attributes.listItemType,
26
+ };
27
+ },
28
+ },
29
+ listItemIndex: {
30
+ default: null,
31
+ parseHTML: (element) => element.getAttribute("data-list-item-index"),
32
+ renderHTML: (attributes) => {
33
+ return {
34
+ "data-list-item-index": attributes.listItemIndex,
35
+ };
36
+ },
37
+ },
38
+ };
39
+ },
40
+
41
+ addInputRules() {
42
+ return [
43
+ // Creates an unordered list when starting with "-", "+", or "*".
44
+ new InputRule({
45
+ find: new RegExp(`^[-+*]\\s$`),
46
+ handler: ({ state, chain, range }) => {
47
+ chain()
48
+ .BNSetContentType(state.selection.from, {
49
+ name: "listItemContent",
50
+ attrs: {
51
+ listItemType: "unordered",
52
+ },
53
+ })
54
+ // Removes the "-", "+", or "*" character used to set the list.
55
+ .deleteRange({ from: range.from, to: range.to });
56
+ },
57
+ }),
58
+ // Creates an ordered list when starting with "1.".
59
+ new InputRule({
60
+ find: new RegExp(`^1\\.\\s$`),
61
+ handler: ({ state, chain, range }) => {
62
+ chain()
63
+ .BNSetContentType(state.selection.from, {
64
+ name: "listItemContent",
65
+ attrs: {
66
+ listItemType: "ordered",
67
+ },
68
+ })
69
+ // Removes the "1." characters used to set the list.
70
+ .deleteRange({ from: range.from, to: range.to });
71
+ },
72
+ }),
73
+ ];
74
+ },
75
+
76
+ addKeyboardShortcuts() {
77
+ const handleEnter = () => {
78
+ const { node, contentType } = getBlockInfoFromPos(
79
+ this.editor.state.doc,
80
+ this.editor.state.selection.from
81
+ )!;
82
+
83
+ const selectionEmpty =
84
+ this.editor.state.selection.anchor === this.editor.state.selection.head;
85
+
86
+ if (contentType.name !== "listItemContent" || !selectionEmpty) {
87
+ return false;
88
+ }
89
+
90
+ return this.editor.commands.first(({ state, chain, commands }) => [
91
+ () =>
92
+ // Changes list item block to a text block if both the content is empty.
93
+ commands.command(() => {
94
+ if (node.textContent.length === 0) {
95
+ return commands.BNSetContentType(state.selection.from, {
96
+ name: "textContent",
97
+ });
98
+ }
99
+
100
+ return false;
101
+ }),
102
+
103
+ () =>
104
+ // Splits the current block, moving content inside that's after the cursor to a new block of the same type
105
+ // below.
106
+ commands.command(() => {
107
+ if (node.textContent.length > 0) {
108
+ chain()
109
+ .deleteSelection()
110
+ .BNSplitBlock(state.selection.from, true)
111
+ .run();
112
+
113
+ return true;
114
+ }
115
+
116
+ return false;
117
+ }),
118
+ ]);
119
+ };
120
+
121
+ return {
122
+ Enter: handleEnter,
123
+ };
124
+ },
125
+
126
+ addProseMirrorPlugins() {
127
+ return [OrderedListItemIndexPlugin()];
128
+ },
129
+
130
+ parseHTML() {
131
+ return [
132
+ {
133
+ tag: "li",
134
+ getAttrs: (element) => {
135
+ if (typeof element === "string") {
136
+ return false;
137
+ }
138
+
139
+ const parent = element.parentElement;
140
+
141
+ if (parent === null) {
142
+ return false;
143
+ }
144
+
145
+ // Case for BlockNote list structure.
146
+ // Gets type of list item (ordered/unordered) based on the block content's listItemType attribute.
147
+ if (parent.getAttribute("data-content-type") === "listItemContent") {
148
+ return { listItemType: parent.getAttribute("data-list-item-type") };
149
+ }
150
+
151
+ // Case for regular HTML list structure.
152
+ // Gets type of list item (ordered/unordered) based on parent element's tag ("ol"/"ul").
153
+ if (parent.tagName === "UL") {
154
+ return { listItemType: "unordered" };
155
+ }
156
+ if (parent.tagName === "OL") {
157
+ return { listItemType: "ordered" };
158
+ }
159
+
160
+ return false;
161
+ },
162
+ node: "block",
163
+ },
164
+ ];
165
+ },
166
+
167
+ renderHTML({ HTMLAttributes }) {
168
+ return [
169
+ "div",
170
+ mergeAttributes(HTMLAttributes, {
171
+ class: styles.blockContent,
172
+ "data-content-type": this.name,
173
+ }),
174
+ ["li", 0],
175
+ ];
176
+ },
177
+ });
@@ -0,0 +1,77 @@
1
+ import { Plugin, PluginKey } from "prosemirror-state";
2
+ import { getBlockInfoFromPos } from "../../../helpers/getBlockInfoFromPos";
3
+
4
+ // ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.
5
+ const PLUGIN_KEY = new PluginKey(`ordered-list-item-index`);
6
+ export const OrderedListItemIndexPlugin = () => {
7
+ return new Plugin({
8
+ key: PLUGIN_KEY,
9
+ appendTransaction: (_transactions, _oldState, newState) => {
10
+ const tr = newState.tr;
11
+ tr.setMeta("orderedListIndexing", true);
12
+
13
+ let modified = false;
14
+
15
+ // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the
16
+ // same order they appear. This means the index of each list item block can be calculated by incrementing the
17
+ // index of the previous list item block.
18
+ newState.doc.descendants((node, pos) => {
19
+ if (
20
+ node.type.name === "block" &&
21
+ node.firstChild!.type.name === "listItemContent" &&
22
+ node.firstChild!.attrs["listItemType"] === "ordered"
23
+ ) {
24
+ let newIndex = "1";
25
+ const isFirstBlockInDoc = pos === 1;
26
+
27
+ const blockInfo = getBlockInfoFromPos(tr.doc, pos + 1)!;
28
+ if (blockInfo === undefined) {
29
+ return;
30
+ }
31
+
32
+ // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the
33
+ // first block in its nesting level, or the previous block is not an ordered list item.
34
+ if (!isFirstBlockInDoc) {
35
+ const prevBlockInfo = getBlockInfoFromPos(tr.doc, pos - 2)!;
36
+ if (prevBlockInfo === undefined) {
37
+ return;
38
+ }
39
+
40
+ const isFirstBlockInNestingLevel =
41
+ blockInfo.depth !== prevBlockInfo.depth;
42
+
43
+ if (!isFirstBlockInNestingLevel) {
44
+ const prevBlockContentNode = prevBlockInfo.contentNode;
45
+ const prevBlockContentType = prevBlockInfo.contentType;
46
+
47
+ const isPrevBlockOrderedListItem =
48
+ prevBlockContentType.name === "listItemContent" &&
49
+ prevBlockContentNode.attrs["listItemType"] === "ordered";
50
+
51
+ if (isPrevBlockOrderedListItem) {
52
+ const prevBlockIndex =
53
+ prevBlockContentNode.attrs["listItemIndex"];
54
+
55
+ newIndex = (parseInt(prevBlockIndex) + 1).toString();
56
+ }
57
+ }
58
+ }
59
+
60
+ const contentNode = blockInfo.contentNode;
61
+ const index = contentNode.attrs["listItemIndex"];
62
+
63
+ if (index !== newIndex) {
64
+ modified = true;
65
+
66
+ tr.setNodeMarkup(pos + 1, undefined, {
67
+ listItemType: "ordered",
68
+ listItemIndex: newIndex,
69
+ });
70
+ }
71
+ }
72
+ });
73
+
74
+ return modified ? tr : null;
75
+ },
76
+ });
77
+ };
@@ -0,0 +1,34 @@
1
+ import { Node } from "@tiptap/core";
2
+ import styles from "../../Block.module.css";
3
+
4
+ export type TextContentType = {
5
+ name: "textContent";
6
+ attrs?: {};
7
+ };
8
+
9
+ export const TextContent = Node.create({
10
+ name: "textContent",
11
+ group: "blockContent",
12
+ content: "inline*",
13
+
14
+ parseHTML() {
15
+ return [
16
+ {
17
+ tag: "p",
18
+ priority: 200,
19
+ node: "block",
20
+ },
21
+ ];
22
+ },
23
+
24
+ renderHTML() {
25
+ return [
26
+ "div",
27
+ {
28
+ class: styles.blockContent,
29
+ "data-content-type": this.name,
30
+ },
31
+ ["p", 0],
32
+ ];
33
+ },
34
+ });
@@ -0,0 +1,20 @@
1
+ import { EditorElement, ElementFactory } from "../../shared/EditorElement";
2
+
3
+ export type BlockSideMenuStaticParams = {
4
+ addBlock: () => void;
5
+ deleteBlock: () => void;
6
+ blockDragStart: (event: DragEvent) => void;
7
+ blockDragEnd: () => void;
8
+ freezeMenu: () => void;
9
+ unfreezeMenu: () => void;
10
+ };
11
+
12
+ export type BlockSideMenuDynamicParams = {
13
+ blockBoundingBox: DOMRect;
14
+ };
15
+
16
+ export type BlockSideMenu = EditorElement<BlockSideMenuDynamicParams>;
17
+ export type BlockSideMenuFactory = ElementFactory<
18
+ BlockSideMenuStaticParams,
19
+ BlockSideMenuDynamicParams
20
+ >;
@@ -1,15 +1,33 @@
1
- import { Extension } from "@tiptap/core";
1
+ import { Editor, Extension } from "@tiptap/core";
2
+ import { BlockSideMenuFactory } from "./BlockSideMenuFactoryTypes";
2
3
  import { createDraggableBlocksPlugin } from "./DraggableBlocksPlugin";
3
4
 
5
+ export type DraggableBlocksOptions = {
6
+ editor: Editor;
7
+ blockSideMenuFactory: BlockSideMenuFactory;
8
+ };
9
+
4
10
  /**
5
- * This extension adds a drag handle in front of all nodes with a "data-id" attribute
11
+ * This extension adds a menu to the side of blocks which features various BlockNote functions such as adding and
12
+ * removing blocks. More importantly, it adds a drag handle which allows the user to drag and drop blocks.
6
13
  *
7
14
  * code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799
8
15
  */
9
- export const DraggableBlocksExtension = Extension.create<{}>({
10
- name: "DraggableBlocksExtension",
11
- priority: 1000, // Need to be high, in order to hide draghandle when typing slash
12
- addProseMirrorPlugins() {
13
- return [createDraggableBlocksPlugin()];
14
- },
15
- });
16
+ export const DraggableBlocksExtension =
17
+ Extension.create<DraggableBlocksOptions>({
18
+ name: "DraggableBlocksExtension",
19
+ priority: 1000, // Need to be high, in order to hide menu when typing slash
20
+ addProseMirrorPlugins() {
21
+ if (!this.options.blockSideMenuFactory) {
22
+ throw new Error(
23
+ "UI Element factory not defined for DraggableBlocksExtension"
24
+ );
25
+ }
26
+ return [
27
+ createDraggableBlocksPlugin({
28
+ editor: this.editor,
29
+ blockSideMenuFactory: this.options.blockSideMenuFactory,
30
+ }),
31
+ ];
32
+ },
33
+ });