@blocknote/core 0.15.9 → 0.15.11
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 +745 -719
- 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/api/blockManipulation/blockManipulation.test.ts +7 -32
- package/src/editor/BlockNoteEditor.ts +2 -2
- package/src/editor/BlockNoteTipTapEditor.ts +34 -7
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +26 -0
- package/src/schema/blocks/createSpec.ts +27 -2
- package/src/schema/blocks/types.ts +2 -0
- package/src/schema/inlineContent/createSpec.ts +7 -4
- package/types/src/editor/BlockNoteEditor.d.ts +1 -1
- package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -1
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +3 -0
- package/types/src/schema/blocks/createSpec.d.ts +3 -0
- package/types/src/schema/blocks/types.d.ts +2 -0
- package/types/src/schema/inlineContent/createSpec.d.ts +3 -2
package/dist/webpack-stats.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"builtAt":
|
|
1
|
+
{"builtAt":1727710427090,"assets":[{"name":"blocknote.umd.cjs","size":200565},{"name":"blocknote.umd.cjs.map","size":726187}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/i18n/locales/ar.ts","size":6582,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/de.ts","size":7183,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/en.ts","size":6664,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/es.ts","size":6796,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/fr.ts","size":7294,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/is.ts","size":6876,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ja.ts","size":6323,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ko.ts","size":6146,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/nl.ts","size":7079,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pl.ts","size":6768,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pt.ts","size":6965,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ru.ts","size":7638,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/vi.ts","size":6927,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/zh.ts","size":6093,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/index.ts","size":0,"chunks":["a1ee98a"]},{"name":"./src/util/esmDependencies.ts","size":820,"chunks":["a1ee98a"]},{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8887,"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":11998,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/sharedHTMLConversion.ts","size":2311,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","size":4488,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":1320,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":758,"chunks":["a1ee98a"]},{"name":"./src/api/getCurrentBlockContentType.ts","size":192,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":536,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1691,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":299,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":3877,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":3229,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1357,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":2761,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/fileBlockHelpers.ts","size":10029,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/audioBlockHelpers.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/AudioBlockContent.ts","size":3075,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/FileBlockContent.ts","size":1581,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/imageBlockHelpers.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":3242,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/videoBlockHelpers.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/VideoBlockContent.ts","size":3050,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":3439,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1201,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":3122,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":1862,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":3437,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts","size":6423,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":1307,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":1462,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":1624,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1123,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockTypeGuards.ts","size":1580,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":548,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/blockManipulation.ts","size":5664,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts","size":962,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":837,"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":1104,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/FilePanel/FilePanelPlugin.ts","size":3584,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":5062,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/LinkToolbarPlugin.ts","size":7365,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":17383,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/SuggestionPlugin.ts","size":7996,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":15855,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/copyExtension.ts","size":3195,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/acceptedMIMETypes.ts","size":91,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/handleFileInsertion.ts","size":3396,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/fileDropExtension.ts","size":884,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/pasteExtension.ts","size":1244,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":791,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":928,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":725,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1594,"chunks":["a1ee98a"]},{"name":"./src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","size":1086,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":18085,"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":4286,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":1062,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteSchema.ts","size":1044,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteTipTapEditor.ts","size":3447,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderPlugin.ts","size":2762,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4572,"chunks":["a1ee98a"]},{"name":"./src/style.css","size":0,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":27991,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts","size":700,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","size":6416,"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.15.
|
|
6
|
+
"version": "0.15.11",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"types",
|
|
@@ -119,5 +119,5 @@
|
|
|
119
119
|
"access": "public",
|
|
120
120
|
"registry": "https://registry.npmjs.org/"
|
|
121
121
|
},
|
|
122
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "7f99a35368217aaab0a8ab9aff2092f2ecfd4aaf"
|
|
123
123
|
}
|
|
@@ -39,17 +39,6 @@ const schema = BlockNoteSchema.create({
|
|
|
39
39
|
let editor: BlockNoteEditor<typeof schema.blockSchema>;
|
|
40
40
|
const div = document.createElement("div");
|
|
41
41
|
|
|
42
|
-
function waitForEditor() {
|
|
43
|
-
// wait for create event on editor,
|
|
44
|
-
// this is necessary because otherwise UniqueId.create hasn't been called yet, and
|
|
45
|
-
// blocks would have "null" as their id
|
|
46
|
-
return new Promise<void>((resolve) => {
|
|
47
|
-
editor._tiptapEditor.on("create", () => {
|
|
48
|
-
resolve();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
42
|
let singleBlock: PartialBlock<
|
|
54
43
|
typeof schema.blockSchema,
|
|
55
44
|
DefaultInlineContentSchema,
|
|
@@ -195,25 +184,19 @@ describe("Test strong typing", () => {
|
|
|
195
184
|
});
|
|
196
185
|
|
|
197
186
|
describe("Inserting Blocks with Different Placements", () => {
|
|
198
|
-
it("Insert before existing block",
|
|
199
|
-
await waitForEditor();
|
|
200
|
-
|
|
187
|
+
it("Insert before existing block", () => {
|
|
201
188
|
const output = insert("before");
|
|
202
189
|
|
|
203
190
|
expect(output).toMatchSnapshot();
|
|
204
191
|
});
|
|
205
192
|
|
|
206
|
-
it("Insert nested inside existing block",
|
|
207
|
-
await waitForEditor();
|
|
208
|
-
|
|
193
|
+
it("Insert nested inside existing block", () => {
|
|
209
194
|
const output = insert("nested");
|
|
210
195
|
|
|
211
196
|
expect(output).toMatchSnapshot();
|
|
212
197
|
});
|
|
213
198
|
|
|
214
|
-
it("Insert after existing block",
|
|
215
|
-
await waitForEditor();
|
|
216
|
-
|
|
199
|
+
it("Insert after existing block", () => {
|
|
217
200
|
const output = insert("after");
|
|
218
201
|
|
|
219
202
|
expect(output).toMatchSnapshot();
|
|
@@ -221,9 +204,7 @@ describe("Inserting Blocks with Different Placements", () => {
|
|
|
221
204
|
});
|
|
222
205
|
|
|
223
206
|
describe("Insert, Update, & Delete Blocks", () => {
|
|
224
|
-
it("Insert, update, & delete single block",
|
|
225
|
-
await waitForEditor();
|
|
226
|
-
|
|
207
|
+
it("Insert, update, & delete single block", () => {
|
|
227
208
|
const existingBlock = editor.document[0];
|
|
228
209
|
editor.insertBlocks([singleBlock], existingBlock);
|
|
229
210
|
|
|
@@ -263,9 +244,7 @@ describe("Insert, Update, & Delete Blocks", () => {
|
|
|
263
244
|
expect(editor.document).toMatchSnapshot();
|
|
264
245
|
});
|
|
265
246
|
|
|
266
|
-
it("Insert, update, & delete multiple blocks",
|
|
267
|
-
await waitForEditor();
|
|
268
|
-
|
|
247
|
+
it("Insert, update, & delete multiple blocks", () => {
|
|
269
248
|
const existingBlock = editor.document[0];
|
|
270
249
|
editor.insertBlocks(multipleBlocks, existingBlock);
|
|
271
250
|
|
|
@@ -286,9 +265,7 @@ describe("Insert, Update, & Delete Blocks", () => {
|
|
|
286
265
|
});
|
|
287
266
|
|
|
288
267
|
describe("Update Line Breaks", () => {
|
|
289
|
-
it("Update paragraph with line break",
|
|
290
|
-
await waitForEditor();
|
|
291
|
-
|
|
268
|
+
it("Update paragraph with line break", () => {
|
|
292
269
|
const existingBlock = editor.document[0];
|
|
293
270
|
editor.insertBlocks(blocksWithLineBreaks, existingBlock);
|
|
294
271
|
|
|
@@ -300,9 +277,7 @@ describe("Update Line Breaks", () => {
|
|
|
300
277
|
|
|
301
278
|
expect(editor.document).toMatchSnapshot();
|
|
302
279
|
});
|
|
303
|
-
it("Update custom block with line break",
|
|
304
|
-
await waitForEditor();
|
|
305
|
-
|
|
280
|
+
it("Update custom block with line break", () => {
|
|
306
281
|
const existingBlock = editor.document[0];
|
|
307
282
|
editor.insertBlocks(blocksWithLineBreaks, existingBlock);
|
|
308
283
|
|
|
@@ -41,9 +41,9 @@ import {
|
|
|
41
41
|
InlineContentSchema,
|
|
42
42
|
InlineContentSpecs,
|
|
43
43
|
PartialInlineContent,
|
|
44
|
-
Styles,
|
|
45
44
|
StyleSchema,
|
|
46
45
|
StyleSpecs,
|
|
46
|
+
Styles,
|
|
47
47
|
} from "../schema";
|
|
48
48
|
import { mergeCSSClasses } from "../util/browser";
|
|
49
49
|
import { NoInfer, UnreachableCaseError } from "../util/typescript";
|
|
@@ -463,7 +463,7 @@ export class BlockNoteEditor<
|
|
|
463
463
|
};
|
|
464
464
|
|
|
465
465
|
if (!this.headless) {
|
|
466
|
-
this._tiptapEditor =
|
|
466
|
+
this._tiptapEditor = BlockNoteTipTapEditor.create(
|
|
467
467
|
tiptapOptions,
|
|
468
468
|
this.schema.styleSchema
|
|
469
469
|
) as BlockNoteTipTapEditor & {
|
|
@@ -23,7 +23,32 @@ export type BlockNoteTipTapEditorOptions = Partial<
|
|
|
23
23
|
export class BlockNoteTipTapEditor extends TiptapEditor {
|
|
24
24
|
private _state: EditorState;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
public static create = (
|
|
27
|
+
options: BlockNoteTipTapEditorOptions,
|
|
28
|
+
styleSchema: StyleSchema
|
|
29
|
+
) => {
|
|
30
|
+
// because we separate the constructor from the creation of the view,
|
|
31
|
+
// we need to patch setTimeout to prevent this code from having any effect:
|
|
32
|
+
// https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117
|
|
33
|
+
const oldSetTimeout = globalThis?.window?.setTimeout;
|
|
34
|
+
if (typeof globalThis?.window?.setTimeout !== "undefined") {
|
|
35
|
+
globalThis.window.setTimeout = (() => {
|
|
36
|
+
return 0;
|
|
37
|
+
}) as any;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
return new BlockNoteTipTapEditor(options, styleSchema);
|
|
41
|
+
} finally {
|
|
42
|
+
if (oldSetTimeout) {
|
|
43
|
+
globalThis.window.setTimeout = oldSetTimeout;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
protected constructor(
|
|
49
|
+
options: BlockNoteTipTapEditorOptions,
|
|
50
|
+
styleSchema: StyleSchema
|
|
51
|
+
) {
|
|
27
52
|
// possible fix for next.js server side rendering
|
|
28
53
|
// const d = globalThis.document;
|
|
29
54
|
// const w = globalThis.window;
|
|
@@ -32,14 +57,10 @@ export class BlockNoteTipTapEditor extends TiptapEditor {
|
|
|
32
57
|
// createElement: () => {},
|
|
33
58
|
// };
|
|
34
59
|
// }
|
|
35
|
-
|
|
36
|
-
// globalThis.window = {
|
|
37
|
-
// setTimeout: () => {},
|
|
38
|
-
// };
|
|
39
|
-
// }
|
|
60
|
+
|
|
40
61
|
// options.injectCSS = false
|
|
41
|
-
super({ ...options, content: undefined });
|
|
42
62
|
|
|
63
|
+
super({ ...options, content: undefined });
|
|
43
64
|
// try {
|
|
44
65
|
// globalThis.window = w;
|
|
45
66
|
// } catch(e) {}
|
|
@@ -149,6 +170,12 @@ export class BlockNoteTipTapEditor extends TiptapEditor {
|
|
|
149
170
|
this.view.updateState(newState);
|
|
150
171
|
|
|
151
172
|
this.createNodeViews();
|
|
173
|
+
|
|
174
|
+
// emit the created event, call here manually because we blocked the default call in the constructor
|
|
175
|
+
// (https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117)
|
|
176
|
+
this.commands.focus(this.options.autofocus);
|
|
177
|
+
this.emit("create", { editor: this });
|
|
178
|
+
this.isInitialized = true;
|
|
152
179
|
});
|
|
153
180
|
}
|
|
154
181
|
|
|
@@ -107,6 +107,8 @@ export class TableHandlesView<
|
|
|
107
107
|
|
|
108
108
|
public menuFrozen = false;
|
|
109
109
|
|
|
110
|
+
public mouseState: "up" | "down" | "selecting" = "up";
|
|
111
|
+
|
|
110
112
|
public prevWasEditable: boolean | null = null;
|
|
111
113
|
|
|
112
114
|
constructor(
|
|
@@ -127,6 +129,8 @@ export class TableHandlesView<
|
|
|
127
129
|
};
|
|
128
130
|
|
|
129
131
|
pmView.dom.addEventListener("mousemove", this.mouseMoveHandler);
|
|
132
|
+
pmView.dom.addEventListener("mousedown", this.viewMousedownHandler);
|
|
133
|
+
pmView.dom.addEventListener("mouseup", this.viewMouseupHandler);
|
|
130
134
|
|
|
131
135
|
pmView.root.addEventListener(
|
|
132
136
|
"dragover",
|
|
@@ -140,11 +144,33 @@ export class TableHandlesView<
|
|
|
140
144
|
pmView.root.addEventListener("scroll", this.scrollHandler, true);
|
|
141
145
|
}
|
|
142
146
|
|
|
147
|
+
viewMousedownHandler = () => {
|
|
148
|
+
this.mouseState = "down";
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
viewMouseupHandler = (event: MouseEvent) => {
|
|
152
|
+
this.mouseState = "up";
|
|
153
|
+
this.mouseMoveHandler(event);
|
|
154
|
+
};
|
|
155
|
+
|
|
143
156
|
mouseMoveHandler = (event: MouseEvent) => {
|
|
144
157
|
if (this.menuFrozen) {
|
|
145
158
|
return;
|
|
146
159
|
}
|
|
147
160
|
|
|
161
|
+
if (this.mouseState === "down") {
|
|
162
|
+
this.mouseState = "selecting";
|
|
163
|
+
|
|
164
|
+
if (this.state?.show) {
|
|
165
|
+
this.state.show = false;
|
|
166
|
+
this.emitUpdate();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (this.mouseState === "selecting") {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
148
174
|
const target = domCellAround(event.target as HTMLElement);
|
|
149
175
|
|
|
150
176
|
if (!target || !this.editor.isEditable) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
1
2
|
import { TagParseRule } from "@tiptap/pm/model";
|
|
3
|
+
import { NodeView } from "@tiptap/pm/view";
|
|
2
4
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
3
5
|
import { InlineContentSchema } from "../inlineContent/types";
|
|
4
6
|
import { StyleSchema } from "../styles/types";
|
|
@@ -61,6 +63,23 @@ export type CustomBlockImplementation<
|
|
|
61
63
|
) => PartialBlockFromConfig<T, I, S>["props"] | undefined;
|
|
62
64
|
};
|
|
63
65
|
|
|
66
|
+
// Function that causes events within non-selectable blocks to be handled by the
|
|
67
|
+
// browser instead of the editor.
|
|
68
|
+
export function applyNonSelectableBlockFix(nodeView: NodeView, editor: Editor) {
|
|
69
|
+
nodeView.stopEvent = (event) => {
|
|
70
|
+
// Blurs the editor on mouse down as the block is non-selectable. This is
|
|
71
|
+
// mainly done to prevent UI elements like the formatting toolbar from being
|
|
72
|
+
// visible while content within a non-selectable block is selected.
|
|
73
|
+
if (event.type === "mousedown") {
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
editor.view.dom.blur();
|
|
76
|
+
}, 10);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return true;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
64
83
|
// Function that uses the 'parse' function of a blockConfig to create a
|
|
65
84
|
// TipTap node's `parseHTML` property. This is only used for parsing content
|
|
66
85
|
// from the clipboard.
|
|
@@ -125,7 +144,7 @@ export function createBlockSpec<
|
|
|
125
144
|
? "inline*"
|
|
126
145
|
: "") as T["content"] extends "inline" ? "inline*" : "",
|
|
127
146
|
group: "blockContent",
|
|
128
|
-
selectable: true,
|
|
147
|
+
selectable: blockConfig.isSelectable ?? true,
|
|
129
148
|
|
|
130
149
|
addAttributes() {
|
|
131
150
|
return propsToAttributes(blockConfig.propSchema);
|
|
@@ -163,13 +182,19 @@ export function createBlockSpec<
|
|
|
163
182
|
|
|
164
183
|
const output = blockImplementation.render(block as any, editor);
|
|
165
184
|
|
|
166
|
-
|
|
185
|
+
const nodeView: NodeView = wrapInBlockStructure(
|
|
167
186
|
output,
|
|
168
187
|
block.type,
|
|
169
188
|
block.props,
|
|
170
189
|
blockConfig.propSchema,
|
|
171
190
|
blockContentDOMAttributes
|
|
172
191
|
);
|
|
192
|
+
|
|
193
|
+
if (blockConfig.isSelectable === false) {
|
|
194
|
+
applyNonSelectableBlockFix(nodeView, this.editor);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return nodeView;
|
|
173
198
|
};
|
|
174
199
|
},
|
|
175
200
|
});
|
|
@@ -49,6 +49,7 @@ export type FileBlockConfig = {
|
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
51
|
content: "none";
|
|
52
|
+
isSelectable?: boolean;
|
|
52
53
|
isFileBlock: true;
|
|
53
54
|
fileBlockAccept?: string[];
|
|
54
55
|
};
|
|
@@ -60,6 +61,7 @@ export type BlockConfig =
|
|
|
60
61
|
type: string;
|
|
61
62
|
readonly propSchema: PropSchema;
|
|
62
63
|
content: "inline" | "none" | "table";
|
|
64
|
+
isSelectable?: boolean;
|
|
63
65
|
isFileBlock?: false;
|
|
64
66
|
}
|
|
65
67
|
| FileBlockConfig;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
inlineContentToNodes,
|
|
5
5
|
nodeToCustomInlineContent,
|
|
6
6
|
} from "../../api/nodeConversions/nodeConversions";
|
|
7
|
+
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
7
8
|
import { propsToAttributes } from "../blocks/internal";
|
|
8
9
|
import { Props } from "../propTypes";
|
|
9
10
|
import { StyleSchema } from "../styles/types";
|
|
@@ -34,13 +35,13 @@ export type CustomInlineContentImplementation<
|
|
|
34
35
|
inlineContent: InlineContentFromConfig<T, S>,
|
|
35
36
|
updateInlineContent: (
|
|
36
37
|
update: PartialCustomInlineContentFromConfig<T, S>
|
|
37
|
-
) => void
|
|
38
|
+
) => void,
|
|
38
39
|
/**
|
|
39
40
|
* The BlockNote editor instance
|
|
40
41
|
* This is typed generically. If you want an editor with your custom schema, you need to
|
|
41
42
|
* cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`
|
|
42
43
|
*/
|
|
43
|
-
|
|
44
|
+
editor: BlockNoteEditor<any, any, S>
|
|
44
45
|
// (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations
|
|
45
46
|
// or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics
|
|
46
47
|
) => {
|
|
@@ -109,7 +110,8 @@ export function createInlineContentSpec<
|
|
|
109
110
|
) as any as InlineContentFromConfig<T, S>, // TODO: fix cast
|
|
110
111
|
() => {
|
|
111
112
|
// No-op
|
|
112
|
-
}
|
|
113
|
+
},
|
|
114
|
+
editor
|
|
113
115
|
);
|
|
114
116
|
|
|
115
117
|
return addInlineContentAttributes(
|
|
@@ -148,7 +150,8 @@ export function createInlineContentSpec<
|
|
|
148
150
|
content
|
|
149
151
|
)
|
|
150
152
|
);
|
|
151
|
-
}
|
|
153
|
+
},
|
|
154
|
+
editor
|
|
152
155
|
);
|
|
153
156
|
|
|
154
157
|
return addInlineContentAttributes(
|
|
@@ -8,7 +8,7 @@ import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkTool
|
|
|
8
8
|
import { SideMenuProsemirrorPlugin } from "../extensions/SideMenu/SideMenuPlugin";
|
|
9
9
|
import { SuggestionMenuProseMirrorPlugin } from "../extensions/SuggestionMenu/SuggestionPlugin";
|
|
10
10
|
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin";
|
|
11
|
-
import { BlockIdentifier, BlockNoteDOMAttributes, BlockSchema, BlockSpecs, InlineContentSchema, InlineContentSpecs, PartialInlineContent,
|
|
11
|
+
import { BlockIdentifier, BlockNoteDOMAttributes, BlockSchema, BlockSpecs, InlineContentSchema, InlineContentSpecs, PartialInlineContent, StyleSchema, StyleSpecs, Styles } from "../schema";
|
|
12
12
|
import { NoInfer } from "../util/typescript";
|
|
13
13
|
import { TextCursorPosition } from "./cursorPositionTypes";
|
|
14
14
|
import { Selection } from "./selectionTypes";
|
|
@@ -12,7 +12,8 @@ export type BlockNoteTipTapEditorOptions = Partial<Omit<EditorOptions, "content"
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class BlockNoteTipTapEditor extends TiptapEditor {
|
|
14
14
|
private _state;
|
|
15
|
-
|
|
15
|
+
static create: (options: BlockNoteTipTapEditorOptions, styleSchema: StyleSchema) => BlockNoteTipTapEditor;
|
|
16
|
+
protected constructor(options: BlockNoteTipTapEditorOptions, styleSchema: StyleSchema);
|
|
16
17
|
get state(): EditorState;
|
|
17
18
|
dispatch(tr: Transaction): void;
|
|
18
19
|
/**
|
|
@@ -25,8 +25,11 @@ export declare class TableHandlesView<I extends InlineContentSchema, S extends S
|
|
|
25
25
|
tableId: string | undefined;
|
|
26
26
|
tablePos: number | undefined;
|
|
27
27
|
menuFrozen: boolean;
|
|
28
|
+
mouseState: "up" | "down" | "selecting";
|
|
28
29
|
prevWasEditable: boolean | null;
|
|
29
30
|
constructor(editor: BlockNoteEditor<BlockSchemaWithBlock<"table", DefaultBlockSchema["table"]>, I, S>, pmView: EditorView, emitUpdate: (state: TableHandlesState<I, S>) => void);
|
|
31
|
+
viewMousedownHandler: () => void;
|
|
32
|
+
viewMouseupHandler: (event: MouseEvent) => void;
|
|
30
33
|
mouseMoveHandler: (event: MouseEvent) => false | undefined;
|
|
31
34
|
dragOverHandler: (event: DragEvent) => void;
|
|
32
35
|
dropHandler: (event: DragEvent) => void;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
1
2
|
import { TagParseRule } from "@tiptap/pm/model";
|
|
3
|
+
import { NodeView } from "@tiptap/pm/view";
|
|
2
4
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
3
5
|
import { InlineContentSchema } from "../inlineContent/types";
|
|
4
6
|
import { StyleSchema } from "../styles/types";
|
|
@@ -28,6 +30,7 @@ export type CustomBlockImplementation<T extends CustomBlockConfig, I extends Inl
|
|
|
28
30
|
};
|
|
29
31
|
parse?: (el: HTMLElement) => PartialBlockFromConfig<T, I, S>["props"] | undefined;
|
|
30
32
|
};
|
|
33
|
+
export declare function applyNonSelectableBlockFix(nodeView: NodeView, editor: Editor): void;
|
|
31
34
|
export declare function getParseRules(config: BlockConfig, customParseFunction: CustomBlockImplementation<any, any, any>["parse"]): TagParseRule[];
|
|
32
35
|
export declare function createBlockSpec<T extends CustomBlockConfig, I extends InlineContentSchema, S extends StyleSchema>(blockConfig: T, blockImplementation: CustomBlockImplementation<T, I, S>): {
|
|
33
36
|
config: T;
|
|
@@ -28,6 +28,7 @@ export type FileBlockConfig = {
|
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
content: "none";
|
|
31
|
+
isSelectable?: boolean;
|
|
31
32
|
isFileBlock: true;
|
|
32
33
|
fileBlockAccept?: string[];
|
|
33
34
|
};
|
|
@@ -35,6 +36,7 @@ export type BlockConfig = {
|
|
|
35
36
|
type: string;
|
|
36
37
|
readonly propSchema: PropSchema;
|
|
37
38
|
content: "inline" | "none" | "table";
|
|
39
|
+
isSelectable?: boolean;
|
|
38
40
|
isFileBlock?: false;
|
|
39
41
|
} | FileBlockConfig;
|
|
40
42
|
export type TiptapBlockImplementation<T extends BlockConfig, B extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TagParseRule } from "@tiptap/pm/model";
|
|
2
|
+
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
2
3
|
import { StyleSchema } from "../styles/types";
|
|
3
4
|
import { CustomInlineContentConfig, InlineContentFromConfig, InlineContentSpec, PartialCustomInlineContentFromConfig } from "./types";
|
|
4
5
|
export type CustomInlineContentImplementation<T extends CustomInlineContentConfig, S extends StyleSchema> = {
|
|
@@ -6,13 +7,13 @@ export type CustomInlineContentImplementation<T extends CustomInlineContentConfi
|
|
|
6
7
|
/**
|
|
7
8
|
* The custom inline content to render
|
|
8
9
|
*/
|
|
9
|
-
inlineContent: InlineContentFromConfig<T, S>, updateInlineContent: (update: PartialCustomInlineContentFromConfig<T, S>) => void
|
|
10
|
+
inlineContent: InlineContentFromConfig<T, S>, updateInlineContent: (update: PartialCustomInlineContentFromConfig<T, S>) => void,
|
|
10
11
|
/**
|
|
11
12
|
* The BlockNote editor instance
|
|
12
13
|
* This is typed generically. If you want an editor with your custom schema, you need to
|
|
13
14
|
* cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`
|
|
14
15
|
*/
|
|
15
|
-
) => {
|
|
16
|
+
editor: BlockNoteEditor<any, any, S>) => {
|
|
16
17
|
dom: HTMLElement;
|
|
17
18
|
contentDOM?: HTMLElement;
|
|
18
19
|
};
|