@blocknote/core 0.7.0 → 0.8.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/dist/blocknote.js +1428 -1252
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +2 -2
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -3
- package/src/BlockNoteEditor.ts +100 -53
- package/src/BlockNoteExtensions.ts +24 -14
- package/src/api/blockManipulation/blockManipulation.test.ts +6 -3
- package/src/api/blockManipulation/blockManipulation.ts +7 -6
- package/src/api/formatConversions/formatConversions.test.ts +13 -8
- package/src/api/formatConversions/formatConversions.ts +15 -12
- package/src/api/nodeConversions/nodeConversions.test.ts +29 -10
- package/src/api/nodeConversions/nodeConversions.ts +33 -12
- package/src/api/nodeConversions/testUtil.ts +8 -4
- package/src/editor.module.css +0 -1
- package/src/extensions/Blocks/api/block.ts +229 -0
- package/src/extensions/Blocks/api/blockTypes.ts +158 -71
- package/src/extensions/Blocks/api/cursorPositionTypes.ts +5 -5
- package/src/extensions/Blocks/api/defaultBlocks.ts +44 -0
- package/src/extensions/Blocks/api/selectionTypes.ts +3 -3
- package/src/extensions/Blocks/api/serialization.ts +29 -0
- package/src/extensions/Blocks/index.ts +0 -8
- package/src/extensions/Blocks/nodes/Block.module.css +24 -12
- package/src/extensions/Blocks/nodes/BlockContainer.ts +8 -4
- package/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts +4 -4
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +5 -5
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +100 -97
- package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +4 -4
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +11 -9
- package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +6 -5
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +12 -11
- package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +21 -16
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +9 -5
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +30 -42
- package/src/extensions/Placeholder/PlaceholderExtension.ts +1 -0
- package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +5 -2
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +37 -33
- package/src/extensions/SlashMenu/defaultSlashMenuItems.tsx +14 -10
- package/src/extensions/SlashMenu/index.ts +2 -2
- package/src/index.ts +4 -0
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +29 -13
- package/types/src/BlockNoteEditor.d.ts +37 -23
- package/types/src/BlockNoteExtensions.d.ts +15 -8
- package/types/src/api/blockManipulation/blockManipulation.d.ts +4 -4
- package/types/src/api/formatConversions/formatConversions.d.ts +5 -5
- package/types/src/api/nodeConversions/nodeConversions.d.ts +3 -3
- package/types/src/api/nodeConversions/testUtil.d.ts +2 -2
- package/types/src/extensions/Blocks/api/block.d.ts +6 -5
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +77 -33
- package/types/src/extensions/Blocks/api/cursorPositionTypes.d.ts +5 -5
- package/types/src/extensions/Blocks/api/selectionTypes.d.ts +3 -3
- package/types/src/extensions/Blocks/api/serialization.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +3 -3
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +1 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +1 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +1 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +1 -2
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +7 -7
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +5 -4
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +11 -10
- package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +6 -5
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +4 -3
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +16 -19
- package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +4 -3
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +5 -4
- package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +66 -1
- package/types/src/extensions/SlashMenu/index.d.ts +2 -2
- package/types/src/index.d.ts +4 -0
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +5 -4
|
@@ -1,117 +1,120 @@
|
|
|
1
|
-
import { InputRule, mergeAttributes
|
|
2
|
-
import
|
|
1
|
+
import { InputRule, mergeAttributes } from "@tiptap/core";
|
|
2
|
+
import { createTipTapBlock } from "../../../../api/block";
|
|
3
3
|
import { handleEnter } from "../ListItemKeyboardShortcuts";
|
|
4
4
|
import { NumberedListIndexingPlugin } from "./NumberedListIndexingPlugin";
|
|
5
|
+
import styles from "../../../Block.module.css";
|
|
5
6
|
|
|
6
|
-
export const NumberedListItemBlockContent =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export const NumberedListItemBlockContent =
|
|
8
|
+
createTipTapBlock<"numberedListItem">({
|
|
9
|
+
name: "numberedListItem",
|
|
10
|
+
content: "inline*",
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
addAttributes() {
|
|
13
|
+
return {
|
|
14
|
+
index: {
|
|
15
|
+
default: null,
|
|
16
|
+
parseHTML: (element) => element.getAttribute("data-index"),
|
|
17
|
+
renderHTML: (attributes) => {
|
|
18
|
+
return {
|
|
19
|
+
"data-index": attributes.index,
|
|
20
|
+
};
|
|
21
|
+
},
|
|
20
22
|
},
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
26
|
+
addInputRules() {
|
|
27
|
+
return [
|
|
28
|
+
// Creates an ordered list when starting with "1.".
|
|
29
|
+
new InputRule({
|
|
30
|
+
find: new RegExp(`^1\\.\\s$`),
|
|
31
|
+
handler: ({ state, chain, range }) => {
|
|
32
|
+
chain()
|
|
33
|
+
.BNUpdateBlock(state.selection.from, {
|
|
34
|
+
type: "numberedListItem",
|
|
35
|
+
props: {},
|
|
36
|
+
})
|
|
37
|
+
// Removes the "1." characters used to set the list.
|
|
38
|
+
.deleteRange({ from: range.from, to: range.to });
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
];
|
|
42
|
+
},
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
addKeyboardShortcuts() {
|
|
45
|
+
return {
|
|
46
|
+
Enter: () => handleEnter(this.editor),
|
|
47
|
+
};
|
|
48
|
+
},
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
addProseMirrorPlugins() {
|
|
51
|
+
return [NumberedListIndexingPlugin()];
|
|
52
|
+
},
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
parseHTML() {
|
|
55
|
+
return [
|
|
56
|
+
// Case for regular HTML list structure.
|
|
57
|
+
// (e.g.: when pasting from other apps)
|
|
58
|
+
{
|
|
59
|
+
tag: "li",
|
|
60
|
+
getAttrs: (element) => {
|
|
61
|
+
if (typeof element === "string") {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
const parent = element.parentElement;
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
if (parent === null) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
if (parent.tagName === "OL") {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
73
74
|
|
|
74
|
-
return false;
|
|
75
|
-
},
|
|
76
|
-
node: "numberedListItem",
|
|
77
|
-
},
|
|
78
|
-
// Case for BlockNote list structure.
|
|
79
|
-
// (e.g.: when pasting from blocknote)
|
|
80
|
-
{
|
|
81
|
-
tag: "p",
|
|
82
|
-
getAttrs: (element) => {
|
|
83
|
-
if (typeof element === "string") {
|
|
84
75
|
return false;
|
|
85
|
-
}
|
|
76
|
+
},
|
|
77
|
+
node: "numberedListItem",
|
|
78
|
+
},
|
|
79
|
+
// Case for BlockNote list structure.
|
|
80
|
+
// (e.g.: when pasting from blocknote)
|
|
81
|
+
{
|
|
82
|
+
tag: "p",
|
|
83
|
+
getAttrs: (element) => {
|
|
84
|
+
if (typeof element === "string") {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
const parent = element.parentElement;
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
if (parent === null) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
if (
|
|
95
|
+
parent.getAttribute("data-content-type") === "numberedListItem"
|
|
96
|
+
) {
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
return false;
|
|
101
|
+
},
|
|
102
|
+
priority: 300,
|
|
103
|
+
node: "numberedListItem",
|
|
98
104
|
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
},
|
|
102
|
-
];
|
|
103
|
-
},
|
|
105
|
+
];
|
|
106
|
+
},
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
108
|
+
renderHTML({ HTMLAttributes }) {
|
|
109
|
+
return [
|
|
110
|
+
"div",
|
|
111
|
+
mergeAttributes(HTMLAttributes, {
|
|
112
|
+
class: styles.blockContent,
|
|
113
|
+
"data-content-type": this.name,
|
|
114
|
+
}),
|
|
115
|
+
// we use a <p> tag, because for <li> tags we'd need to add a <ul> parent for around siblings to be semantically correct,
|
|
116
|
+
// which would be quite cumbersome
|
|
117
|
+
["p", { class: styles.inlineContent }, 0],
|
|
118
|
+
];
|
|
119
|
+
},
|
|
120
|
+
});
|
package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { mergeAttributes
|
|
1
|
+
import { mergeAttributes } from "@tiptap/core";
|
|
2
|
+
import { createTipTapBlock } from "../../../api/block";
|
|
2
3
|
import styles from "../../Block.module.css";
|
|
3
4
|
|
|
4
|
-
export const ParagraphBlockContent =
|
|
5
|
+
export const ParagraphBlockContent = createTipTapBlock<"paragraph">({
|
|
5
6
|
name: "paragraph",
|
|
6
|
-
group: "blockContent",
|
|
7
7
|
content: "inline*",
|
|
8
8
|
|
|
9
9
|
parseHTML() {
|
|
@@ -23,7 +23,7 @@ export const ParagraphBlockContent = Node.create({
|
|
|
23
23
|
class: styles.blockContent,
|
|
24
24
|
"data-content-type": this.name,
|
|
25
25
|
}),
|
|
26
|
-
["p", 0],
|
|
26
|
+
["p", { class: styles.inlineContent }, 0],
|
|
27
27
|
];
|
|
28
28
|
},
|
|
29
29
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
2
2
|
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
3
|
-
import { Block } from "../Blocks/api/blockTypes";
|
|
3
|
+
import { Block, BlockSchema } from "../Blocks/api/blockTypes";
|
|
4
4
|
|
|
5
|
-
export type BlockSideMenuStaticParams = {
|
|
6
|
-
editor: BlockNoteEditor
|
|
5
|
+
export type BlockSideMenuStaticParams<BSchema extends BlockSchema> = {
|
|
6
|
+
editor: BlockNoteEditor<BSchema>;
|
|
7
7
|
|
|
8
8
|
addBlock: () => void;
|
|
9
9
|
|
|
@@ -14,14 +14,16 @@ export type BlockSideMenuStaticParams = {
|
|
|
14
14
|
unfreezeMenu: () => void;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export type BlockSideMenuDynamicParams = {
|
|
18
|
-
block: Block
|
|
17
|
+
export type BlockSideMenuDynamicParams<BSchema extends BlockSchema> = {
|
|
18
|
+
block: Block<BSchema>;
|
|
19
19
|
|
|
20
20
|
referenceRect: DOMRect;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
export type BlockSideMenu = EditorElement<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
export type BlockSideMenu<BSchema extends BlockSchema> = EditorElement<
|
|
24
|
+
BlockSideMenuDynamicParams<BSchema>
|
|
25
|
+
>;
|
|
26
|
+
export type BlockSideMenuFactory<BSchema extends BlockSchema> = ElementFactory<
|
|
27
|
+
BlockSideMenuStaticParams<BSchema>,
|
|
28
|
+
BlockSideMenuDynamicParams<BSchema>
|
|
27
29
|
>;
|
|
@@ -2,11 +2,12 @@ import { Editor, Extension } from "@tiptap/core";
|
|
|
2
2
|
import { BlockSideMenuFactory } from "./BlockSideMenuFactoryTypes";
|
|
3
3
|
import { createDraggableBlocksPlugin } from "./DraggableBlocksPlugin";
|
|
4
4
|
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
5
|
+
import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
5
6
|
|
|
6
|
-
export type DraggableBlocksOptions = {
|
|
7
|
+
export type DraggableBlocksOptions<BSchema extends BlockSchema> = {
|
|
7
8
|
tiptapEditor: Editor;
|
|
8
|
-
editor: BlockNoteEditor
|
|
9
|
-
blockSideMenuFactory: BlockSideMenuFactory
|
|
9
|
+
editor: BlockNoteEditor<BSchema>;
|
|
10
|
+
blockSideMenuFactory: BlockSideMenuFactory<BSchema>;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -15,8 +16,8 @@ export type DraggableBlocksOptions = {
|
|
|
15
16
|
*
|
|
16
17
|
* code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799
|
|
17
18
|
*/
|
|
18
|
-
export const
|
|
19
|
-
Extension.create<DraggableBlocksOptions
|
|
19
|
+
export const createDraggableBlocksExtension = <BSchema extends BlockSchema>() =>
|
|
20
|
+
Extension.create<DraggableBlocksOptions<BSchema>>({
|
|
20
21
|
name: "DraggableBlocksExtension",
|
|
21
22
|
priority: 1000, // Need to be high, in order to hide menu when typing slash
|
|
22
23
|
addProseMirrorPlugins() {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import { DraggableBlocksOptions } from "./DraggableBlocksExtension";
|
|
16
16
|
import { MultipleNodeSelection } from "./MultipleNodeSelection";
|
|
17
17
|
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
18
|
+
import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
18
19
|
|
|
19
20
|
const serializeForClipboard = (pv as any).__serializeForClipboard;
|
|
20
21
|
// code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799
|
|
@@ -223,15 +224,15 @@ function dragStart(e: DragEvent, view: EditorView) {
|
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
226
|
|
|
226
|
-
export type BlockMenuViewProps = {
|
|
227
|
+
export type BlockMenuViewProps<BSchema extends BlockSchema> = {
|
|
227
228
|
tiptapEditor: Editor;
|
|
228
|
-
editor: BlockNoteEditor
|
|
229
|
-
blockMenuFactory: BlockSideMenuFactory
|
|
229
|
+
editor: BlockNoteEditor<BSchema>;
|
|
230
|
+
blockMenuFactory: BlockSideMenuFactory<BSchema>;
|
|
230
231
|
horizontalPosAnchoredAtRoot: boolean;
|
|
231
232
|
};
|
|
232
233
|
|
|
233
|
-
export class BlockMenuView {
|
|
234
|
-
editor: BlockNoteEditor
|
|
234
|
+
export class BlockMenuView<BSchema extends BlockSchema> {
|
|
235
|
+
editor: BlockNoteEditor<BSchema>;
|
|
235
236
|
private ttEditor: Editor;
|
|
236
237
|
|
|
237
238
|
// When true, the drag handle with be anchored at the same level as root elements
|
|
@@ -240,7 +241,7 @@ export class BlockMenuView {
|
|
|
240
241
|
|
|
241
242
|
horizontalPosAnchor: number;
|
|
242
243
|
|
|
243
|
-
blockMenu: BlockSideMenu
|
|
244
|
+
blockMenu: BlockSideMenu<BSchema>;
|
|
244
245
|
|
|
245
246
|
hoveredBlock: HTMLElement | undefined;
|
|
246
247
|
|
|
@@ -254,7 +255,7 @@ export class BlockMenuView {
|
|
|
254
255
|
editor,
|
|
255
256
|
blockMenuFactory,
|
|
256
257
|
horizontalPosAnchoredAtRoot,
|
|
257
|
-
}: BlockMenuViewProps) {
|
|
258
|
+
}: BlockMenuViewProps<BSchema>) {
|
|
258
259
|
this.editor = editor;
|
|
259
260
|
this.ttEditor = tiptapEditor;
|
|
260
261
|
this.horizontalPosAnchoredAtRoot = horizontalPosAnchoredAtRoot;
|
|
@@ -497,7 +498,7 @@ export class BlockMenuView {
|
|
|
497
498
|
);
|
|
498
499
|
}
|
|
499
500
|
|
|
500
|
-
getStaticParams(): BlockSideMenuStaticParams {
|
|
501
|
+
getStaticParams(): BlockSideMenuStaticParams<BSchema> {
|
|
501
502
|
return {
|
|
502
503
|
editor: this.editor,
|
|
503
504
|
addBlock: () => this.addBlock(),
|
|
@@ -516,7 +517,7 @@ export class BlockMenuView {
|
|
|
516
517
|
};
|
|
517
518
|
}
|
|
518
519
|
|
|
519
|
-
getDynamicParams(): BlockSideMenuDynamicParams {
|
|
520
|
+
getDynamicParams(): BlockSideMenuDynamicParams<BSchema> {
|
|
520
521
|
const blockContent = this.hoveredBlock!.firstChild! as HTMLElement;
|
|
521
522
|
const blockContentBoundingBox = blockContent.getBoundingClientRect();
|
|
522
523
|
|
|
@@ -534,8 +535,8 @@ export class BlockMenuView {
|
|
|
534
535
|
}
|
|
535
536
|
}
|
|
536
537
|
|
|
537
|
-
export const createDraggableBlocksPlugin = (
|
|
538
|
-
options: DraggableBlocksOptions
|
|
538
|
+
export const createDraggableBlocksPlugin = <BSchema extends BlockSchema>(
|
|
539
|
+
options: DraggableBlocksOptions<BSchema>
|
|
539
540
|
) => {
|
|
540
541
|
return new Plugin({
|
|
541
542
|
key: new PluginKey("DraggableBlocksPlugin"),
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { Extension } from "@tiptap/core";
|
|
2
2
|
import { PluginKey } from "prosemirror-state";
|
|
3
|
-
import { BlockNoteEditor } from "../..";
|
|
3
|
+
import { BlockNoteEditor, BlockSchema } from "../..";
|
|
4
4
|
import { FormattingToolbarFactory } from "./FormattingToolbarFactoryTypes";
|
|
5
5
|
import { createFormattingToolbarPlugin } from "./FormattingToolbarPlugin";
|
|
6
6
|
|
|
7
|
+
export type FormattingToolbarOptions<BSchema extends BlockSchema> = {
|
|
8
|
+
formattingToolbarFactory: FormattingToolbarFactory<BSchema>;
|
|
9
|
+
editor: BlockNoteEditor<BSchema>;
|
|
10
|
+
};
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* The menu that is displayed when selecting a piece of text.
|
|
9
14
|
*/
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
export const createFormattingToolbarExtension = <
|
|
16
|
+
BSchema extends BlockSchema
|
|
17
|
+
>() =>
|
|
18
|
+
Extension.create<FormattingToolbarOptions<BSchema>>({
|
|
19
|
+
name: "FormattingToolbarExtension",
|
|
15
20
|
|
|
16
21
|
addProseMirrorPlugins() {
|
|
17
22
|
if (!this.options.formattingToolbarFactory || !this.options.editor) {
|
|
@@ -20,13 +25,13 @@ export const FormattingToolbarExtension = Extension.create<{
|
|
|
20
25
|
);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
28
|
+
return [
|
|
29
|
+
createFormattingToolbarPlugin({
|
|
30
|
+
tiptapEditor: this.editor,
|
|
31
|
+
editor: this.options.editor,
|
|
32
|
+
formattingToolbarFactory: this.options.formattingToolbarFactory,
|
|
33
|
+
pluginKey: new PluginKey("FormattingToolbarPlugin"),
|
|
34
|
+
}),
|
|
35
|
+
];
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
2
2
|
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
3
|
+
import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
3
4
|
|
|
4
|
-
export type FormattingToolbarStaticParams = {
|
|
5
|
-
editor: BlockNoteEditor
|
|
5
|
+
export type FormattingToolbarStaticParams<BSchema extends BlockSchema> = {
|
|
6
|
+
editor: BlockNoteEditor<BSchema>;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export type FormattingToolbarDynamicParams = {
|
|
9
10
|
referenceRect: DOMRect;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
export type FormattingToolbar = EditorElement<
|
|
13
|
-
export type FormattingToolbarFactory = ElementFactory<
|
|
14
|
-
FormattingToolbarStaticParams,
|
|
13
|
+
export type FormattingToolbar = EditorElement<
|
|
15
14
|
FormattingToolbarDynamicParams
|
|
16
15
|
>;
|
|
16
|
+
export type FormattingToolbarFactory<BSchema extends BlockSchema> =
|
|
17
|
+
ElementFactory<
|
|
18
|
+
FormattingToolbarStaticParams<BSchema>,
|
|
19
|
+
FormattingToolbarDynamicParams
|
|
20
|
+
>;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "@tiptap/core";
|
|
7
7
|
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
8
8
|
import { EditorView } from "prosemirror-view";
|
|
9
|
-
import { BlockNoteEditor } from "../..";
|
|
9
|
+
import { BlockNoteEditor, BlockSchema } from "../..";
|
|
10
10
|
import {
|
|
11
11
|
FormattingToolbar,
|
|
12
12
|
FormattingToolbarDynamicParams,
|
|
@@ -16,29 +16,20 @@ import {
|
|
|
16
16
|
|
|
17
17
|
// Same as TipTap bubblemenu plugin, but with these changes:
|
|
18
18
|
// https://github.com/ueberdosis/tiptap/pull/2596/files
|
|
19
|
-
export interface FormattingToolbarPluginProps {
|
|
19
|
+
export interface FormattingToolbarPluginProps<BSchema extends BlockSchema> {
|
|
20
20
|
pluginKey: PluginKey;
|
|
21
21
|
tiptapEditor: Editor;
|
|
22
|
-
editor: BlockNoteEditor
|
|
23
|
-
formattingToolbarFactory: FormattingToolbarFactory
|
|
24
|
-
shouldShow?:
|
|
25
|
-
| ((props: {
|
|
26
|
-
editor: BlockNoteEditor;
|
|
27
|
-
view: EditorView;
|
|
28
|
-
state: EditorState;
|
|
29
|
-
oldState?: EditorState;
|
|
30
|
-
from: number;
|
|
31
|
-
to: number;
|
|
32
|
-
}) => boolean)
|
|
33
|
-
| null;
|
|
22
|
+
editor: BlockNoteEditor<BSchema>;
|
|
23
|
+
formattingToolbarFactory: FormattingToolbarFactory<BSchema>;
|
|
34
24
|
}
|
|
35
25
|
|
|
36
|
-
export type FormattingToolbarViewProps
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
export type FormattingToolbarViewProps<BSchema extends BlockSchema> =
|
|
27
|
+
FormattingToolbarPluginProps<BSchema> & {
|
|
28
|
+
view: EditorView;
|
|
29
|
+
};
|
|
39
30
|
|
|
40
|
-
export class FormattingToolbarView {
|
|
41
|
-
public editor: BlockNoteEditor
|
|
31
|
+
export class FormattingToolbarView<BSchema extends BlockSchema> {
|
|
32
|
+
public editor: BlockNoteEditor<BSchema>;
|
|
42
33
|
private ttEditor: Editor;
|
|
43
34
|
|
|
44
35
|
public view: EditorView;
|
|
@@ -53,44 +44,43 @@ export class FormattingToolbarView {
|
|
|
53
44
|
|
|
54
45
|
public prevWasEditable: boolean | null = null;
|
|
55
46
|
|
|
56
|
-
public shouldShow:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
public shouldShow: (props: {
|
|
48
|
+
view: EditorView;
|
|
49
|
+
state: EditorState;
|
|
50
|
+
from: number;
|
|
51
|
+
to: number;
|
|
52
|
+
}) => boolean = ({ view, state, from, to }) => {
|
|
53
|
+
const { doc, selection } = state;
|
|
54
|
+
const { empty } = selection;
|
|
60
55
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
// Sometime check for `empty` is not enough.
|
|
57
|
+
// Doubleclick an empty paragraph returns a node size of 2.
|
|
58
|
+
// So we check also for an empty text size.
|
|
59
|
+
const isEmptyTextBlock =
|
|
60
|
+
!doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
66
61
|
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
return !(!view.hasFocus() || empty || isEmptyTextBlock);
|
|
63
|
+
};
|
|
69
64
|
|
|
70
65
|
constructor({
|
|
71
66
|
editor,
|
|
72
67
|
tiptapEditor,
|
|
73
68
|
formattingToolbarFactory,
|
|
74
69
|
view,
|
|
75
|
-
|
|
76
|
-
}: FormattingToolbarViewProps) {
|
|
70
|
+
}: FormattingToolbarViewProps<BSchema>) {
|
|
77
71
|
this.editor = editor;
|
|
78
72
|
this.ttEditor = tiptapEditor;
|
|
79
73
|
this.view = view;
|
|
80
74
|
|
|
81
75
|
this.formattingToolbar = formattingToolbarFactory(this.getStaticParams());
|
|
82
76
|
|
|
83
|
-
if (shouldShow) {
|
|
84
|
-
this.shouldShow = shouldShow;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
77
|
this.view.dom.addEventListener("mousedown", this.viewMousedownHandler);
|
|
88
78
|
this.view.dom.addEventListener("mouseup", this.viewMouseupHandler);
|
|
89
79
|
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
|
|
90
80
|
|
|
91
81
|
this.ttEditor.on("focus", this.focusHandler);
|
|
92
82
|
this.ttEditor.on("blur", this.blurHandler);
|
|
93
|
-
|
|
83
|
+
|
|
94
84
|
document.addEventListener("scroll", this.scrollHandler);
|
|
95
85
|
}
|
|
96
86
|
|
|
@@ -163,10 +153,8 @@ export class FormattingToolbarView {
|
|
|
163
153
|
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
164
154
|
|
|
165
155
|
const shouldShow = this.shouldShow?.({
|
|
166
|
-
editor: this.editor,
|
|
167
156
|
view,
|
|
168
157
|
state,
|
|
169
|
-
oldState,
|
|
170
158
|
from,
|
|
171
159
|
to,
|
|
172
160
|
});
|
|
@@ -250,7 +238,7 @@ export class FormattingToolbarView {
|
|
|
250
238
|
return posToDOMRect(this.ttEditor.view, from, to);
|
|
251
239
|
}
|
|
252
240
|
|
|
253
|
-
getStaticParams(): FormattingToolbarStaticParams {
|
|
241
|
+
getStaticParams(): FormattingToolbarStaticParams<BSchema> {
|
|
254
242
|
return {
|
|
255
243
|
editor: this.editor,
|
|
256
244
|
};
|
|
@@ -263,8 +251,8 @@ export class FormattingToolbarView {
|
|
|
263
251
|
}
|
|
264
252
|
}
|
|
265
253
|
|
|
266
|
-
export const createFormattingToolbarPlugin = (
|
|
267
|
-
options: FormattingToolbarPluginProps
|
|
254
|
+
export const createFormattingToolbarPlugin = <BSchema extends BlockSchema>(
|
|
255
|
+
options: FormattingToolbarPluginProps<BSchema>
|
|
268
256
|
) => {
|
|
269
257
|
return new Plugin({
|
|
270
258
|
key: new PluginKey("FormattingToolbarPlugin"),
|
|
@@ -72,6 +72,7 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
|
|
|
72
72
|
if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
|
|
73
73
|
const classes = [this.options.emptyNodeClass];
|
|
74
74
|
|
|
75
|
+
// TODO: Doesn't work?
|
|
75
76
|
if (this.editor.isEmpty) {
|
|
76
77
|
classes.push(this.options.emptyEditorClass);
|
|
77
78
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { SuggestionItem } from "../../shared/plugins/suggestion/SuggestionItem";
|
|
2
2
|
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
3
|
+
import { BlockSchema } from "../Blocks/api/blockTypes";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* A class that defines a slash command (/<command>).
|
|
6
7
|
*
|
|
7
8
|
* (Not to be confused with ProseMirror commands nor TipTap commands.)
|
|
8
9
|
*/
|
|
9
|
-
export class BaseSlashMenuItem
|
|
10
|
+
export class BaseSlashMenuItem<
|
|
11
|
+
BSchema extends BlockSchema
|
|
12
|
+
> extends SuggestionItem {
|
|
10
13
|
/**
|
|
11
14
|
* Constructs a new slash-command.
|
|
12
15
|
*
|
|
@@ -16,7 +19,7 @@ export class BaseSlashMenuItem extends SuggestionItem {
|
|
|
16
19
|
*/
|
|
17
20
|
constructor(
|
|
18
21
|
public readonly name: string,
|
|
19
|
-
public readonly execute: (editor: BlockNoteEditor) => void,
|
|
22
|
+
public readonly execute: (editor: BlockNoteEditor<BSchema>) => void,
|
|
20
23
|
public readonly aliases: string[] = []
|
|
21
24
|
) {
|
|
22
25
|
super(name, (query: string): boolean => {
|