@blocknote/core 0.12.4 → 0.13.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 +1079 -685
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +6 -6
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +2 -2
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +1 -1
- package/src/editor/BlockNoteEditor.ts +24 -8
- package/src/editor/BlockNoteExtensions.ts +22 -11
- package/src/editor/BlockNoteTipTapEditor.ts +9 -6
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +24 -41
- package/src/extensions/ImagePanel/ImageToolbarPlugin.ts +27 -30
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +25 -3
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +95 -0
- package/src/extensions/SideMenu/SideMenuPlugin.ts +3 -2
- package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +3 -0
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +6 -2
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +18 -44
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +1 -1
- package/src/i18n/dictionary.ts +17 -0
- package/src/i18n/locales/en.ts +196 -0
- package/src/i18n/locales/index.ts +2 -0
- package/src/i18n/locales/nl.ts +197 -0
- package/src/index.ts +4 -1
- package/src/pm-nodes/BlockContainer.ts +17 -1
- package/src/util/browser.ts +2 -2
- package/src/util/typescript.ts +8 -0
- package/types/src/editor/BlockNoteEditor.d.ts +11 -1
- package/types/src/editor/BlockNoteExtensions.d.ts +3 -3
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -4
- package/types/src/extensions/ImagePanel/ImageToolbarPlugin.d.ts +7 -5
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +3 -1
- package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +3 -0
- package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +2 -0
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +2 -1
- package/types/src/i18n/dictionary.d.ts +2 -0
- package/types/src/i18n/locales/en.d.ts +184 -0
- package/types/src/i18n/locales/index.d.ts +2 -0
- package/types/src/i18n/locales/nl.d.ts +2 -0
- package/types/src/index.d.ts +4 -1
- package/types/src/pm-nodes/BlockContainer.d.ts +1 -1
- package/types/src/util/browser.d.ts +1 -1
- package/types/src/util/typescript.d.ts +1 -0
- package/src/extensions/Placeholder/PlaceholderExtension.ts +0 -124
- package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +0 -12
package/dist/webpack-stats.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"builtAt":
|
|
1
|
+
{"builtAt":1714926597310,"assets":[{"name":"blocknote.umd.cjs","size":109661},{"name":"blocknote.umd.cjs.map","size":481369}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/i18n/locales/en.ts","size":4307,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/nl.ts","size":4477,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/index.ts","size":0,"chunks":["a1ee98a"]},{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8518,"chunks":["a1ee98a"]},{"name":"./src/api/getBlockInfoFromPos.ts","size":1691,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/types.ts","size":302,"chunks":["a1ee98a"]},{"name":"./src/util/typescript.ts","size":331,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/nodeConversions.ts","size":11959,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/sharedHTMLConversion.ts","size":2293,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","size":2687,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":1066,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":704,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":536,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1731,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":3701,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":2781,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1357,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":1627,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/api/getCurrentBlockContentType.ts","size":192,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":3439,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":9303,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1151,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":2964,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":1862,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":3421,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":1172,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":1462,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":1207,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1025,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockTypeGuards.ts","size":757,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":548,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/blockManipulation.ts","size":5738,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":549,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/util/nestedLists.ts","size":2174,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/parseHTML.ts","size":503,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/markdown/parseMarkdown.ts","size":1054,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":4287,"chunks":["a1ee98a"]},{"name":"./src/extensions/ImagePanel/ImageToolbarPlugin.ts","size":3393,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/LinkToolbarPlugin.ts","size":7273,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/SuggestionPlugin.ts","size":7646,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":14952,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":14755,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/copyExtension.ts","size":2883,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/pasteExtension.ts","size":1131,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":688,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":748,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":622,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1594,"chunks":["a1ee98a"]},{"name":"./src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","size":467,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4578,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":17589,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockGroup.ts","size":1097,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/Doc.ts","size":90,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteExtensions.ts","size":3859,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":1017,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteSchema.ts","size":827,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteTipTapEditor.ts","size":2655,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderPlugin.ts","size":2253,"chunks":["a1ee98a"]},{"name":"./src/editor/Block.css","size":17,"chunks":["a1ee98a"]},{"name":"./src/editor/editor.css","size":18,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":22961,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","size":4553,"chunks":["a1ee98a"]},{"name":"./src/api/testUtil/partialBlockTestUtil.ts","size":2166,"chunks":["a1ee98a"]},{"name":"./src/index.ts","size":0,"chunks":["a1ee98a"]}]}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://github.com/TypeCellOS/BlockNote",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.13.0",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"types",
|
|
@@ -116,5 +116,5 @@
|
|
|
116
116
|
"access": "public",
|
|
117
117
|
"registry": "https://registry.npmjs.org/"
|
|
118
118
|
},
|
|
119
|
-
"gitHead": "
|
|
119
|
+
"gitHead": "501dc35254104a4ee56718ee299d31d534586b55"
|
|
120
120
|
}
|
|
@@ -76,7 +76,7 @@ export const renderImage = (
|
|
|
76
76
|
// Text for the add image button.
|
|
77
77
|
const addImageButtonText = document.createElement("p");
|
|
78
78
|
addImageButtonText.className = "bn-add-image-button-text";
|
|
79
|
-
addImageButtonText.innerText =
|
|
79
|
+
addImageButtonText.innerText = editor.dictionary.image.add_button;
|
|
80
80
|
|
|
81
81
|
// Wrapper element for the image, resize handles and caption.
|
|
82
82
|
const imageAndCaptionWrapper = document.createElement("div");
|
|
@@ -27,10 +27,10 @@ import {
|
|
|
27
27
|
PartialBlock,
|
|
28
28
|
} from "../blocks/defaultBlocks";
|
|
29
29
|
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin";
|
|
30
|
+
import { ImagePanelProsemirrorPlugin } from "../extensions/ImagePanel/ImageToolbarPlugin";
|
|
30
31
|
import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkToolbarPlugin";
|
|
31
32
|
import { SideMenuProsemirrorPlugin } from "../extensions/SideMenu/SideMenuPlugin";
|
|
32
33
|
import { SuggestionMenuProseMirrorPlugin } from "../extensions/SuggestionMenu/SuggestionPlugin";
|
|
33
|
-
import { ImagePanelProsemirrorPlugin } from "../extensions/ImagePanel/ImageToolbarPlugin";
|
|
34
34
|
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin";
|
|
35
35
|
import { UniqueID } from "../extensions/UniqueID/UniqueID";
|
|
36
36
|
import {
|
|
@@ -62,6 +62,9 @@ import {
|
|
|
62
62
|
} from "./BlockNoteTipTapEditor";
|
|
63
63
|
|
|
64
64
|
// CSS
|
|
65
|
+
import { PlaceholderPlugin } from "../extensions/Placeholder/PlaceholderPlugin";
|
|
66
|
+
import { Dictionary } from "../i18n/dictionary";
|
|
67
|
+
import { en } from "../i18n/locales";
|
|
65
68
|
import "./Block.css";
|
|
66
69
|
import "./editor.css";
|
|
67
70
|
|
|
@@ -73,6 +76,14 @@ export type BlockNoteEditorOptions<
|
|
|
73
76
|
// TODO: Figure out if enableBlockNoteExtensions/disableHistoryExtension are needed and document them.
|
|
74
77
|
enableBlockNoteExtensions: boolean;
|
|
75
78
|
|
|
79
|
+
/**
|
|
80
|
+
* A dictionary object containing translations for the editor.
|
|
81
|
+
*/
|
|
82
|
+
dictionary?: Dictionary;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @deprecated, provide placeholders via dictionary instead
|
|
86
|
+
*/
|
|
76
87
|
placeholders: Record<string | "default", string>;
|
|
77
88
|
|
|
78
89
|
/**
|
|
@@ -133,6 +144,8 @@ export type BlockNoteEditorOptions<
|
|
|
133
144
|
|
|
134
145
|
// tiptap options, undocumented
|
|
135
146
|
_tiptapOptions: Partial<EditorOptions>;
|
|
147
|
+
|
|
148
|
+
trailingBlock?: boolean;
|
|
136
149
|
};
|
|
137
150
|
|
|
138
151
|
const blockNoteTipTapOptions = {
|
|
@@ -150,6 +163,8 @@ export class BlockNoteEditor<
|
|
|
150
163
|
contentComponent: any;
|
|
151
164
|
};
|
|
152
165
|
public blockCache = new WeakMap<Node, Block<any, any, any>>();
|
|
166
|
+
public readonly dictionary: Dictionary;
|
|
167
|
+
|
|
153
168
|
public readonly schema: BlockNoteSchema<BSchema, ISchema, SSchema>;
|
|
154
169
|
|
|
155
170
|
public readonly blockImplementations: BlockSpecs;
|
|
@@ -216,11 +231,17 @@ export class BlockNoteEditor<
|
|
|
216
231
|
);
|
|
217
232
|
}
|
|
218
233
|
|
|
234
|
+
this.dictionary = options.dictionary || en;
|
|
235
|
+
|
|
219
236
|
// apply defaults
|
|
220
237
|
const newOptions = {
|
|
221
238
|
defaultStyles: true,
|
|
222
239
|
schema: options.schema || BlockNoteSchema.create(),
|
|
223
240
|
...options,
|
|
241
|
+
placeholders: {
|
|
242
|
+
...this.dictionary.placeholders,
|
|
243
|
+
...options.placeholders,
|
|
244
|
+
},
|
|
224
245
|
};
|
|
225
246
|
|
|
226
247
|
// @ts-ignore
|
|
@@ -243,13 +264,13 @@ export class BlockNoteEditor<
|
|
|
243
264
|
|
|
244
265
|
const extensions = getBlockNoteExtensions({
|
|
245
266
|
editor: this,
|
|
246
|
-
placeholders: newOptions.placeholders,
|
|
247
267
|
domAttributes: newOptions.domAttributes || {},
|
|
248
268
|
blockSchema: this.schema.blockSchema,
|
|
249
269
|
blockSpecs: this.schema.blockSpecs,
|
|
250
270
|
styleSpecs: this.schema.styleSpecs,
|
|
251
271
|
inlineContentSpecs: this.schema.inlineContentSpecs,
|
|
252
272
|
collaboration: newOptions.collaboration,
|
|
273
|
+
trailingBlock: newOptions.trailingBlock,
|
|
253
274
|
});
|
|
254
275
|
|
|
255
276
|
const blockNoteUIExtension = Extension.create({
|
|
@@ -263,6 +284,7 @@ export class BlockNoteEditor<
|
|
|
263
284
|
this.suggestionMenus.plugin,
|
|
264
285
|
...(this.imagePanel ? [this.imagePanel.plugin] : []),
|
|
265
286
|
...(this.tableHandles ? [this.tableHandles.plugin] : []),
|
|
287
|
+
PlaceholderPlugin(this, newOptions.placeholders),
|
|
266
288
|
];
|
|
267
289
|
},
|
|
268
290
|
});
|
|
@@ -759,8 +781,6 @@ export class BlockNoteEditor<
|
|
|
759
781
|
* @param styles The styles to add.
|
|
760
782
|
*/
|
|
761
783
|
public addStyles(styles: Styles<SSchema>) {
|
|
762
|
-
this._tiptapEditor.view.focus();
|
|
763
|
-
|
|
764
784
|
for (const [style, value] of Object.entries(styles)) {
|
|
765
785
|
const config = this.schema.styleSchema[style];
|
|
766
786
|
if (!config) {
|
|
@@ -781,8 +801,6 @@ export class BlockNoteEditor<
|
|
|
781
801
|
* @param styles The styles to remove.
|
|
782
802
|
*/
|
|
783
803
|
public removeStyles(styles: Styles<SSchema>) {
|
|
784
|
-
this._tiptapEditor.view.focus();
|
|
785
|
-
|
|
786
804
|
for (const style of Object.keys(styles)) {
|
|
787
805
|
this._tiptapEditor.commands.unsetMark(style);
|
|
788
806
|
}
|
|
@@ -793,8 +811,6 @@ export class BlockNoteEditor<
|
|
|
793
811
|
* @param styles The styles to toggle.
|
|
794
812
|
*/
|
|
795
813
|
public toggleStyles(styles: Styles<SSchema>) {
|
|
796
|
-
this._tiptapEditor.view.focus();
|
|
797
|
-
|
|
798
814
|
for (const [style, value] of Object.entries(styles)) {
|
|
799
815
|
const config = this.schema.styleSchema[style];
|
|
800
816
|
if (!config) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Extensions, extensions } from "@tiptap/core";
|
|
1
|
+
import { Extension, Extensions, extensions } from "@tiptap/core";
|
|
2
2
|
|
|
3
3
|
import type { BlockNoteEditor } from "./BlockNoteEditor";
|
|
4
4
|
|
|
@@ -14,7 +14,6 @@ import * as Y from "yjs";
|
|
|
14
14
|
import { createCopyToClipboardExtension } from "../api/exporters/copyExtension";
|
|
15
15
|
import { createPasteFromClipboardExtension } from "../api/parsers/pasteExtension";
|
|
16
16
|
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension";
|
|
17
|
-
import { Placeholder } from "../extensions/Placeholder/PlaceholderExtension";
|
|
18
17
|
import { TextAlignmentExtension } from "../extensions/TextAlignment/TextAlignmentExtension";
|
|
19
18
|
import { TextColorExtension } from "../extensions/TextColor/TextColorExtension";
|
|
20
19
|
import { TrailingNode } from "../extensions/TrailingNode/TrailingNodeExtension";
|
|
@@ -39,12 +38,12 @@ export const getBlockNoteExtensions = <
|
|
|
39
38
|
S extends StyleSchema
|
|
40
39
|
>(opts: {
|
|
41
40
|
editor: BlockNoteEditor<BSchema, I, S>;
|
|
42
|
-
placeholders?: Record<string | "default", string>;
|
|
43
41
|
domAttributes: Partial<BlockNoteDOMAttributes>;
|
|
44
42
|
blockSchema: BSchema;
|
|
45
43
|
blockSpecs: BlockSpecs;
|
|
46
44
|
inlineContentSpecs: InlineContentSpecs;
|
|
47
45
|
styleSpecs: StyleSpecs;
|
|
46
|
+
trailingBlock: boolean | undefined;
|
|
48
47
|
collaboration?: {
|
|
49
48
|
fragment: Y.XmlFragment;
|
|
50
49
|
user: {
|
|
@@ -66,12 +65,6 @@ export const getBlockNoteExtensions = <
|
|
|
66
65
|
Gapcursor,
|
|
67
66
|
|
|
68
67
|
// DropCursor,
|
|
69
|
-
Placeholder.configure({
|
|
70
|
-
// TODO: This shorthand is kind of ugly
|
|
71
|
-
...(opts.placeholders !== undefined
|
|
72
|
-
? { placeholders: opts.placeholders }
|
|
73
|
-
: {}),
|
|
74
|
-
}),
|
|
75
68
|
UniqueID.configure({
|
|
76
69
|
types: ["blockContainer"],
|
|
77
70
|
}),
|
|
@@ -92,10 +85,26 @@ export const getBlockNoteExtensions = <
|
|
|
92
85
|
BackgroundColorExtension,
|
|
93
86
|
TextAlignmentExtension,
|
|
94
87
|
|
|
88
|
+
// make sure escape blurs editor, so that we can tab to other elements in the host page (accessibility)
|
|
89
|
+
Extension.create({
|
|
90
|
+
name: "OverrideEscape",
|
|
91
|
+
addKeyboardShortcuts() {
|
|
92
|
+
return {
|
|
93
|
+
Escape: () => {
|
|
94
|
+
if (opts.editor.suggestionMenus.shown) {
|
|
95
|
+
// escape is handled by suggestionmenu
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return this.editor.commands.blur();
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
}),
|
|
103
|
+
|
|
95
104
|
// nodes
|
|
96
105
|
Doc,
|
|
97
106
|
BlockContainer.configure({
|
|
98
|
-
editor: opts.editor
|
|
107
|
+
editor: opts.editor,
|
|
99
108
|
domAttributes: opts.domAttributes,
|
|
100
109
|
}),
|
|
101
110
|
BlockGroup.configure({
|
|
@@ -131,7 +140,9 @@ export const getBlockNoteExtensions = <
|
|
|
131
140
|
Dropcursor.configure({ width: 5, color: "#ddeeff" }),
|
|
132
141
|
// This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),
|
|
133
142
|
// should be handled before Enter handlers in other components like splitListItem
|
|
134
|
-
|
|
143
|
+
...(opts.trailingBlock === undefined || opts.trailingBlock
|
|
144
|
+
? [TrailingNode]
|
|
145
|
+
: []),
|
|
135
146
|
];
|
|
136
147
|
|
|
137
148
|
if (opts.collaboration) {
|
|
@@ -126,12 +126,15 @@ export class BlockNoteTipTapEditor extends TiptapEditor {
|
|
|
126
126
|
private createViewAlternative() {
|
|
127
127
|
// Without queueMicrotask, custom IC / styles will give a React FlushSync error
|
|
128
128
|
queueMicrotask(() => {
|
|
129
|
-
this.view = new EditorView(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
this.view = new EditorView(
|
|
130
|
+
{ mount: this.options.element as any }, // use mount option so that we reuse the existing element instead of creating a new one
|
|
131
|
+
{
|
|
132
|
+
...this.options.editorProps,
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
dispatchTransaction: this.dispatchTransaction.bind(this),
|
|
135
|
+
state: this.state,
|
|
136
|
+
}
|
|
137
|
+
);
|
|
135
138
|
|
|
136
139
|
// `editor.view` is not yet available at this time.
|
|
137
140
|
// Therefore we will add all plugins and node views directly afterwards.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNodeSelection, posToDOMRect } from "@tiptap/core";
|
|
2
|
-
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
2
|
+
import { EditorState, Plugin, PluginKey, PluginView } from "prosemirror-state";
|
|
3
3
|
import { EditorView } from "prosemirror-view";
|
|
4
4
|
|
|
5
5
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
@@ -9,7 +9,7 @@ import { EventEmitter } from "../../util/EventEmitter";
|
|
|
9
9
|
|
|
10
10
|
export type FormattingToolbarState = UiElementPosition;
|
|
11
11
|
|
|
12
|
-
export class FormattingToolbarView {
|
|
12
|
+
export class FormattingToolbarView implements PluginView {
|
|
13
13
|
public state?: FormattingToolbarState;
|
|
14
14
|
public emitUpdate: () => void;
|
|
15
15
|
|
|
@@ -48,9 +48,6 @@ export class FormattingToolbarView {
|
|
|
48
48
|
pmView.dom.addEventListener("dragstart", this.dragHandler);
|
|
49
49
|
pmView.dom.addEventListener("dragover", this.dragHandler);
|
|
50
50
|
|
|
51
|
-
pmView.dom.addEventListener("focus", this.focusHandler);
|
|
52
|
-
pmView.dom.addEventListener("blur", this.blurHandler);
|
|
53
|
-
|
|
54
51
|
document.addEventListener("scroll", this.scrollHandler);
|
|
55
52
|
}
|
|
56
53
|
|
|
@@ -71,39 +68,6 @@ export class FormattingToolbarView {
|
|
|
71
68
|
}
|
|
72
69
|
};
|
|
73
70
|
|
|
74
|
-
focusHandler = () => {
|
|
75
|
-
// we use `setTimeout` to make sure `selection` is already updated
|
|
76
|
-
setTimeout(() => this.update(this.pmView));
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
blurHandler = (event: FocusEvent) => {
|
|
80
|
-
if (this.preventHide) {
|
|
81
|
-
this.preventHide = false;
|
|
82
|
-
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const editorWrapper = this.pmView.dom.parentElement!;
|
|
87
|
-
|
|
88
|
-
// Checks if the focus is moving to an element outside the editor. If it is,
|
|
89
|
-
// the toolbar is hidden.
|
|
90
|
-
if (
|
|
91
|
-
// An element is clicked.
|
|
92
|
-
event &&
|
|
93
|
-
event.relatedTarget &&
|
|
94
|
-
// Element is inside the editor.
|
|
95
|
-
(editorWrapper === (event.relatedTarget as Node) ||
|
|
96
|
-
editorWrapper.contains(event.relatedTarget as Node))
|
|
97
|
-
) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (this.state?.show) {
|
|
102
|
-
this.state.show = false;
|
|
103
|
-
this.emitUpdate();
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
71
|
scrollHandler = () => {
|
|
108
72
|
if (this.state?.show) {
|
|
109
73
|
this.state.referencePos = this.getSelectionBoundingBox();
|
|
@@ -174,12 +138,16 @@ export class FormattingToolbarView {
|
|
|
174
138
|
this.pmView.dom.removeEventListener("dragstart", this.dragHandler);
|
|
175
139
|
this.pmView.dom.removeEventListener("dragover", this.dragHandler);
|
|
176
140
|
|
|
177
|
-
this.pmView.dom.removeEventListener("focus", this.focusHandler);
|
|
178
|
-
this.pmView.dom.removeEventListener("blur", this.blurHandler);
|
|
179
|
-
|
|
180
141
|
document.removeEventListener("scroll", this.scrollHandler);
|
|
181
142
|
}
|
|
182
143
|
|
|
144
|
+
closeMenu = () => {
|
|
145
|
+
if (this.state?.show) {
|
|
146
|
+
this.state.show = false;
|
|
147
|
+
this.emitUpdate();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
183
151
|
getSelectionBoundingBox() {
|
|
184
152
|
const { state } = this.pmView;
|
|
185
153
|
const { selection } = state;
|
|
@@ -219,10 +187,25 @@ export class FormattingToolbarProsemirrorPlugin extends EventEmitter<any> {
|
|
|
219
187
|
});
|
|
220
188
|
return this.view;
|
|
221
189
|
},
|
|
190
|
+
props: {
|
|
191
|
+
handleKeyDown: (_view, event: KeyboardEvent) => {
|
|
192
|
+
if (event.key === "Escape" && this.shown) {
|
|
193
|
+
this.view!.closeMenu();
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
},
|
|
198
|
+
},
|
|
222
199
|
});
|
|
223
200
|
}
|
|
224
201
|
|
|
202
|
+
public get shown() {
|
|
203
|
+
return this.view?.state?.show || false;
|
|
204
|
+
}
|
|
205
|
+
|
|
225
206
|
public onUpdate(callback: (state: FormattingToolbarState) => void) {
|
|
226
207
|
return this.on("update", callback);
|
|
227
208
|
}
|
|
209
|
+
|
|
210
|
+
public closeMenu = () => this.view!.closeMenu();
|
|
228
211
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
1
|
+
import { EditorState, Plugin, PluginKey, PluginView } from "prosemirror-state";
|
|
2
2
|
import { EditorView } from "prosemirror-view";
|
|
3
3
|
|
|
4
|
+
import { DefaultBlockSchema } from "../../blocks/defaultBlocks";
|
|
4
5
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
6
|
+
import { UiElementPosition } from "../../extensions-shared/UiElementPosition";
|
|
5
7
|
import type {
|
|
6
8
|
BlockFromConfig,
|
|
7
9
|
InlineContentSchema,
|
|
8
10
|
StyleSchema,
|
|
9
11
|
} from "../../schema";
|
|
10
|
-
import { UiElementPosition } from "../../extensions-shared/UiElementPosition";
|
|
11
12
|
import { EventEmitter } from "../../util/EventEmitter";
|
|
12
|
-
import { DefaultBlockSchema } from "../../blocks/defaultBlocks";
|
|
13
13
|
|
|
14
14
|
export type ImagePanelState<
|
|
15
15
|
I extends InlineContentSchema,
|
|
@@ -22,7 +22,8 @@ export type ImagePanelState<
|
|
|
22
22
|
export class ImagePanelView<
|
|
23
23
|
I extends InlineContentSchema,
|
|
24
24
|
S extends StyleSchema
|
|
25
|
-
>
|
|
25
|
+
> implements PluginView
|
|
26
|
+
{
|
|
26
27
|
public state?: ImagePanelState<I, S>;
|
|
27
28
|
public emitUpdate: () => void;
|
|
28
29
|
|
|
@@ -45,8 +46,6 @@ export class ImagePanelView<
|
|
|
45
46
|
|
|
46
47
|
pmView.dom.addEventListener("dragstart", this.dragstartHandler);
|
|
47
48
|
|
|
48
|
-
pmView.dom.addEventListener("blur", this.blurHandler);
|
|
49
|
-
|
|
50
49
|
document.addEventListener("scroll", this.scrollHandler);
|
|
51
50
|
}
|
|
52
51
|
|
|
@@ -65,28 +64,6 @@ export class ImagePanelView<
|
|
|
65
64
|
}
|
|
66
65
|
};
|
|
67
66
|
|
|
68
|
-
blurHandler = (event: FocusEvent) => {
|
|
69
|
-
const editorWrapper = this.pmView.dom.parentElement!;
|
|
70
|
-
|
|
71
|
-
// Checks if the focus is moving to an element outside the editor. If it is,
|
|
72
|
-
// the panel is hidden.
|
|
73
|
-
if (
|
|
74
|
-
// An element is clicked.
|
|
75
|
-
event &&
|
|
76
|
-
event.relatedTarget &&
|
|
77
|
-
// Element is inside the editor.
|
|
78
|
-
(editorWrapper === (event.relatedTarget as Node) ||
|
|
79
|
-
editorWrapper.contains(event.relatedTarget as Node))
|
|
80
|
-
) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (this.state?.show) {
|
|
85
|
-
this.state.show = false;
|
|
86
|
-
this.emitUpdate();
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
67
|
scrollHandler = () => {
|
|
91
68
|
if (this.state?.show) {
|
|
92
69
|
const blockElement = document.querySelector(
|
|
@@ -131,13 +108,18 @@ export class ImagePanelView<
|
|
|
131
108
|
}
|
|
132
109
|
}
|
|
133
110
|
|
|
111
|
+
closeMenu = () => {
|
|
112
|
+
if (this.state?.show) {
|
|
113
|
+
this.state.show = false;
|
|
114
|
+
this.emitUpdate();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
134
118
|
destroy() {
|
|
135
119
|
this.pmView.dom.removeEventListener("mousedown", this.mouseDownHandler);
|
|
136
120
|
|
|
137
121
|
this.pmView.dom.removeEventListener("dragstart", this.dragstartHandler);
|
|
138
122
|
|
|
139
|
-
this.pmView.dom.removeEventListener("blur", this.blurHandler);
|
|
140
|
-
|
|
141
123
|
document.removeEventListener("scroll", this.scrollHandler);
|
|
142
124
|
}
|
|
143
125
|
}
|
|
@@ -170,6 +152,15 @@ export class ImagePanelProsemirrorPlugin<
|
|
|
170
152
|
);
|
|
171
153
|
return this.view;
|
|
172
154
|
},
|
|
155
|
+
props: {
|
|
156
|
+
handleKeyDown: (_view, event: KeyboardEvent) => {
|
|
157
|
+
if (event.key === "Escape" && this.shown) {
|
|
158
|
+
this.view!.closeMenu();
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
173
164
|
state: {
|
|
174
165
|
init: () => {
|
|
175
166
|
return {
|
|
@@ -189,7 +180,13 @@ export class ImagePanelProsemirrorPlugin<
|
|
|
189
180
|
});
|
|
190
181
|
}
|
|
191
182
|
|
|
183
|
+
public get shown() {
|
|
184
|
+
return this.view?.state?.show || false;
|
|
185
|
+
}
|
|
186
|
+
|
|
192
187
|
public onUpdate(callback: (state: ImagePanelState<I, S>) => void) {
|
|
193
188
|
return this.on("update", callback);
|
|
194
189
|
}
|
|
190
|
+
|
|
191
|
+
public closeMenu = () => this.view!.closeMenu();
|
|
195
192
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { getMarkRange, posToDOMRect, Range } from "@tiptap/core";
|
|
2
2
|
import { EditorView } from "@tiptap/pm/view";
|
|
3
3
|
import { Mark } from "prosemirror-model";
|
|
4
|
-
import { Plugin, PluginKey } from "prosemirror-state";
|
|
4
|
+
import { Plugin, PluginKey, PluginView } from "prosemirror-state";
|
|
5
5
|
|
|
6
6
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
7
|
-
import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
|
|
8
7
|
import { UiElementPosition } from "../../extensions-shared/UiElementPosition";
|
|
8
|
+
import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
|
|
9
9
|
import { EventEmitter } from "../../util/EventEmitter";
|
|
10
10
|
|
|
11
11
|
export type LinkToolbarState = UiElementPosition & {
|
|
@@ -15,7 +15,7 @@ export type LinkToolbarState = UiElementPosition & {
|
|
|
15
15
|
text: string;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
class LinkToolbarView {
|
|
18
|
+
class LinkToolbarView implements PluginView {
|
|
19
19
|
public state?: LinkToolbarState;
|
|
20
20
|
public emitUpdate: () => void;
|
|
21
21
|
|
|
@@ -258,6 +258,13 @@ class LinkToolbarView {
|
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
closeMenu = () => {
|
|
262
|
+
if (this.state?.show) {
|
|
263
|
+
this.state.show = false;
|
|
264
|
+
this.emitUpdate();
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
261
268
|
destroy() {
|
|
262
269
|
this.pmView.dom.removeEventListener("mouseover", this.mouseOverHandler);
|
|
263
270
|
document.removeEventListener("scroll", this.scrollHandler);
|
|
@@ -285,6 +292,15 @@ export class LinkToolbarProsemirrorPlugin<
|
|
|
285
292
|
});
|
|
286
293
|
return this.view;
|
|
287
294
|
},
|
|
295
|
+
props: {
|
|
296
|
+
handleKeyDown: (_view, event: KeyboardEvent) => {
|
|
297
|
+
if (event.key === "Escape" && this.shown) {
|
|
298
|
+
this.view!.closeMenu();
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
},
|
|
303
|
+
},
|
|
288
304
|
});
|
|
289
305
|
}
|
|
290
306
|
|
|
@@ -327,4 +343,10 @@ export class LinkToolbarProsemirrorPlugin<
|
|
|
327
343
|
public stopHideTimer = () => {
|
|
328
344
|
this.view!.stopMenuUpdateTimer();
|
|
329
345
|
};
|
|
346
|
+
|
|
347
|
+
public get shown() {
|
|
348
|
+
return this.view?.state?.show || false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
public closeMenu = () => this.view!.closeMenu();
|
|
330
352
|
}
|