@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.
- package/README.md +12 -6
- package/dist/blocknote.js +1425 -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 +19 -32
- 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 +5 -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
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Editor,
|
|
3
|
+
isNodeSelection,
|
|
4
|
+
isTextSelection,
|
|
5
|
+
posToDOMRect,
|
|
6
|
+
} from "@tiptap/core";
|
|
7
|
+
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
8
|
+
import { EditorView } from "prosemirror-view";
|
|
9
|
+
import {
|
|
10
|
+
FormattingToolbar,
|
|
11
|
+
FormattingToolbarDynamicParams,
|
|
12
|
+
FormattingToolbarFactory,
|
|
13
|
+
FormattingToolbarStaticParams,
|
|
14
|
+
} from "./FormattingToolbarFactoryTypes";
|
|
15
|
+
import { BlockContentType } from "../Blocks/nodes/Block";
|
|
16
|
+
|
|
17
|
+
// Same as TipTap bubblemenu plugin, but with these changes:
|
|
18
|
+
// https://github.com/ueberdosis/tiptap/pull/2596/files
|
|
19
|
+
export interface FormattingToolbarPluginProps {
|
|
20
|
+
pluginKey: PluginKey;
|
|
21
|
+
editor: Editor;
|
|
22
|
+
formattingToolbarFactory: FormattingToolbarFactory;
|
|
23
|
+
shouldShow?:
|
|
24
|
+
| ((props: {
|
|
25
|
+
editor: Editor;
|
|
26
|
+
view: EditorView;
|
|
27
|
+
state: EditorState;
|
|
28
|
+
oldState?: EditorState;
|
|
29
|
+
from: number;
|
|
30
|
+
to: number;
|
|
31
|
+
}) => boolean)
|
|
32
|
+
| null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type FormattingToolbarViewProps = FormattingToolbarPluginProps & {
|
|
36
|
+
view: EditorView;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export class FormattingToolbarView {
|
|
40
|
+
public editor: Editor;
|
|
41
|
+
|
|
42
|
+
public view: EditorView;
|
|
43
|
+
|
|
44
|
+
public formattingToolbar: FormattingToolbar;
|
|
45
|
+
|
|
46
|
+
public preventHide = false;
|
|
47
|
+
|
|
48
|
+
public preventShow = false;
|
|
49
|
+
|
|
50
|
+
public toolbarIsOpen = false;
|
|
51
|
+
|
|
52
|
+
public shouldShow: Exclude<FormattingToolbarPluginProps["shouldShow"], null> =
|
|
53
|
+
({ view, state, from, to }) => {
|
|
54
|
+
const { doc, selection } = state;
|
|
55
|
+
const { empty } = selection;
|
|
56
|
+
|
|
57
|
+
// Sometime check for `empty` is not enough.
|
|
58
|
+
// Doubleclick an empty paragraph returns a node size of 2.
|
|
59
|
+
// So we check also for an empty text size.
|
|
60
|
+
const isEmptyTextBlock =
|
|
61
|
+
!doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
62
|
+
|
|
63
|
+
return !(!view.hasFocus() || empty || isEmptyTextBlock);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
constructor({
|
|
67
|
+
editor,
|
|
68
|
+
formattingToolbarFactory,
|
|
69
|
+
view,
|
|
70
|
+
shouldShow,
|
|
71
|
+
}: FormattingToolbarViewProps) {
|
|
72
|
+
this.editor = editor;
|
|
73
|
+
this.view = view;
|
|
74
|
+
|
|
75
|
+
this.formattingToolbar = formattingToolbarFactory(this.getStaticParams());
|
|
76
|
+
|
|
77
|
+
if (shouldShow) {
|
|
78
|
+
this.shouldShow = shouldShow;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.view.dom.addEventListener("mousedown", this.viewMousedownHandler);
|
|
82
|
+
this.view.dom.addEventListener("mouseup", this.viewMouseupHandler);
|
|
83
|
+
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
|
|
84
|
+
|
|
85
|
+
this.editor.on("focus", this.focusHandler);
|
|
86
|
+
this.editor.on("blur", this.blurHandler);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
viewMousedownHandler = () => {
|
|
90
|
+
this.preventShow = true;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
viewMouseupHandler = () => {
|
|
94
|
+
this.preventShow = false;
|
|
95
|
+
setTimeout(() => this.update(this.editor.view));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
dragstartHandler = () => {
|
|
99
|
+
this.formattingToolbar.hide();
|
|
100
|
+
this.toolbarIsOpen = false;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
focusHandler = () => {
|
|
104
|
+
// we use `setTimeout` to make sure `selection` is already updated
|
|
105
|
+
setTimeout(() => this.update(this.editor.view));
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
blurHandler = ({ event }: { event: FocusEvent }) => {
|
|
109
|
+
if (this.preventHide) {
|
|
110
|
+
this.preventHide = false;
|
|
111
|
+
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
event?.relatedTarget &&
|
|
117
|
+
this.formattingToolbar.element?.parentNode?.contains(
|
|
118
|
+
event.relatedTarget as Node
|
|
119
|
+
)
|
|
120
|
+
) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this.toolbarIsOpen) {
|
|
125
|
+
this.formattingToolbar.hide();
|
|
126
|
+
this.toolbarIsOpen = false;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
update(view: EditorView, oldState?: EditorState) {
|
|
131
|
+
const { state, composing } = view;
|
|
132
|
+
const { doc, selection } = state;
|
|
133
|
+
const isSame =
|
|
134
|
+
oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);
|
|
135
|
+
|
|
136
|
+
if (composing || isSame) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// support for CellSelections
|
|
141
|
+
const { ranges } = selection;
|
|
142
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
143
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
144
|
+
|
|
145
|
+
const shouldShow = this.shouldShow?.({
|
|
146
|
+
editor: this.editor,
|
|
147
|
+
view,
|
|
148
|
+
state,
|
|
149
|
+
oldState,
|
|
150
|
+
from,
|
|
151
|
+
to,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Checks if menu should be shown.
|
|
155
|
+
if (
|
|
156
|
+
!this.toolbarIsOpen &&
|
|
157
|
+
!this.preventShow &&
|
|
158
|
+
(shouldShow || this.preventHide)
|
|
159
|
+
) {
|
|
160
|
+
this.formattingToolbar.render(this.getDynamicParams(), true);
|
|
161
|
+
this.toolbarIsOpen = true;
|
|
162
|
+
|
|
163
|
+
// TODO: Is this necessary? Also for other menu plugins.
|
|
164
|
+
// Listener stops focus moving to the menu on click.
|
|
165
|
+
this.formattingToolbar.element!.addEventListener("mousedown", (event) =>
|
|
166
|
+
event.preventDefault()
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Checks if menu should be updated.
|
|
173
|
+
if (
|
|
174
|
+
this.toolbarIsOpen &&
|
|
175
|
+
!this.preventShow &&
|
|
176
|
+
(shouldShow || this.preventHide)
|
|
177
|
+
) {
|
|
178
|
+
this.formattingToolbar.render(this.getDynamicParams(), false);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Checks if menu should be hidden.
|
|
183
|
+
if (
|
|
184
|
+
this.toolbarIsOpen &&
|
|
185
|
+
!this.preventHide &&
|
|
186
|
+
(!shouldShow || this.preventShow)
|
|
187
|
+
) {
|
|
188
|
+
this.formattingToolbar.hide();
|
|
189
|
+
this.toolbarIsOpen = false;
|
|
190
|
+
|
|
191
|
+
// Listener stops focus moving to the menu on click.
|
|
192
|
+
this.formattingToolbar.element!.removeEventListener(
|
|
193
|
+
"mousedown",
|
|
194
|
+
(event) => event.preventDefault()
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
destroy() {
|
|
202
|
+
this.view.dom.removeEventListener("mousedown", this.viewMousedownHandler);
|
|
203
|
+
this.view.dom.removeEventListener("mouseup", this.viewMouseupHandler);
|
|
204
|
+
this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
|
|
205
|
+
|
|
206
|
+
this.editor.off("focus", this.focusHandler);
|
|
207
|
+
this.editor.off("blur", this.blurHandler);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
getSelectionBoundingBox() {
|
|
211
|
+
const { state } = this.editor.view;
|
|
212
|
+
const { selection } = state;
|
|
213
|
+
|
|
214
|
+
// support for CellSelections
|
|
215
|
+
const { ranges } = selection;
|
|
216
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
217
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
218
|
+
|
|
219
|
+
if (isNodeSelection(selection)) {
|
|
220
|
+
const node = this.editor.view.nodeDOM(from) as HTMLElement;
|
|
221
|
+
|
|
222
|
+
if (node) {
|
|
223
|
+
return node.getBoundingClientRect();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return posToDOMRect(this.editor.view, from, to);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
getStaticParams(): FormattingToolbarStaticParams {
|
|
231
|
+
return {
|
|
232
|
+
toggleBold: () => {
|
|
233
|
+
this.editor.view.focus();
|
|
234
|
+
this.editor.commands.toggleBold();
|
|
235
|
+
},
|
|
236
|
+
toggleItalic: () => {
|
|
237
|
+
this.editor.view.focus();
|
|
238
|
+
this.editor.commands.toggleItalic();
|
|
239
|
+
},
|
|
240
|
+
toggleUnderline: () => {
|
|
241
|
+
this.editor.view.focus();
|
|
242
|
+
this.editor.commands.toggleUnderline();
|
|
243
|
+
},
|
|
244
|
+
toggleStrike: () => {
|
|
245
|
+
this.editor.view.focus();
|
|
246
|
+
this.editor.commands.toggleStrike();
|
|
247
|
+
},
|
|
248
|
+
setHyperlink: (url: string, text?: string) => {
|
|
249
|
+
if (url === "") {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
let { from, to } = this.editor.state.selection;
|
|
254
|
+
|
|
255
|
+
if (!text) {
|
|
256
|
+
text = this.editor.state.doc.textBetween(from, to);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const mark = this.editor.schema.mark("link", { href: url });
|
|
260
|
+
|
|
261
|
+
this.editor.view.dispatch(
|
|
262
|
+
this.editor.view.state.tr
|
|
263
|
+
.insertText(text, from, to)
|
|
264
|
+
.addMark(from, from + text.length, mark)
|
|
265
|
+
);
|
|
266
|
+
this.editor.view.focus();
|
|
267
|
+
},
|
|
268
|
+
setBlockType: (type: BlockContentType) => {
|
|
269
|
+
this.editor.view.focus();
|
|
270
|
+
this.editor.commands.BNSetContentType(
|
|
271
|
+
this.editor.state.selection.from,
|
|
272
|
+
type
|
|
273
|
+
);
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
getDynamicParams(): FormattingToolbarDynamicParams {
|
|
279
|
+
return {
|
|
280
|
+
boldIsActive: this.editor.isActive("bold"),
|
|
281
|
+
italicIsActive: this.editor.isActive("italic"),
|
|
282
|
+
underlineIsActive: this.editor.isActive("underline"),
|
|
283
|
+
strikeIsActive: this.editor.isActive("strike"),
|
|
284
|
+
hyperlinkIsActive: this.editor.isActive("link"),
|
|
285
|
+
activeHyperlinkUrl: this.editor.getAttributes("link").href
|
|
286
|
+
? this.editor.getAttributes("link").href
|
|
287
|
+
: "",
|
|
288
|
+
activeHyperlinkText: this.editor.state.doc.textBetween(
|
|
289
|
+
this.editor.state.selection.from,
|
|
290
|
+
this.editor.state.selection.to
|
|
291
|
+
),
|
|
292
|
+
activeBlockType: {
|
|
293
|
+
name: this.editor.state.selection.$from.node().type.name,
|
|
294
|
+
attrs: this.editor.state.selection.$from.node().attrs,
|
|
295
|
+
} as Required<BlockContentType>,
|
|
296
|
+
selectionBoundingBox: this.getSelectionBoundingBox(),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export const createFormattingToolbarPlugin = (
|
|
302
|
+
options: FormattingToolbarPluginProps
|
|
303
|
+
) => {
|
|
304
|
+
return new Plugin({
|
|
305
|
+
key: new PluginKey("FormattingToolbarPlugin"),
|
|
306
|
+
view: (view) => new FormattingToolbarView({ view, ...options }),
|
|
307
|
+
});
|
|
308
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Link } from "@tiptap/extension-link";
|
|
2
|
+
import {
|
|
3
|
+
createHyperlinkToolbarPlugin,
|
|
4
|
+
HyperlinkToolbarPluginProps,
|
|
5
|
+
} from "./HyperlinkToolbarPlugin";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This custom link includes a special menu for editing/deleting/opening the link.
|
|
9
|
+
* The menu will be triggered by hovering over the link with the mouse,
|
|
10
|
+
* or by moving the cursor inside the link text
|
|
11
|
+
*/
|
|
12
|
+
const Hyperlink = Link.extend<HyperlinkToolbarPluginProps>({
|
|
13
|
+
priority: 500,
|
|
14
|
+
addProseMirrorPlugins() {
|
|
15
|
+
if (!this.options.hyperlinkToolbarFactory) {
|
|
16
|
+
throw new Error("UI Element factory not defined for HyperlinkMark");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return [
|
|
20
|
+
...(this.parent?.() || []),
|
|
21
|
+
createHyperlinkToolbarPlugin(this.editor, {
|
|
22
|
+
hyperlinkToolbarFactory: this.options.hyperlinkToolbarFactory,
|
|
23
|
+
}),
|
|
24
|
+
];
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export default Hyperlink;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EditorElement, ElementFactory } from "../../shared/EditorElement";
|
|
2
|
+
|
|
3
|
+
export type HyperlinkToolbarStaticParams = {
|
|
4
|
+
editHyperlink: (url: string, text: string) => void;
|
|
5
|
+
deleteHyperlink: () => void;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type HyperlinkToolbarDynamicParams = {
|
|
9
|
+
url: string;
|
|
10
|
+
text: string;
|
|
11
|
+
|
|
12
|
+
boundingBox: DOMRect;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type HyperlinkToolbar = EditorElement<HyperlinkToolbarDynamicParams>;
|
|
16
|
+
export type HyperlinkToolbarFactory = ElementFactory<
|
|
17
|
+
HyperlinkToolbarStaticParams,
|
|
18
|
+
HyperlinkToolbarDynamicParams
|
|
19
|
+
>;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { Editor, getMarkRange, posToDOMRect, Range } from "@tiptap/core";
|
|
2
|
+
import { Mark } from "prosemirror-model";
|
|
3
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
4
|
+
import {
|
|
5
|
+
HyperlinkToolbar,
|
|
6
|
+
HyperlinkToolbarDynamicParams,
|
|
7
|
+
HyperlinkToolbarFactory,
|
|
8
|
+
HyperlinkToolbarStaticParams,
|
|
9
|
+
} from "./HyperlinkToolbarFactoryTypes";
|
|
10
|
+
const PLUGIN_KEY = new PluginKey("HyperlinkToolbarPlugin");
|
|
11
|
+
|
|
12
|
+
export type HyperlinkToolbarPluginProps = {
|
|
13
|
+
hyperlinkToolbarFactory: HyperlinkToolbarFactory;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type HyperlinkToolbarViewProps = {
|
|
17
|
+
editor: Editor;
|
|
18
|
+
hyperlinkToolbarFactory: HyperlinkToolbarFactory;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
class HyperlinkToolbarView {
|
|
22
|
+
editor: Editor;
|
|
23
|
+
|
|
24
|
+
hyperlinkToolbar: HyperlinkToolbar;
|
|
25
|
+
|
|
26
|
+
menuUpdateTimer: NodeJS.Timeout | undefined;
|
|
27
|
+
startMenuUpdateTimer: () => void;
|
|
28
|
+
stopMenuUpdateTimer: () => void;
|
|
29
|
+
|
|
30
|
+
mouseHoveredHyperlinkMark: Mark | undefined;
|
|
31
|
+
mouseHoveredHyperlinkMarkRange: Range | undefined;
|
|
32
|
+
|
|
33
|
+
keyboardHoveredHyperlinkMark: Mark | undefined;
|
|
34
|
+
keyboardHoveredHyperlinkMarkRange: Range | undefined;
|
|
35
|
+
|
|
36
|
+
hyperlinkMark: Mark | undefined;
|
|
37
|
+
hyperlinkMarkRange: Range | undefined;
|
|
38
|
+
|
|
39
|
+
constructor({ editor, hyperlinkToolbarFactory }: HyperlinkToolbarViewProps) {
|
|
40
|
+
this.editor = editor;
|
|
41
|
+
|
|
42
|
+
this.hyperlinkToolbar = hyperlinkToolbarFactory(this.getStaticParams());
|
|
43
|
+
|
|
44
|
+
this.startMenuUpdateTimer = () => {
|
|
45
|
+
this.menuUpdateTimer = setTimeout(() => {
|
|
46
|
+
this.update();
|
|
47
|
+
}, 250);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
this.stopMenuUpdateTimer = () => {
|
|
51
|
+
if (this.menuUpdateTimer) {
|
|
52
|
+
clearTimeout(this.menuUpdateTimer);
|
|
53
|
+
this.menuUpdateTimer = undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
editor.view.dom.addEventListener("mouseover", (event) => {
|
|
60
|
+
// Resets the hyperlink mark currently hovered by the mouse cursor.
|
|
61
|
+
this.mouseHoveredHyperlinkMark = undefined;
|
|
62
|
+
this.mouseHoveredHyperlinkMarkRange = undefined;
|
|
63
|
+
|
|
64
|
+
this.stopMenuUpdateTimer();
|
|
65
|
+
|
|
66
|
+
if (
|
|
67
|
+
event.target instanceof HTMLAnchorElement &&
|
|
68
|
+
event.target.nodeName === "A"
|
|
69
|
+
) {
|
|
70
|
+
// Finds link mark at the hovered element's position to update mouseHoveredHyperlinkMark and
|
|
71
|
+
// mouseHoveredHyperlinkMarkRange.
|
|
72
|
+
const hoveredHyperlinkElement = event.target;
|
|
73
|
+
const posInHoveredHyperlinkMark =
|
|
74
|
+
editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;
|
|
75
|
+
const resolvedPosInHoveredHyperlinkMark = editor.state.doc.resolve(
|
|
76
|
+
posInHoveredHyperlinkMark
|
|
77
|
+
);
|
|
78
|
+
const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();
|
|
79
|
+
|
|
80
|
+
for (const mark of marksAtPos) {
|
|
81
|
+
if (mark.type.name === editor.schema.mark("link").type.name) {
|
|
82
|
+
this.mouseHoveredHyperlinkMark = mark;
|
|
83
|
+
this.mouseHoveredHyperlinkMarkRange =
|
|
84
|
+
getMarkRange(
|
|
85
|
+
resolvedPosInHoveredHyperlinkMark,
|
|
86
|
+
mark.type,
|
|
87
|
+
mark.attrs
|
|
88
|
+
) || undefined;
|
|
89
|
+
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.startMenuUpdateTimer();
|
|
96
|
+
|
|
97
|
+
return false;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
update() {
|
|
102
|
+
if (!this.editor.view.hasFocus()) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Saves the currently hovered hyperlink mark before it's updated.
|
|
107
|
+
const prevHyperlinkMark = this.hyperlinkMark;
|
|
108
|
+
|
|
109
|
+
// Resets the currently hovered hyperlink mark.
|
|
110
|
+
this.hyperlinkMark = undefined;
|
|
111
|
+
this.hyperlinkMarkRange = undefined;
|
|
112
|
+
|
|
113
|
+
// Resets the hyperlink mark currently hovered by the keyboard cursor.
|
|
114
|
+
this.keyboardHoveredHyperlinkMark = undefined;
|
|
115
|
+
this.keyboardHoveredHyperlinkMarkRange = undefined;
|
|
116
|
+
|
|
117
|
+
// Finds link mark at the editor selection's position to update keyboardHoveredHyperlinkMark and
|
|
118
|
+
// keyboardHoveredHyperlinkMarkRange.
|
|
119
|
+
if (this.editor.state.selection.empty) {
|
|
120
|
+
const marksAtPos = this.editor.state.selection.$from.marks();
|
|
121
|
+
|
|
122
|
+
for (const mark of marksAtPos) {
|
|
123
|
+
if (mark.type.name === this.editor.schema.mark("link").type.name) {
|
|
124
|
+
this.keyboardHoveredHyperlinkMark = mark;
|
|
125
|
+
this.keyboardHoveredHyperlinkMarkRange =
|
|
126
|
+
getMarkRange(
|
|
127
|
+
this.editor.state.selection.$from,
|
|
128
|
+
mark.type,
|
|
129
|
+
mark.attrs
|
|
130
|
+
) || undefined;
|
|
131
|
+
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.mouseHoveredHyperlinkMark) {
|
|
138
|
+
this.hyperlinkMark = this.mouseHoveredHyperlinkMark;
|
|
139
|
+
this.hyperlinkMarkRange = this.mouseHoveredHyperlinkMarkRange;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Keyboard cursor position takes precedence over mouse hovered hyperlink.
|
|
143
|
+
if (this.keyboardHoveredHyperlinkMark) {
|
|
144
|
+
this.hyperlinkMark = this.keyboardHoveredHyperlinkMark;
|
|
145
|
+
this.hyperlinkMarkRange = this.keyboardHoveredHyperlinkMarkRange;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (this.hyperlinkMark) {
|
|
149
|
+
this.getDynamicParams();
|
|
150
|
+
|
|
151
|
+
// Shows menu.
|
|
152
|
+
if (!prevHyperlinkMark) {
|
|
153
|
+
this.hyperlinkToolbar.render(this.getDynamicParams(), true);
|
|
154
|
+
|
|
155
|
+
this.hyperlinkToolbar.element?.addEventListener(
|
|
156
|
+
"mouseleave",
|
|
157
|
+
this.startMenuUpdateTimer
|
|
158
|
+
);
|
|
159
|
+
this.hyperlinkToolbar.element?.addEventListener(
|
|
160
|
+
"mouseenter",
|
|
161
|
+
this.stopMenuUpdateTimer
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Updates menu.
|
|
168
|
+
this.hyperlinkToolbar.render(this.getDynamicParams(), false);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Hides menu.
|
|
172
|
+
if (!this.hyperlinkMark && prevHyperlinkMark) {
|
|
173
|
+
this.hyperlinkToolbar.element?.removeEventListener(
|
|
174
|
+
"mouseleave",
|
|
175
|
+
this.startMenuUpdateTimer
|
|
176
|
+
);
|
|
177
|
+
this.hyperlinkToolbar.element?.removeEventListener(
|
|
178
|
+
"mouseenter",
|
|
179
|
+
this.stopMenuUpdateTimer
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
this.hyperlinkToolbar.hide();
|
|
183
|
+
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getStaticParams(): HyperlinkToolbarStaticParams {
|
|
189
|
+
return {
|
|
190
|
+
editHyperlink: (url: string, text: string) => {
|
|
191
|
+
const tr = this.editor.view.state.tr.insertText(
|
|
192
|
+
text,
|
|
193
|
+
this.hyperlinkMarkRange!.from,
|
|
194
|
+
this.hyperlinkMarkRange!.to
|
|
195
|
+
);
|
|
196
|
+
tr.addMark(
|
|
197
|
+
this.hyperlinkMarkRange!.from,
|
|
198
|
+
this.hyperlinkMarkRange!.from + text.length,
|
|
199
|
+
this.editor.schema.mark("link", { href: url })
|
|
200
|
+
);
|
|
201
|
+
this.editor.view.dispatch(tr);
|
|
202
|
+
this.editor.view.focus();
|
|
203
|
+
|
|
204
|
+
this.hyperlinkToolbar.hide();
|
|
205
|
+
},
|
|
206
|
+
deleteHyperlink: () => {
|
|
207
|
+
this.editor.view.dispatch(
|
|
208
|
+
this.editor.view.state.tr
|
|
209
|
+
.removeMark(
|
|
210
|
+
this.hyperlinkMarkRange!.from,
|
|
211
|
+
this.hyperlinkMarkRange!.to,
|
|
212
|
+
this.hyperlinkMark!.type
|
|
213
|
+
)
|
|
214
|
+
.setMeta("preventAutolink", true)
|
|
215
|
+
);
|
|
216
|
+
this.editor.view.focus();
|
|
217
|
+
|
|
218
|
+
this.hyperlinkToolbar.hide();
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
getDynamicParams(): HyperlinkToolbarDynamicParams {
|
|
224
|
+
return {
|
|
225
|
+
url: this.hyperlinkMark!.attrs.href,
|
|
226
|
+
text: this.editor.view.state.doc.textBetween(
|
|
227
|
+
this.hyperlinkMarkRange!.from,
|
|
228
|
+
this.hyperlinkMarkRange!.to
|
|
229
|
+
),
|
|
230
|
+
boundingBox: posToDOMRect(
|
|
231
|
+
this.editor.view,
|
|
232
|
+
this.hyperlinkMarkRange!.from,
|
|
233
|
+
this.hyperlinkMarkRange!.to
|
|
234
|
+
),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const createHyperlinkToolbarPlugin = (
|
|
240
|
+
editor: Editor,
|
|
241
|
+
options: HyperlinkToolbarPluginProps
|
|
242
|
+
) => {
|
|
243
|
+
return new Plugin({
|
|
244
|
+
key: PLUGIN_KEY,
|
|
245
|
+
view: () =>
|
|
246
|
+
new HyperlinkToolbarView({
|
|
247
|
+
editor: editor,
|
|
248
|
+
hyperlinkToolbarFactory: options.hyperlinkToolbarFactory,
|
|
249
|
+
}),
|
|
250
|
+
});
|
|
251
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Editor, Extension } from "@tiptap/core";
|
|
2
2
|
import { Node as ProsemirrorNode } from "prosemirror-model";
|
|
3
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
3
4
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4
|
-
import { Plugin } from "prosemirror-state";
|
|
5
5
|
import { SlashMenuPluginKey } from "../SlashMenu/SlashMenuExtension";
|
|
6
6
|
|
|
7
|
+
const PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* This is a modified version of the tiptap
|
|
9
11
|
* placeholder plugin, that also sets hasAnchorClass
|
|
@@ -48,6 +50,7 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
|
|
|
48
50
|
addProseMirrorPlugins() {
|
|
49
51
|
return [
|
|
50
52
|
new Plugin({
|
|
53
|
+
key: PLUGIN_KEY,
|
|
51
54
|
props: {
|
|
52
55
|
decorations: (state) => {
|
|
53
56
|
const { doc, selection } = state;
|
|
@@ -78,7 +81,7 @@ export const Placeholder = Extension.create<PlaceholderOptions>({
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
// If slash menu is of drag type and active, show the filter placeholder
|
|
81
|
-
if (menuState
|
|
84
|
+
if (menuState?.type === "drag" && menuState?.active) {
|
|
82
85
|
classes.push(this.options.isFilterClass);
|
|
83
86
|
}
|
|
84
87
|
// using widget, didn't work (caret position bug)
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { PluginKey } from "prosemirror-state";
|
|
2
3
|
import { createSuggestionPlugin } from "../../shared/plugins/suggestion/SuggestionPlugin";
|
|
4
|
+
import { SuggestionsMenuFactory } from "../../shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
|
|
3
5
|
import defaultCommands from "./defaultCommands";
|
|
4
6
|
import { SlashMenuItem } from "./SlashMenuItem";
|
|
5
|
-
import { PluginKey } from "prosemirror-state";
|
|
6
7
|
|
|
7
8
|
export type SlashMenuOptions = {
|
|
8
9
|
commands: { [key: string]: SlashMenuItem };
|
|
10
|
+
slashMenuFactory: SuggestionsMenuFactory<any> | undefined;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
export const SlashMenuPluginKey = new PluginKey("suggestions-slash-commands");
|
|
@@ -16,15 +18,21 @@ export const SlashMenuExtension = Extension.create<SlashMenuOptions>({
|
|
|
16
18
|
addOptions() {
|
|
17
19
|
return {
|
|
18
20
|
commands: defaultCommands,
|
|
21
|
+
slashMenuFactory: undefined, // TODO: fix undefined
|
|
19
22
|
};
|
|
20
23
|
},
|
|
21
24
|
|
|
22
25
|
addProseMirrorPlugins() {
|
|
26
|
+
if (!this.options.slashMenuFactory) {
|
|
27
|
+
throw new Error("UI Element factory not defined for SlashMenuExtension");
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
return [
|
|
24
31
|
createSuggestionPlugin<SlashMenuItem>({
|
|
25
32
|
pluginKey: SlashMenuPluginKey,
|
|
26
33
|
editor: this.editor,
|
|
27
34
|
char: "/",
|
|
35
|
+
suggestionsMenuFactory: this.options.slashMenuFactory!,
|
|
28
36
|
items: (query) => {
|
|
29
37
|
const commands = [];
|
|
30
38
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Editor, Range } from "@tiptap/core";
|
|
2
|
-
import SuggestionItem from "../../shared/plugins/suggestion/SuggestionItem";
|
|
3
|
-
import { IconType } from "react-icons";
|
|
2
|
+
import { SuggestionItem } from "../../shared/plugins/suggestion/SuggestionItem";
|
|
4
3
|
|
|
5
4
|
export type SlashMenuCallback = (editor: Editor, range: Range) => boolean;
|
|
6
5
|
|
|
@@ -40,7 +39,6 @@ export class SlashMenuItem implements SuggestionItem {
|
|
|
40
39
|
public readonly group: SlashMenuGroups,
|
|
41
40
|
public readonly execute: SlashMenuCallback,
|
|
42
41
|
public readonly aliases: string[] = [],
|
|
43
|
-
public readonly icon?: IconType,
|
|
44
42
|
public readonly hint?: string,
|
|
45
43
|
public readonly shortcut?: string
|
|
46
44
|
) {
|