@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.
- package/README.md +12 -6
- package/dist/blocknote.js +1424 -5109
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +1 -53
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -16
- package/src/BlockNoteEditor.ts +54 -0
- package/src/BlockNoteExtensions.ts +52 -7
- package/src/assets/fonts-inter.css +92 -0
- package/src/editor.module.css +37 -0
- package/src/extensions/Blocks/BlockAttributes.ts +1 -3
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +71 -18
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +66 -0
- package/src/extensions/Blocks/index.ts +7 -3
- package/src/extensions/Blocks/nodes/Block.module.css +116 -74
- package/src/extensions/Blocks/nodes/Block.ts +413 -292
- package/src/extensions/Blocks/nodes/BlockGroup.ts +6 -6
- package/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.ts +84 -0
- package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts +177 -0
- package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts +77 -0
- package/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.ts +34 -0
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +20 -0
- package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +27 -9
- package/src/extensions/DraggableBlocks/{DraggableBlocksPlugin.tsx → DraggableBlocksPlugin.ts} +227 -147
- package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +29 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +35 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +308 -0
- package/src/extensions/HyperlinkToolbar/HyperlinkMark.ts +28 -0
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +19 -0
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +251 -0
- package/src/extensions/Placeholder/PlaceholderExtension.ts +2 -2
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +9 -1
- package/src/extensions/SlashMenu/SlashMenuItem.ts +1 -3
- package/src/extensions/SlashMenu/defaultCommands.tsx +33 -22
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +4 -4
- package/src/extensions/UniqueID/UniqueID.ts +14 -1
- package/src/index.ts +8 -4
- package/src/shared/EditorElement.ts +10 -0
- package/src/shared/plugins/suggestion/SuggestionItem.ts +1 -8
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +222 -101
- package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +21 -0
- package/src/{utils.ts → shared/utils.ts} +0 -0
- package/types/src/BlockNoteEditor.d.ts +13 -0
- package/types/src/BlockNoteExtensions.d.ts +12 -1
- package/types/src/EditorElement.d.ts +7 -0
- package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +1 -1
- package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +19 -0
- package/types/src/extensions/Blocks/nodes/Block.d.ts +11 -19
- package/types/src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.d.ts +8 -0
- package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.d.ts +8 -0
- package/types/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.d.ts +6 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +4 -1
- package/types/src/extensions/BubbleMenu/BubbleMenuFactoryTypes.d.ts +27 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +10 -12
- package/types/src/extensions/DraggableBlocks/BlockMenuFactoryTypes.d.ts +12 -0
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +14 -0
- package/types/src/extensions/DraggableBlocks/DragMenuFactoryTypes.d.ts +18 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +9 -3
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +23 -1
- package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +8 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +23 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +43 -0
- package/types/src/extensions/HyperlinkToolbar/HyperlinkMark.d.ts +8 -0
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +12 -0
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +11 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +2 -1
- package/types/src/extensions/Hyperlinks/HyperlinkMenuFactoryTypes.d.ts +11 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +10 -1
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +3 -1
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -4
- package/types/src/index.d.ts +8 -3
- package/types/src/shared/EditorElement.d.ts +6 -0
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +1 -6
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +15 -10
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +12 -0
- package/types/src/shared/utils.d.ts +2 -0
- package/types/src/utils.d.ts +2 -2
- package/src/BlockNoteTheme.ts +0 -150
- package/src/EditorContent.tsx +0 -2
- package/src/extensions/Blocks/OrderedListPlugin.ts +0 -46
- package/src/extensions/Blocks/commands/joinBackward.ts +0 -274
- package/src/extensions/Blocks/helpers/setBlockHeading.ts +0 -30
- package/src/extensions/Blocks/nodes/Content.ts +0 -63
- package/src/extensions/Blocks/rule.ts +0 -48
- package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +0 -36
- package/src/extensions/BubbleMenu/BubbleMenuPlugin.ts +0 -245
- package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +0 -240
- package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +0 -67
- package/src/extensions/DraggableBlocks/components/DragHandle.tsx +0 -102
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +0 -19
- package/src/extensions/Hyperlinks/HyperlinkMark.tsx +0 -16
- package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +0 -165
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.tsx +0 -44
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.tsx +0 -34
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.tsx +0 -31
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.tsx +0 -40
- package/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.tsx +0 -37
- package/src/extensions/Hyperlinks/menus/HyperlinkMenu.tsx +0 -63
- package/src/fonts-inter.css +0 -94
- package/src/globals.css +0 -28
- package/src/root.module.css +0 -19
- package/src/shared/components/toolbar/Toolbar.tsx +0 -10
- package/src/shared/components/toolbar/ToolbarButton.tsx +0 -57
- package/src/shared/components/toolbar/ToolbarDropdown.tsx +0 -35
- package/src/shared/components/toolbar/ToolbarDropdownItem.tsx +0 -35
- package/src/shared/components/toolbar/ToolbarDropdownTarget.tsx +0 -31
- package/src/shared/components/tooltip/TooltipContent.module.css +0 -15
- package/src/shared/components/tooltip/TooltipContent.tsx +0 -23
- package/src/shared/hooks/useEditorForceUpdate.tsx +0 -30
- package/src/shared/plugins/suggestion/SuggestionListReactRenderer.tsx +0 -236
- package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +0 -47
- package/src/shared/plugins/suggestion/components/SuggestionGroupItem.tsx +0 -82
- package/src/shared/plugins/suggestion/components/SuggestionList.tsx +0 -92
- package/src/useEditor.ts +0 -51
- package/types/src/BlockNoteTheme.d.ts +0 -2
- package/types/src/EditorContent.d.ts +0 -1
- package/types/src/commands/indentation.d.ts +0 -2
- package/types/src/extensions/Blocks/OrderedListPlugin.d.ts +0 -2
- package/types/src/extensions/Blocks/commands/joinBackward.d.ts +0 -14
- package/types/src/extensions/Blocks/helpers/setBlockHeading.d.ts +0 -5
- package/types/src/extensions/Blocks/nodes/Content.d.ts +0 -5
- package/types/src/extensions/Blocks/rule.d.ts +0 -16
- package/types/src/extensions/BubbleMenu/component/BubbleMenu.d.ts +0 -5
- package/types/src/extensions/BubbleMenu/component/DropdownBlockItem.d.ts +0 -10
- package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +0 -11
- package/types/src/extensions/DraggableBlocks/components/DragHandle.d.ts +0 -12
- package/types/src/extensions/DraggableBlocks/components/DragHandleMenu.d.ts +0 -6
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.d.ts +0 -11
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.d.ts +0 -13
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.d.ts +0 -8
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.d.ts +0 -9
- package/types/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.d.ts +0 -12
- package/types/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.d.ts +0 -12
- package/types/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.d.ts +0 -10
- package/types/src/extensions/Hyperlinks/menus/HyperlinkMenu.d.ts +0 -21
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.d.ts +0 -39
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.d.ts +0 -1
- package/types/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.d.ts +0 -11
- package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInput.d.ts +0 -39
- package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInputStyles.d.ts +0 -3
- package/types/src/extensions/Hyperlinks/menus/helpers/ToolbarComponent.d.ts +0 -13
- package/types/src/extensions/helpers/formatKeyboardShortcut.d.ts +0 -1
- package/types/src/lib/atlaskit/browser.d.ts +0 -12
- package/types/src/nodes/ChildgroupNode.d.ts +0 -28
- package/types/src/nodes/patchNodes.d.ts +0 -1
- package/types/src/plugins/TreeViewPlugin/index.d.ts +0 -2
- package/types/src/plugins/animation.d.ts +0 -2
- package/types/src/react/BlockNoteComposer.d.ts +0 -17
- package/types/src/react/BlockNotePlugin.d.ts +0 -1
- package/types/src/react/index.d.ts +0 -3
- package/types/src/react/useBlockNoteSetup.d.ts +0 -2
- package/types/src/registerBlockNote.d.ts +0 -2
- package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +0 -15
- package/types/src/shared/components/toolbar/SimpleToolbarDropdown.d.ts +0 -11
- package/types/src/shared/components/toolbar/SimpleToolbarDropdownItem.d.ts +0 -11
- package/types/src/shared/components/toolbar/Toolbar.d.ts +0 -4
- package/types/src/shared/components/toolbar/ToolbarButton.d.ts +0 -15
- package/types/src/shared/components/toolbar/ToolbarDropdown.d.ts +0 -17
- package/types/src/shared/components/toolbar/ToolbarDropdownItem.d.ts +0 -11
- package/types/src/shared/components/toolbar/ToolbarDropdownTarget.d.ts +0 -8
- package/types/src/shared/components/toolbar/ToolbarSeparator.d.ts +0 -2
- package/types/src/shared/components/tooltip/TooltipContent.d.ts +0 -15
- package/types/src/shared/hooks/useEditorForceUpdate.d.ts +0 -2
- package/types/src/shared/plugins/suggestion/SuggestionListReactRenderer.d.ts +0 -71
- package/types/src/shared/plugins/suggestion/components/SuggestionGroup.d.ts +0 -23
- package/types/src/shared/plugins/suggestion/components/SuggestionGroupItem.d.ts +0 -9
- package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +0 -11
- package/types/src/themes/BlockNoteEditorTheme.d.ts +0 -11
- 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: "
|
|
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
|
|
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 =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
+
});
|