@blocknote/core 0.1.2 → 0.2.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 +1424 -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 +3 -16
  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 +2 -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
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "homepage": "https://github.com/yousefed/blocknote",
4
4
  "private": false,
5
5
  "license": "MPL-2.0",
6
- "version": "0.1.2",
6
+ "version": "0.2.0",
7
7
  "files": [
8
8
  "dist",
9
9
  "types",
@@ -41,6 +41,7 @@
41
41
  "scripts": {
42
42
  "dev": "vite",
43
43
  "build": "tsc && vite build",
44
+ "build-bundled": "tsc && vite build --config vite.config.bundled.ts && git checkout tmp-releases && rm -rf ../../release && mv ../../release-tmp ../../release",
44
45
  "preview": "vite preview",
45
46
  "lint": "eslint src --max-warnings 0"
46
47
  },
@@ -48,8 +49,6 @@
48
49
  "@emotion/cache": "^11.10.5",
49
50
  "@emotion/serialize": "^1.1.1",
50
51
  "@emotion/utils": "^1.2.0",
51
- "@mantine/core": "^5.6.1",
52
- "@tippyjs/react": "^4.2.6",
53
52
  "@tiptap/core": "^2.0.0-beta.182",
54
53
  "@tiptap/extension-bold": "^2.0.0-beta.28",
55
54
  "@tiptap/extension-code": "^2.0.0-beta.28",
@@ -66,26 +65,14 @@
66
65
  "@tiptap/extension-strike": "^2.0.0-beta.29",
67
66
  "@tiptap/extension-text": "^2.0.0-beta.17",
68
67
  "@tiptap/extension-underline": "^2.0.0-beta.25",
69
- "@tiptap/react": "^2.0.0-beta.114",
70
68
  "lodash": "^4.17.21",
71
69
  "prosemirror-model": "1.18.1",
72
70
  "prosemirror-state": "1.4.1",
73
71
  "prosemirror-view": "1.26.2",
74
- "react": "^17.0.2",
75
- "react-dom": "^17.0.2",
76
- "react-icons": "^4.3.1",
77
- "styled-components": "^5.3.3",
78
72
  "uuid": "^8.3.2"
79
73
  },
80
- "overrides": {
81
- "react-dom": "$react-dom",
82
- "react": "$react"
83
- },
84
74
  "devDependencies": {
85
75
  "@types/lodash": "^4.14.179",
86
- "@types/react": "^17.0.39",
87
- "@types/react-dom": "^17.0.12",
88
- "@types/styled-components": "^5.1.24",
89
76
  "@types/uuid": "^8.3.4",
90
77
  "eslint": "^8.10.0",
91
78
  "eslint-config-react-app": "^7.0.0",
@@ -107,5 +94,5 @@
107
94
  "access": "public",
108
95
  "registry": "https://registry.npmjs.org/"
109
96
  },
110
- "gitHead": "085650a27c92af2b54df6d8b0e73673180821ebe"
97
+ "gitHead": "5ccf86c22d62e87813d4314a5f9f0b24d8e1c9d5"
111
98
  }
@@ -0,0 +1,54 @@
1
+ import { Editor, EditorOptions } from "@tiptap/core";
2
+
3
+ // import "./blocknote.css";
4
+ import { getBlockNoteExtensions, UiFactories } from "./BlockNoteExtensions";
5
+ import styles from "./editor.module.css";
6
+
7
+ export type BlockNoteEditorOptions = EditorOptions & {
8
+ enableBlockNoteExtensions: boolean;
9
+ disableHistoryExtension: boolean;
10
+ uiFactories: UiFactories;
11
+ };
12
+
13
+ const blockNoteOptions = {
14
+ enableInputRules: true,
15
+ enablePasteRules: true,
16
+ enableCoreExtensions: false,
17
+ };
18
+
19
+ export class BlockNoteEditor {
20
+ public readonly tiptapEditor: Editor & { contentComponent: any };
21
+
22
+ constructor(options: Partial<BlockNoteEditorOptions> = {}) {
23
+ const blockNoteExtensions = getBlockNoteExtensions(
24
+ options.uiFactories || {}
25
+ );
26
+
27
+ let extensions = options.disableHistoryExtension
28
+ ? blockNoteExtensions.filter((e) => e.name !== "history")
29
+ : blockNoteExtensions;
30
+
31
+ const tiptapOptions = {
32
+ ...blockNoteOptions,
33
+ ...options,
34
+ extensions:
35
+ options.enableBlockNoteExtensions === false
36
+ ? options.extensions
37
+ : [...(options.extensions || []), ...extensions],
38
+ editorProps: {
39
+ attributes: {
40
+ ...(options.editorProps?.attributes || {}),
41
+ class: [
42
+ styles.bnEditor,
43
+ styles.bnRoot,
44
+ (options.editorProps?.attributes as any)?.class || "",
45
+ ].join(" "),
46
+ },
47
+ },
48
+ };
49
+
50
+ this.tiptapEditor = new Editor(tiptapOptions) as Editor & {
51
+ contentComponent: any;
52
+ };
53
+ }
54
+ }
@@ -13,14 +13,20 @@ import Text from "@tiptap/extension-text";
13
13
  import Underline from "@tiptap/extension-underline";
14
14
  import { blocks } from "./extensions/Blocks";
15
15
  import blockStyles from "./extensions/Blocks/nodes/Block.module.css";
16
- import { BubbleMenuExtension } from "./extensions/BubbleMenu/BubbleMenuExtension";
16
+ import { FormattingToolbarExtension } from "./extensions/FormattingToolbar/FormattingToolbarExtension";
17
17
  import { DraggableBlocksExtension } from "./extensions/DraggableBlocks/DraggableBlocksExtension";
18
- import HyperlinkMark from "./extensions/Hyperlinks/HyperlinkMark";
18
+ import HyperlinkMark from "./extensions/HyperlinkToolbar/HyperlinkMark";
19
19
  import { FixedParagraph } from "./extensions/Paragraph/FixedParagraph";
20
20
  import { Placeholder } from "./extensions/Placeholder/PlaceholderExtension";
21
21
  import SlashMenuExtension from "./extensions/SlashMenu";
22
22
  import { TrailingNode } from "./extensions/TrailingNode/TrailingNodeExtension";
23
23
  import UniqueID from "./extensions/UniqueID/UniqueID";
24
+ import { FormattingToolbarFactory } from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
25
+ import { HyperlinkToolbarFactory } from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
26
+ import { SuggestionsMenuFactory } from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
27
+ import { BlockSideMenuFactory } from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
28
+ import { Link } from "@tiptap/extension-link";
29
+ import { SlashMenuItem } from "./extensions/SlashMenu/SlashMenuItem";
24
30
 
25
31
  export const Document = Node.create({
26
32
  name: "doc",
@@ -28,10 +34,17 @@ export const Document = Node.create({
28
34
  content: "block+",
29
35
  });
30
36
 
37
+ export type UiFactories = Partial<{
38
+ formattingToolbarFactory: FormattingToolbarFactory;
39
+ hyperlinkToolbarFactory: HyperlinkToolbarFactory;
40
+ slashMenuFactory: SuggestionsMenuFactory<SlashMenuItem>;
41
+ blockSideMenuFactory: BlockSideMenuFactory;
42
+ }>;
43
+
31
44
  /**
32
45
  * Get all the Tiptap extensions BlockNote is configured with by default
33
46
  */
34
- export const getBlockNoteExtensions = () => {
47
+ export const getBlockNoteExtensions = (uiFactories: UiFactories) => {
35
48
  const ret: Extensions = [
36
49
  extensions.ClipboardTextSerializer,
37
50
  extensions.Commands,
@@ -65,19 +78,51 @@ export const getBlockNoteExtensions = () => {
65
78
  Italic,
66
79
  Strike,
67
80
  Underline,
68
- HyperlinkMark,
69
81
  FixedParagraph,
70
82
 
71
83
  // custom blocks:
72
84
  ...blocks,
73
- DraggableBlocksExtension,
85
+
74
86
  DropCursor.configure({ width: 5, color: "#ddeeff" }),
75
- BubbleMenuExtension,
76
87
  History,
77
88
  // This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),
78
89
  // should be handled before Enter handlers in other components like splitListItem
79
- SlashMenuExtension,
80
90
  TrailingNode,
81
91
  ];
92
+
93
+ if (uiFactories.blockSideMenuFactory) {
94
+ ret.push(
95
+ DraggableBlocksExtension.configure({
96
+ blockSideMenuFactory: uiFactories.blockSideMenuFactory,
97
+ })
98
+ );
99
+ }
100
+
101
+ if (uiFactories.formattingToolbarFactory) {
102
+ ret.push(
103
+ FormattingToolbarExtension.configure({
104
+ formattingToolbarFactory: uiFactories.formattingToolbarFactory,
105
+ })
106
+ );
107
+ }
108
+
109
+ if (uiFactories.hyperlinkToolbarFactory) {
110
+ ret.push(
111
+ HyperlinkMark.configure({
112
+ hyperlinkToolbarFactory: uiFactories.hyperlinkToolbarFactory,
113
+ })
114
+ );
115
+ } else {
116
+ ret.push(Link);
117
+ }
118
+
119
+ if (uiFactories.slashMenuFactory) {
120
+ ret.push(
121
+ SlashMenuExtension.configure({
122
+ slashMenuFactory: uiFactories.slashMenuFactory,
123
+ })
124
+ );
125
+ }
126
+
82
127
  return ret;
83
128
  };
@@ -0,0 +1,92 @@
1
+ /* Generated using https://google-webfonts-helper.herokuapp.com/fonts/inter?subsets=latin */
2
+
3
+ /* inter-100 - latin */
4
+ @font-face {
5
+ font-family: "Inter";
6
+ font-style: normal;
7
+ font-weight: 100;
8
+ src: local(""),
9
+ url("./inter-v12-latin/inter-v12-latin-100.woff2") format("woff2"),
10
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
11
+ url("./inter-v12-latin/inter-v12-latin-100.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
12
+ }
13
+ /* inter-200 - latin */
14
+ @font-face {
15
+ font-family: "Inter";
16
+ font-style: normal;
17
+ font-weight: 200;
18
+ src: local(""),
19
+ url("./inter-v12-latin/inter-v12-latin-200.woff2") format("woff2"),
20
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
21
+ url("./inter-v12-latin/inter-v12-latin-200.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
22
+ }
23
+ /* inter-300 - latin */
24
+ @font-face {
25
+ font-family: "Inter";
26
+ font-style: normal;
27
+ font-weight: 300;
28
+ src: local(""),
29
+ url("./inter-v12-latin/inter-v12-latin-300.woff2") format("woff2"),
30
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
31
+ url("./inter-v12-latin/inter-v12-latin-300.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
32
+ }
33
+ /* inter-regular - latin */
34
+ @font-face {
35
+ font-family: "Inter";
36
+ font-style: normal;
37
+ font-weight: 400;
38
+ src: local(""),
39
+ url("./inter-v12-latin/inter-v12-latin-regular.woff2") format("woff2"),
40
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
41
+ url("./inter-v12-latin/inter-v12-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
42
+ }
43
+ /* inter-500 - latin */
44
+ @font-face {
45
+ font-family: "Inter";
46
+ font-style: normal;
47
+ font-weight: 500;
48
+ src: local(""),
49
+ url("./inter-v12-latin/inter-v12-latin-500.woff2") format("woff2"),
50
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
51
+ url("./inter-v12-latin/inter-v12-latin-500.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
52
+ }
53
+ /* inter-600 - latin */
54
+ @font-face {
55
+ font-family: "Inter";
56
+ font-style: normal;
57
+ font-weight: 600;
58
+ src: local(""),
59
+ url("./inter-v12-latin/inter-v12-latin-600.woff2") format("woff2"),
60
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
61
+ url("./inter-v12-latin/inter-v12-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
62
+ }
63
+ /* inter-700 - latin */
64
+ @font-face {
65
+ font-family: "Inter";
66
+ font-style: normal;
67
+ font-weight: 700;
68
+ src: local(""),
69
+ url("./inter-v12-latin/inter-v12-latin-700.woff2") format("woff2"),
70
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
71
+ url("./inter-v12-latin/inter-v12-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
72
+ }
73
+ /* inter-800 - latin */
74
+ @font-face {
75
+ font-family: "Inter";
76
+ font-style: normal;
77
+ font-weight: 800;
78
+ src: local(""),
79
+ url("./inter-v12-latin/inter-v12-latin-800.woff2") format("woff2"),
80
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
81
+ url("./inter-v12-latin/inter-v12-latin-800.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
82
+ }
83
+ /* inter-900 - latin */
84
+ @font-face {
85
+ font-family: "Inter";
86
+ font-style: normal;
87
+ font-weight: 900;
88
+ src: local(""),
89
+ url("./inter-v12-latin/inter-v12-latin-900.woff2") format("woff2"),
90
+ /* Chrome 26+, Opera 23+, Firefox 39+ */
91
+ url("./inter-v12-latin/inter-v12-latin-900.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
92
+ }
@@ -1,3 +1,40 @@
1
+ @import url("./assets/fonts-inter.css");
2
+
1
3
  .bnEditor {
2
4
  outline: none;
3
5
  }
6
+
7
+ /*
8
+ bnRoot should be applied to all top-level elements
9
+
10
+ This includes the Prosemirror editor, but also <div> element such as
11
+ Tippy popups that are appended to document.body directly
12
+ */
13
+ .bnRoot {
14
+ -webkit-box-sizing: border-box;
15
+ -moz-box-sizing: border-box;
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ .bnRoot *,
20
+ .bnRoot *::before,
21
+ .bnRoot *::after {
22
+ -webkit-box-sizing: inherit;
23
+ -moz-box-sizing: inherit;
24
+ box-sizing: inherit;
25
+ }
26
+
27
+ .bnEditor, .dragPreview {
28
+ /* Define a set of colors to be used throughout the app for consistency
29
+ see https://atlassian.design/foundations/color for more info */
30
+ --N800: #172b4d; /* Dark neutral used for tooltips and text on light background */
31
+ --N40: #dfe1e6; /* Light neutral used for subtle borders and text on dark background */
32
+
33
+ font-family: "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont,
34
+ "Open Sans", "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
35
+ "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
36
+ -webkit-font-smoothing: antialiased;
37
+ -moz-osx-font-smoothing: grayscale;
38
+
39
+ color: rgb(60, 65, 73);
40
+ }
@@ -1,12 +1,10 @@
1
1
  // Object containing all possible block attributes.
2
2
  const BlockAttributes: Record<string, string> = {
3
- listType: "data-list-type",
4
3
  blockColor: "data-block-color",
5
4
  blockStyle: "data-block-style",
6
- headingType: "data-heading-type",
7
5
  id: "data-id",
8
6
  depth: "data-depth",
9
7
  depthChange: "data-depth-change",
10
8
  };
11
9
 
12
- export default BlockAttributes;
10
+ export default BlockAttributes;
@@ -5,18 +5,22 @@ import {
5
5
  } from "@tiptap/core";
6
6
  import { Plugin, PluginKey } from "prosemirror-state";
7
7
  import { Decoration, DecorationSet } from "prosemirror-view";
8
- import BlockAttributes from "./BlockAttributes";
9
8
 
10
9
  const PLUGIN_KEY = new PluginKey(`previous-blocks`);
11
10
 
12
- // Inserts "prev-" string into an HTML attribute name with a "data-" prefix, e.g. "data-depth" -> "data-prev-depth".
13
- // Assumes "data-" prefix is in the attribute name.
14
- const insertPrev = (attr: string) => attr.slice(0, 5) + "prev-" + attr.slice(5);
11
+ const nodeAttributes: Record<string, string> = {
12
+ listItemType: "list-item-type",
13
+ listItemIndex: "list-item-index",
14
+ headingLevel: "heading-level",
15
+ type: "type",
16
+ depth: "depth",
17
+ "depth-change": "depth-change",
18
+ };
15
19
 
16
20
  /**
17
21
  * This plugin tracks transformation of Block node attributes, so we can support CSS transitions.
18
22
  *
19
- * Problem it solves: Prosemirror recreates the DOM when transactions happen. So when a transaction changes an Node attribute,
23
+ * Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,
20
24
  * it results in a completely new DOM element. This means CSS transitions don't work.
21
25
  *
22
26
  * Solution: When attributes change on a node, this plugin sets a data-* attribute with the "previous" value. This way we can still use CSS transitions. (See block.module.css)
@@ -75,7 +79,6 @@ export const PreviousBlockTypePlugin = () => {
75
79
 
76
80
  changes.forEach(() => {
77
81
  const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);
78
-
79
82
  const oldNodesById = new Map(
80
83
  oldNodes.map((node) => [node.node.attrs.id, node])
81
84
  );
@@ -84,28 +87,68 @@ export const PreviousBlockTypePlugin = () => {
84
87
 
85
88
  for (let node of newNodes) {
86
89
  const oldNode = oldNodesById.get(node.node.attrs.id);
87
- if (oldNode) {
90
+ const oldContentNode = oldNode?.node.firstChild;
91
+ const newContentNode = node.node.firstChild;
92
+ if (oldNode && oldContentNode && newContentNode) {
88
93
  const newAttrs = {
89
- listType: node.node.attrs.listType,
90
- blockColor: node.node.attrs.blockColor,
91
- blockStyle: node.node.attrs.blockStyle,
92
- headingType: node.node.attrs.headingType,
94
+ listItemType: newContentNode.attrs.listItemType,
95
+ listItemIndex: newContentNode.attrs.listItemIndex,
96
+ headingLevel: newContentNode.attrs.headingLevel,
97
+ type: newContentNode.type.name,
93
98
  depth: newState.doc.resolve(node.pos).depth,
94
99
  };
95
100
 
96
101
  const oldAttrs = {
97
- listType: oldNode.node.attrs.listType,
98
- blockColor: oldNode.node.attrs.blockColor,
99
- blockStyle: oldNode.node.attrs.blockStyle,
100
- headingType: oldNode.node.attrs.headingType,
102
+ listItemType: oldContentNode.attrs.listItemType,
103
+ listItemIndex: oldContentNode.attrs.listItemIndex,
104
+ headingLevel: oldContentNode.attrs.headingLevel,
105
+ type: oldContentNode.type.name,
101
106
  depth: oldState.doc.resolve(oldNode.pos).depth,
102
107
  };
103
108
 
109
+ // Hacky fix to avoid processing certain transactions created by ordered list indexing plugin.
110
+
111
+ // True when an existing ordered list item is assigned an index for the first time, which happens
112
+ // immediately after it's created. Using this condition to start an animation ensures it's not
113
+ // immediately overridden by a different transaction created by the ordered list indexing plugin.
114
+ const indexInitialized =
115
+ oldAttrs.listItemIndex === null &&
116
+ newAttrs.listItemIndex !== null;
117
+
118
+ // True when an existing ordered list item changes nesting levels, before its index is updated by the
119
+ // ordered list indexing plugin. This condition ensures that animations for indentation still work with
120
+ // ordered list items, while preventing unnecessary animations being done when dragging/dropping them.
121
+ const depthChanged =
122
+ oldAttrs.listItemIndex !== null &&
123
+ newAttrs.listItemIndex !== null &&
124
+ oldAttrs.listItemIndex === newAttrs.listItemIndex;
125
+
126
+ // Only false for transactions in which the block remains an ordered list item before & after, but neither
127
+ // of the previous conditions apply.
128
+ const shouldUpdate =
129
+ oldAttrs.listItemType === "ordered" &&
130
+ newAttrs.listItemType === "ordered"
131
+ ? indexInitialized || depthChanged
132
+ : true;
133
+
104
134
  if (
105
- JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) // TODO: faster deep equal?
135
+ JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) && // TODO: faster deep equal?
136
+ shouldUpdate
106
137
  ) {
107
- (oldAttrs as any).depthChange = oldAttrs.depth - newAttrs.depth;
138
+ (oldAttrs as any)["depth-change"] =
139
+ oldAttrs.depth - newAttrs.depth;
108
140
  prev.prevBlockAttrs[node.node.attrs.id] = oldAttrs;
141
+
142
+ // for debugging:
143
+ console.log(
144
+ "id:",
145
+ node.node.attrs.id,
146
+ "previousBlockTypePlugin changes detected, oldAttrs",
147
+ oldAttrs,
148
+ "new",
149
+ newAttrs
150
+ );
151
+
109
152
  prev.needsUpdate = true;
110
153
  }
111
154
  }
@@ -119,6 +162,7 @@ export const PreviousBlockTypePlugin = () => {
119
162
  decorations(state) {
120
163
  const pluginState = (this as Plugin).getState(state);
121
164
  if (!pluginState.needsUpdate) {
165
+ // console.log("0");
122
166
  return undefined;
123
167
  }
124
168
 
@@ -126,18 +170,27 @@ export const PreviousBlockTypePlugin = () => {
126
170
 
127
171
  state.doc.descendants((node, pos) => {
128
172
  if (!node.attrs.id) {
173
+ // console.log("1");
129
174
  return;
130
175
  }
131
176
  const prevAttrs = pluginState.prevBlockAttrs[node.attrs.id];
132
177
  if (!prevAttrs) {
178
+ // console.log("2");
133
179
  return;
134
180
  }
135
181
 
136
182
  const decorationAttributes: any = {};
137
183
  for (let [nodeAttr, val] of Object.entries(prevAttrs)) {
138
- decorationAttributes[insertPrev(BlockAttributes[nodeAttr])] =
184
+ decorationAttributes["data-prev-" + nodeAttributes[nodeAttr]] =
139
185
  val || "none";
140
186
  }
187
+
188
+ // for debugging:
189
+ console.log(
190
+ "previousBlockTypePlugin committing decorations",
191
+ decorationAttributes
192
+ );
193
+
141
194
  const decoration = Decoration.node(pos, pos + node.nodeSize, {
142
195
  ...decorationAttributes,
143
196
  });
@@ -0,0 +1,66 @@
1
+ import { Node, NodeType } from "prosemirror-model";
2
+
3
+ export type BlockInfo = {
4
+ id: string;
5
+ node: Node;
6
+ contentNode: Node;
7
+ contentType: NodeType;
8
+ numChildBlocks: number;
9
+ startPos: number;
10
+ endPos: number;
11
+ depth: number;
12
+ };
13
+
14
+ /**
15
+ * Retrieves information regarding the most nested block node in a ProseMirror doc, that a given position lies in.
16
+ * @param doc The ProseMirror doc.
17
+ * @param posInBlock A position somewhere within a block node.
18
+ * @returns A BlockInfo object for the block the given position is in, or undefined if the position is not in a block
19
+ * for the given doc.
20
+ */
21
+ export function getBlockInfoFromPos(
22
+ doc: Node,
23
+ posInBlock: number
24
+ ): BlockInfo | undefined {
25
+ if (posInBlock <= 0 || posInBlock > doc.nodeSize) {
26
+ return undefined;
27
+ }
28
+
29
+ const $pos = doc.resolve(posInBlock);
30
+
31
+ const maxDepth = $pos.depth;
32
+ let node = $pos.node(maxDepth);
33
+ let depth = maxDepth;
34
+
35
+ while (depth >= 0) {
36
+ // If the outermost node is not a block, it means the position does not lie within a block.
37
+ if (depth === 0) {
38
+ return undefined;
39
+ }
40
+ if (node.type.name === "block") {
41
+ break;
42
+ }
43
+
44
+ depth -= 1;
45
+ node = $pos.node(depth);
46
+ }
47
+
48
+ const id = node.attrs["id"];
49
+ const contentNode = node.firstChild!;
50
+ const contentType = contentNode.type;
51
+ const numChildBlocks = node.childCount === 2 ? node.lastChild!.childCount : 0;
52
+
53
+ const startPos = $pos.start(depth);
54
+ const endPos = $pos.end(depth);
55
+
56
+ return {
57
+ id,
58
+ node,
59
+ contentNode,
60
+ contentType,
61
+ numChildBlocks,
62
+ startPos,
63
+ endPos,
64
+ depth,
65
+ };
66
+ }
@@ -1,15 +1,19 @@
1
1
  import { Node } from "@tiptap/core";
2
2
  import { Block } from "./nodes/Block";
3
3
  import { BlockGroup } from "./nodes/BlockGroup";
4
- import { ContentBlock } from "./nodes/Content";
4
+ import { TextContent } from "./nodes/BlockTypes/TextBlock/TextContent";
5
+ import { HeadingContent } from "./nodes/BlockTypes/HeadingBlock/HeadingContent";
6
+ import { ListItemContent } from "./nodes/BlockTypes/ListItemBlock/ListItemContent";
5
7
 
6
8
  export const blocks: any[] = [
7
- ContentBlock,
9
+ TextContent,
10
+ HeadingContent,
11
+ ListItemContent,
8
12
  Block,
9
13
  BlockGroup,
10
14
  Node.create({
11
15
  name: "doc",
12
16
  topNode: true,
13
- content: "blockgroup",
17
+ content: "blockGroup",
14
18
  }),
15
19
  ];