@blocknote/core 0.36.1 → 0.38.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.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1689 -1715
- package/dist/blocknote.js.map +1 -1
- package/dist/{en-CvDoFvhc.js → en-Bq3Es3Np.js} +6 -12
- package/dist/en-Bq3Es3Np.js.map +1 -0
- package/dist/en-D3B48eJ7.cjs +2 -0
- package/dist/en-D3B48eJ7.cjs.map +1 -0
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +109 -229
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +7 -7
- package/src/api/clipboard/toClipboard/copyExtension.ts +0 -2
- package/src/api/exporters/html/externalHTMLExporter.ts +0 -1
- package/src/api/exporters/markdown/markdownExporter.ts +13 -22
- package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +2 -12
- package/src/api/parsers/html/parseHTML.ts +3 -2
- package/src/api/parsers/html/util/nestedLists.test.ts +8 -8
- package/src/api/parsers/markdown/parseMarkdown.ts +17 -14
- package/src/api/positionMapping.test.ts +155 -34
- package/src/api/positionMapping.ts +2 -2
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +0 -1
- package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +3 -2
- package/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts +1 -7
- package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +64 -17
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +0 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +2 -5
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -1
- package/src/editor/BlockNoteEditor.ts +17 -23
- package/src/editor/BlockNoteExtensions.ts +3 -0
- package/src/editor/editor.css +5 -0
- package/src/extensions/Comments/CommentsPlugin.ts +2 -0
- package/src/extensions/SideMenu/SideMenuPlugin.ts +0 -2
- package/src/i18n/locales/ar.ts +6 -12
- package/src/i18n/locales/de.ts +6 -12
- package/src/i18n/locales/en.ts +6 -12
- package/src/i18n/locales/es.ts +6 -12
- package/src/i18n/locales/fr.ts +6 -12
- package/src/i18n/locales/he.ts +6 -12
- package/src/i18n/locales/hr.ts +6 -12
- package/src/i18n/locales/is.ts +6 -12
- package/src/i18n/locales/it.ts +6 -12
- package/src/i18n/locales/ja.ts +6 -12
- package/src/i18n/locales/ko.ts +6 -12
- package/src/i18n/locales/nl.ts +6 -12
- package/src/i18n/locales/no.ts +6 -12
- package/src/i18n/locales/pl.ts +6 -12
- package/src/i18n/locales/pt.ts +6 -12
- package/src/i18n/locales/ru.ts +6 -12
- package/src/i18n/locales/sk.ts +6 -12
- package/src/i18n/locales/uk.ts +6 -12
- package/src/i18n/locales/vi.ts +6 -12
- package/src/i18n/locales/zh-tw.ts +6 -12
- package/src/i18n/locales/zh.ts +6 -12
- package/src/index.ts +0 -1
- package/types/src/api/exporters/markdown/markdownExporter.d.ts +1 -1
- package/types/src/api/parsers/html/parseHTML.d.ts +1 -1
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -2
- package/types/src/blocks/FileBlockContent/helpers/render/createAddFileButton.d.ts +1 -1
- package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +1 -1
- package/types/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.d.ts +1 -1
- package/types/src/editor/BlockNoteEditor.d.ts +6 -9
- package/types/src/editor/BlockNoteExtensions.d.ts +2 -0
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +3 -1
- package/types/src/i18n/locales/en.d.ts +1 -12
- package/types/src/i18n/locales/sk.d.ts +1 -12
- package/types/src/index.d.ts +0 -1
- package/dist/en-CvDoFvhc.js.map +0 -1
- package/dist/en-ub2yVBX0.cjs +0 -2
- package/dist/en-ub2yVBX0.cjs.map +0 -1
- package/src/util/esmDependencies.ts +0 -51
- package/types/src/util/esmDependencies.d.ts +0 -24
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
import * as Y from "yjs";
|
|
3
3
|
import { BlockNoteEditor } from "../editor/BlockNoteEditor.js";
|
|
4
4
|
import { trackPosition } from "./positionMapping.js";
|
|
5
5
|
|
|
6
6
|
describe("PositionStorage with local editor", () => {
|
|
7
|
-
let editor: BlockNoteEditor;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
editor = BlockNoteEditor.create();
|
|
11
|
-
editor.mount(document.createElement("div"));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
editor.mount(undefined);
|
|
16
|
-
editor._tiptapEditor.destroy();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
7
|
describe("mount and unmount", () => {
|
|
20
8
|
it("should register transaction handler on creation", () => {
|
|
9
|
+
const editor = BlockNoteEditor.create();
|
|
10
|
+
editor.mount(document.createElement("div"));
|
|
11
|
+
|
|
21
12
|
editor._tiptapEditor.on = vi.fn();
|
|
22
13
|
trackPosition(editor, 0);
|
|
23
14
|
|
|
@@ -25,24 +16,42 @@ describe("PositionStorage with local editor", () => {
|
|
|
25
16
|
"transaction",
|
|
26
17
|
expect.any(Function),
|
|
27
18
|
);
|
|
19
|
+
|
|
20
|
+
editor.mount(undefined);
|
|
21
|
+
editor._tiptapEditor.destroy();
|
|
28
22
|
});
|
|
29
23
|
});
|
|
30
24
|
|
|
31
25
|
describe("set and get positions", () => {
|
|
32
26
|
it("should store and retrieve positions without Y.js", () => {
|
|
27
|
+
const editor = BlockNoteEditor.create();
|
|
28
|
+
editor.mount(document.createElement("div"));
|
|
29
|
+
|
|
33
30
|
const getPos = trackPosition(editor, 10);
|
|
34
31
|
|
|
35
32
|
expect(getPos()).toBe(10);
|
|
33
|
+
|
|
34
|
+
editor.mount(undefined);
|
|
35
|
+
editor._tiptapEditor.destroy();
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it("should handle right side positions", () => {
|
|
39
|
+
const editor = BlockNoteEditor.create();
|
|
40
|
+
editor.mount(document.createElement("div"));
|
|
41
|
+
|
|
39
42
|
const getPos = trackPosition(editor, 10, "right");
|
|
40
43
|
|
|
41
44
|
expect(getPos()).toBe(10);
|
|
45
|
+
|
|
46
|
+
editor.mount(undefined);
|
|
47
|
+
editor._tiptapEditor.destroy();
|
|
42
48
|
});
|
|
43
49
|
});
|
|
44
50
|
|
|
45
51
|
it("should update mapping for local transactions before the position", () => {
|
|
52
|
+
const editor = BlockNoteEditor.create();
|
|
53
|
+
editor.mount(document.createElement("div"));
|
|
54
|
+
|
|
46
55
|
// Set initial content
|
|
47
56
|
editor.insertBlocks(
|
|
48
57
|
[
|
|
@@ -79,9 +88,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
79
88
|
|
|
80
89
|
// Position should be updated according to mapping
|
|
81
90
|
expect(getPos()).toBe(14);
|
|
91
|
+
|
|
92
|
+
editor.mount(undefined);
|
|
93
|
+
editor._tiptapEditor.destroy();
|
|
82
94
|
});
|
|
83
95
|
|
|
84
96
|
it("should not update mapping for local transactions after the position", () => {
|
|
97
|
+
const editor = BlockNoteEditor.create();
|
|
98
|
+
editor.mount(document.createElement("div"));
|
|
99
|
+
|
|
85
100
|
// Set initial content
|
|
86
101
|
editor.insertBlocks(
|
|
87
102
|
[
|
|
@@ -117,9 +132,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
117
132
|
|
|
118
133
|
// Position should not be updated
|
|
119
134
|
expect(getPos()).toBe(10);
|
|
135
|
+
|
|
136
|
+
editor.mount(undefined);
|
|
137
|
+
editor._tiptapEditor.destroy();
|
|
120
138
|
});
|
|
121
139
|
|
|
122
140
|
it("should track positions on each side", () => {
|
|
141
|
+
const editor = BlockNoteEditor.create();
|
|
142
|
+
editor.mount(document.createElement("div"));
|
|
143
|
+
|
|
123
144
|
editor.replaceBlocks(editor.document, [
|
|
124
145
|
{
|
|
125
146
|
type: "paragraph",
|
|
@@ -142,9 +163,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
142
163
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
143
164
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
144
165
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
166
|
+
|
|
167
|
+
editor.mount(undefined);
|
|
168
|
+
editor._tiptapEditor.destroy();
|
|
145
169
|
});
|
|
146
170
|
|
|
147
171
|
it("should handle multiple transactions", () => {
|
|
172
|
+
const editor = BlockNoteEditor.create();
|
|
173
|
+
editor.mount(document.createElement("div"));
|
|
174
|
+
|
|
148
175
|
editor.replaceBlocks(editor.document, [
|
|
149
176
|
{
|
|
150
177
|
type: "paragraph",
|
|
@@ -172,6 +199,9 @@ describe("PositionStorage with local editor", () => {
|
|
|
172
199
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
173
200
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
174
201
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
202
|
+
|
|
203
|
+
editor.mount(undefined);
|
|
204
|
+
editor._tiptapEditor.destroy();
|
|
175
205
|
});
|
|
176
206
|
});
|
|
177
207
|
|
|
@@ -202,16 +232,12 @@ describe("PositionStorage with remote editor", () => {
|
|
|
202
232
|
}
|
|
203
233
|
|
|
204
234
|
describe("remote editor", () => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
beforeEach(() => {
|
|
211
|
-
ydoc = new Y.Doc();
|
|
212
|
-
remoteYdoc = new Y.Doc();
|
|
235
|
+
it("should update the local position when collaborating", () => {
|
|
236
|
+
const ydoc = new Y.Doc();
|
|
237
|
+
const remoteYdoc = new Y.Doc();
|
|
238
|
+
|
|
213
239
|
// Create a mock editor
|
|
214
|
-
localEditor = BlockNoteEditor.create({
|
|
240
|
+
const localEditor = BlockNoteEditor.create({
|
|
215
241
|
collaboration: {
|
|
216
242
|
fragment: ydoc.getXmlFragment("doc"),
|
|
217
243
|
user: { color: "#ff0000", name: "Local User" },
|
|
@@ -221,7 +247,7 @@ describe("PositionStorage with remote editor", () => {
|
|
|
221
247
|
const div = document.createElement("div");
|
|
222
248
|
localEditor.mount(div);
|
|
223
249
|
|
|
224
|
-
remoteEditor = BlockNoteEditor.create({
|
|
250
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
225
251
|
collaboration: {
|
|
226
252
|
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
227
253
|
user: { color: "#ff0000", name: "Remote User" },
|
|
@@ -232,18 +258,7 @@ describe("PositionStorage with remote editor", () => {
|
|
|
232
258
|
const remoteDiv = document.createElement("div");
|
|
233
259
|
remoteEditor.mount(remoteDiv);
|
|
234
260
|
setupTwoWaySync(ydoc, remoteYdoc);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
afterEach(() => {
|
|
238
|
-
ydoc.destroy();
|
|
239
|
-
remoteYdoc.destroy();
|
|
240
|
-
localEditor.mount(undefined);
|
|
241
|
-
localEditor._tiptapEditor.destroy();
|
|
242
|
-
remoteEditor.mount(undefined);
|
|
243
|
-
remoteEditor._tiptapEditor.destroy();
|
|
244
|
-
});
|
|
245
261
|
|
|
246
|
-
it("should update the local position when collaborating", () => {
|
|
247
262
|
localEditor.replaceBlocks(localEditor.document, [
|
|
248
263
|
{
|
|
249
264
|
type: "paragraph",
|
|
@@ -271,9 +286,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
271
286
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
272
287
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
273
288
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
289
|
+
|
|
290
|
+
ydoc.destroy();
|
|
291
|
+
remoteYdoc.destroy();
|
|
292
|
+
localEditor.mount(undefined);
|
|
293
|
+
localEditor._tiptapEditor.destroy();
|
|
294
|
+
remoteEditor.mount(undefined);
|
|
295
|
+
remoteEditor._tiptapEditor.destroy();
|
|
274
296
|
});
|
|
275
297
|
|
|
276
298
|
it("should handle multiple transactions when collaborating", () => {
|
|
299
|
+
const ydoc = new Y.Doc();
|
|
300
|
+
const remoteYdoc = new Y.Doc();
|
|
301
|
+
|
|
302
|
+
// Create a mock editor
|
|
303
|
+
const localEditor = BlockNoteEditor.create({
|
|
304
|
+
collaboration: {
|
|
305
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
306
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
307
|
+
provider: undefined,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
const div = document.createElement("div");
|
|
311
|
+
localEditor.mount(div);
|
|
312
|
+
|
|
313
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
314
|
+
collaboration: {
|
|
315
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
316
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
317
|
+
provider: undefined,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const remoteDiv = document.createElement("div");
|
|
322
|
+
remoteEditor.mount(remoteDiv);
|
|
323
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
324
|
+
|
|
277
325
|
localEditor.replaceBlocks(localEditor.document, [
|
|
278
326
|
{
|
|
279
327
|
type: "paragraph",
|
|
@@ -305,9 +353,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
305
353
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
306
354
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
307
355
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
356
|
+
|
|
357
|
+
ydoc.destroy();
|
|
358
|
+
remoteYdoc.destroy();
|
|
359
|
+
localEditor.mount(undefined);
|
|
360
|
+
localEditor._tiptapEditor.destroy();
|
|
361
|
+
remoteEditor.mount(undefined);
|
|
362
|
+
remoteEditor._tiptapEditor.destroy();
|
|
308
363
|
});
|
|
309
364
|
|
|
310
365
|
it("should update the local position from a remote transaction", () => {
|
|
366
|
+
const ydoc = new Y.Doc();
|
|
367
|
+
const remoteYdoc = new Y.Doc();
|
|
368
|
+
|
|
369
|
+
// Create a mock editor
|
|
370
|
+
const localEditor = BlockNoteEditor.create({
|
|
371
|
+
collaboration: {
|
|
372
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
373
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
374
|
+
provider: undefined,
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
const div = document.createElement("div");
|
|
378
|
+
localEditor.mount(div);
|
|
379
|
+
|
|
380
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
381
|
+
collaboration: {
|
|
382
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
383
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
384
|
+
provider: undefined,
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const remoteDiv = document.createElement("div");
|
|
389
|
+
remoteEditor.mount(remoteDiv);
|
|
390
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
391
|
+
|
|
311
392
|
remoteEditor.replaceBlocks(remoteEditor.document, [
|
|
312
393
|
{
|
|
313
394
|
type: "paragraph",
|
|
@@ -335,9 +416,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
335
416
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
336
417
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
337
418
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
419
|
+
|
|
420
|
+
ydoc.destroy();
|
|
421
|
+
remoteYdoc.destroy();
|
|
422
|
+
localEditor.mount(undefined);
|
|
423
|
+
localEditor._tiptapEditor.destroy();
|
|
424
|
+
remoteEditor.mount(undefined);
|
|
425
|
+
remoteEditor._tiptapEditor.destroy();
|
|
338
426
|
});
|
|
339
427
|
|
|
340
428
|
it("should update the remote position from a remote transaction", () => {
|
|
429
|
+
const ydoc = new Y.Doc();
|
|
430
|
+
const remoteYdoc = new Y.Doc();
|
|
431
|
+
|
|
432
|
+
// Create a mock editor
|
|
433
|
+
const localEditor = BlockNoteEditor.create({
|
|
434
|
+
collaboration: {
|
|
435
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
436
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
437
|
+
provider: undefined,
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
const div = document.createElement("div");
|
|
441
|
+
localEditor.mount(div);
|
|
442
|
+
|
|
443
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
444
|
+
collaboration: {
|
|
445
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
446
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
447
|
+
provider: undefined,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
const remoteDiv = document.createElement("div");
|
|
452
|
+
remoteEditor.mount(remoteDiv);
|
|
453
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
454
|
+
|
|
341
455
|
remoteEditor.replaceBlocks(remoteEditor.document, [
|
|
342
456
|
{
|
|
343
457
|
type: "paragraph",
|
|
@@ -365,6 +479,13 @@ describe("PositionStorage with remote editor", () => {
|
|
|
365
479
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
366
480
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
367
481
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
482
|
+
|
|
483
|
+
ydoc.destroy();
|
|
484
|
+
remoteYdoc.destroy();
|
|
485
|
+
localEditor.mount(undefined);
|
|
486
|
+
localEditor._tiptapEditor.destroy();
|
|
487
|
+
remoteEditor.mount(undefined);
|
|
488
|
+
remoteEditor._tiptapEditor.destroy();
|
|
368
489
|
});
|
|
369
490
|
});
|
|
370
491
|
});
|
|
@@ -88,7 +88,7 @@ export function trackPosition(
|
|
|
88
88
|
|
|
89
89
|
const relativePosition = absolutePositionToRelativePosition(
|
|
90
90
|
// Track the position after the position if we are on the right side
|
|
91
|
-
position + (side === "right" ? 1 :
|
|
91
|
+
position + (side === "right" ? 1 : -1),
|
|
92
92
|
ySyncPluginState.binding.type,
|
|
93
93
|
ySyncPluginState.binding.mapping,
|
|
94
94
|
);
|
|
@@ -109,6 +109,6 @@ export function trackPosition(
|
|
|
109
109
|
throw new Error("Position not found, cannot track positions");
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
return pos + (side === "right" ? -1 :
|
|
112
|
+
return pos + (side === "right" ? -1 : 1);
|
|
113
113
|
};
|
|
114
114
|
}
|
|
@@ -4,7 +4,6 @@ import { BlockFromConfig, FileBlockConfig } from "../../../../schema/index.js";
|
|
|
4
4
|
export const createAddFileButton = (
|
|
5
5
|
block: BlockFromConfig<FileBlockConfig, any, any>,
|
|
6
6
|
editor: BlockNoteEditor<any, any, any>,
|
|
7
|
-
buttonText?: string,
|
|
8
7
|
buttonIcon?: HTMLElement,
|
|
9
8
|
) => {
|
|
10
9
|
const addFileButton = document.createElement("div");
|
|
@@ -23,7 +22,9 @@ export const createAddFileButton = (
|
|
|
23
22
|
const addFileButtonText = document.createElement("p");
|
|
24
23
|
addFileButtonText.className = "bn-add-file-button-text";
|
|
25
24
|
addFileButtonText.innerHTML =
|
|
26
|
-
|
|
25
|
+
block.type in editor.dictionary.file_blocks.add_button_text
|
|
26
|
+
? editor.dictionary.file_blocks.add_button_text[block.type]
|
|
27
|
+
: editor.dictionary.file_blocks.add_button_text["file"];
|
|
27
28
|
addFileButton.appendChild(addFileButtonText);
|
|
28
29
|
|
|
29
30
|
// Prevents focus from moving to the button.
|
|
@@ -15,7 +15,6 @@ export const createFileBlockWrapper = (
|
|
|
15
15
|
any
|
|
16
16
|
>,
|
|
17
17
|
element?: { dom: HTMLElement; destroy?: () => void },
|
|
18
|
-
buttonText?: string,
|
|
19
18
|
buttonIcon?: HTMLElement,
|
|
20
19
|
) => {
|
|
21
20
|
const wrapper = document.createElement("div");
|
|
@@ -24,12 +23,7 @@ export const createFileBlockWrapper = (
|
|
|
24
23
|
// Show the add file button if the file has not been uploaded yet. Change to
|
|
25
24
|
// show a loader if a file upload for the block begins.
|
|
26
25
|
if (block.props.url === "") {
|
|
27
|
-
const addFileButton = createAddFileButton(
|
|
28
|
-
block,
|
|
29
|
-
editor,
|
|
30
|
-
buttonText,
|
|
31
|
-
buttonIcon,
|
|
32
|
-
);
|
|
26
|
+
const addFileButton = createAddFileButton(block, editor, buttonIcon);
|
|
33
27
|
wrapper.appendChild(addFileButton.dom);
|
|
34
28
|
|
|
35
29
|
const destroyUploadStartHandler = editor.onUploadStart((blockId) => {
|
|
@@ -7,17 +7,16 @@ export const createResizableFileBlockWrapper = (
|
|
|
7
7
|
editor: BlockNoteEditor<any, any, any>,
|
|
8
8
|
element: { dom: HTMLElement; destroy?: () => void },
|
|
9
9
|
resizeHandlesContainerElement: HTMLElement,
|
|
10
|
-
|
|
11
|
-
buttonIcon: HTMLElement,
|
|
10
|
+
buttonIcon?: HTMLElement,
|
|
12
11
|
): { dom: HTMLElement; destroy: () => void } => {
|
|
13
12
|
const { dom, destroy } = createFileBlockWrapper(
|
|
14
13
|
block,
|
|
15
14
|
editor,
|
|
16
15
|
element,
|
|
17
|
-
buttonText,
|
|
18
16
|
buttonIcon,
|
|
19
17
|
);
|
|
20
18
|
const wrapper = dom;
|
|
19
|
+
wrapper.style.position = "relative";
|
|
21
20
|
if (block.props.url && block.props.showPreview) {
|
|
22
21
|
if (block.props.previewWidth) {
|
|
23
22
|
wrapper.style.width = `${block.props.previewWidth}px`;
|
|
@@ -33,6 +32,15 @@ export const createResizableFileBlockWrapper = (
|
|
|
33
32
|
rightResizeHandle.className = "bn-resize-handle";
|
|
34
33
|
rightResizeHandle.style.right = "4px";
|
|
35
34
|
|
|
35
|
+
// This element ensures `mousemove` and `mouseup` events are captured while
|
|
36
|
+
// resizing when the cursor is over the wrapper content. This is because
|
|
37
|
+
// embeds are treated as separate HTML documents, so if the content is an
|
|
38
|
+
// embed, the events will only fire within that document.
|
|
39
|
+
const eventCaptureElement = document.createElement("div");
|
|
40
|
+
eventCaptureElement.style.position = "absolute";
|
|
41
|
+
eventCaptureElement.style.height = "100%";
|
|
42
|
+
eventCaptureElement.style.width = "100%";
|
|
43
|
+
|
|
36
44
|
// Temporary parameters set when the user begins resizing the element, used to
|
|
37
45
|
// calculate the new width of the element.
|
|
38
46
|
let resizeParams:
|
|
@@ -46,7 +54,7 @@ export const createResizableFileBlockWrapper = (
|
|
|
46
54
|
|
|
47
55
|
// Updates the element width with an updated width depending on the cursor X
|
|
48
56
|
// offset from when the resize began, and which resize handle is being used.
|
|
49
|
-
const windowMouseMoveHandler = (event: MouseEvent) => {
|
|
57
|
+
const windowMouseMoveHandler = (event: MouseEvent | TouchEvent) => {
|
|
50
58
|
if (!resizeParams) {
|
|
51
59
|
if (
|
|
52
60
|
!editor.isEditable &&
|
|
@@ -62,27 +70,26 @@ export const createResizableFileBlockWrapper = (
|
|
|
62
70
|
|
|
63
71
|
let newWidth: number;
|
|
64
72
|
|
|
73
|
+
const clientX =
|
|
74
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
75
|
+
|
|
65
76
|
if (block.props.textAlignment === "center") {
|
|
66
77
|
if (resizeParams.handleUsed === "left") {
|
|
67
78
|
newWidth =
|
|
68
79
|
resizeParams.initialWidth +
|
|
69
|
-
(resizeParams.initialClientX -
|
|
80
|
+
(resizeParams.initialClientX - clientX) * 2;
|
|
70
81
|
} else {
|
|
71
82
|
newWidth =
|
|
72
83
|
resizeParams.initialWidth +
|
|
73
|
-
(
|
|
84
|
+
(clientX - resizeParams.initialClientX) * 2;
|
|
74
85
|
}
|
|
75
86
|
} else {
|
|
76
87
|
if (resizeParams.handleUsed === "left") {
|
|
77
88
|
newWidth =
|
|
78
|
-
resizeParams.initialWidth +
|
|
79
|
-
resizeParams.initialClientX -
|
|
80
|
-
event.clientX;
|
|
89
|
+
resizeParams.initialWidth + resizeParams.initialClientX - clientX;
|
|
81
90
|
} else {
|
|
82
91
|
newWidth =
|
|
83
|
-
resizeParams.initialWidth +
|
|
84
|
-
event.clientX -
|
|
85
|
-
resizeParams.initialClientX;
|
|
92
|
+
resizeParams.initialWidth + clientX - resizeParams.initialClientX;
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
|
|
@@ -99,7 +106,7 @@ export const createResizableFileBlockWrapper = (
|
|
|
99
106
|
};
|
|
100
107
|
// Stops mouse movements from resizing the element and updates the block's
|
|
101
108
|
// `width` prop to the new value.
|
|
102
|
-
const windowMouseUpHandler = (event: MouseEvent) => {
|
|
109
|
+
const windowMouseUpHandler = (event: MouseEvent | TouchEvent) => {
|
|
103
110
|
// Hides the drag handles if the cursor is no longer over the element.
|
|
104
111
|
if (
|
|
105
112
|
(!event.target ||
|
|
@@ -118,6 +125,10 @@ export const createResizableFileBlockWrapper = (
|
|
|
118
125
|
|
|
119
126
|
resizeParams = undefined;
|
|
120
127
|
|
|
128
|
+
if (wrapper.contains(eventCaptureElement)) {
|
|
129
|
+
wrapper.removeChild(eventCaptureElement);
|
|
130
|
+
}
|
|
131
|
+
|
|
121
132
|
editor.updateBlock(block, {
|
|
122
133
|
props: {
|
|
123
134
|
previewWidth: width,
|
|
@@ -158,54 +169,90 @@ export const createResizableFileBlockWrapper = (
|
|
|
158
169
|
|
|
159
170
|
// Sets the resize params, allowing the user to begin resizing the element by
|
|
160
171
|
// moving the cursor left or right.
|
|
161
|
-
const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {
|
|
172
|
+
const leftResizeHandleMouseDownHandler = (event: MouseEvent | TouchEvent) => {
|
|
162
173
|
event.preventDefault();
|
|
163
174
|
|
|
175
|
+
if (!wrapper.contains(eventCaptureElement)) {
|
|
176
|
+
wrapper.appendChild(eventCaptureElement);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const clientX =
|
|
180
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
181
|
+
|
|
164
182
|
resizeParams = {
|
|
165
183
|
handleUsed: "left",
|
|
166
184
|
initialWidth: wrapper.clientWidth,
|
|
167
|
-
initialClientX:
|
|
185
|
+
initialClientX: clientX,
|
|
168
186
|
};
|
|
169
187
|
};
|
|
170
|
-
const rightResizeHandleMouseDownHandler = (
|
|
188
|
+
const rightResizeHandleMouseDownHandler = (
|
|
189
|
+
event: MouseEvent | TouchEvent,
|
|
190
|
+
) => {
|
|
171
191
|
event.preventDefault();
|
|
172
192
|
|
|
193
|
+
if (!wrapper.contains(eventCaptureElement)) {
|
|
194
|
+
wrapper.appendChild(eventCaptureElement);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const clientX =
|
|
198
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
199
|
+
|
|
173
200
|
resizeParams = {
|
|
174
201
|
handleUsed: "right",
|
|
175
202
|
initialWidth: wrapper.clientWidth,
|
|
176
|
-
initialClientX:
|
|
203
|
+
initialClientX: clientX,
|
|
177
204
|
};
|
|
178
205
|
};
|
|
179
206
|
|
|
180
207
|
window.addEventListener("mousemove", windowMouseMoveHandler);
|
|
208
|
+
window.addEventListener("touchmove", windowMouseMoveHandler);
|
|
181
209
|
window.addEventListener("mouseup", windowMouseUpHandler);
|
|
210
|
+
window.addEventListener("touchend", windowMouseUpHandler);
|
|
182
211
|
wrapper.addEventListener("mouseenter", wrapperMouseEnterHandler);
|
|
183
212
|
wrapper.addEventListener("mouseleave", wrapperMouseLeaveHandler);
|
|
184
213
|
leftResizeHandle.addEventListener(
|
|
185
214
|
"mousedown",
|
|
186
215
|
leftResizeHandleMouseDownHandler,
|
|
187
216
|
);
|
|
217
|
+
leftResizeHandle.addEventListener(
|
|
218
|
+
"touchstart",
|
|
219
|
+
leftResizeHandleMouseDownHandler,
|
|
220
|
+
);
|
|
188
221
|
rightResizeHandle.addEventListener(
|
|
189
222
|
"mousedown",
|
|
190
223
|
rightResizeHandleMouseDownHandler,
|
|
191
224
|
);
|
|
225
|
+
rightResizeHandle.addEventListener(
|
|
226
|
+
"touchstart",
|
|
227
|
+
rightResizeHandleMouseDownHandler,
|
|
228
|
+
);
|
|
192
229
|
|
|
193
230
|
return {
|
|
194
231
|
dom: wrapper,
|
|
195
232
|
destroy: () => {
|
|
196
233
|
destroy?.();
|
|
197
234
|
window.removeEventListener("mousemove", windowMouseMoveHandler);
|
|
235
|
+
window.removeEventListener("touchmove", windowMouseMoveHandler);
|
|
198
236
|
window.removeEventListener("mouseup", windowMouseUpHandler);
|
|
237
|
+
window.removeEventListener("touchend", windowMouseUpHandler);
|
|
199
238
|
wrapper.removeEventListener("mouseenter", wrapperMouseEnterHandler);
|
|
200
239
|
wrapper.removeEventListener("mouseleave", wrapperMouseLeaveHandler);
|
|
201
240
|
leftResizeHandle.removeEventListener(
|
|
202
241
|
"mousedown",
|
|
203
242
|
leftResizeHandleMouseDownHandler,
|
|
204
243
|
);
|
|
244
|
+
leftResizeHandle.removeEventListener(
|
|
245
|
+
"touchstart",
|
|
246
|
+
leftResizeHandleMouseDownHandler,
|
|
247
|
+
);
|
|
205
248
|
rightResizeHandle.removeEventListener(
|
|
206
249
|
"mousedown",
|
|
207
250
|
rightResizeHandleMouseDownHandler,
|
|
208
251
|
);
|
|
252
|
+
rightResizeHandle.removeEventListener(
|
|
253
|
+
"touchstart",
|
|
254
|
+
rightResizeHandleMouseDownHandler,
|
|
255
|
+
);
|
|
209
256
|
},
|
|
210
257
|
};
|
|
211
258
|
};
|
|
@@ -170,11 +170,8 @@ const TableParagraph = createStronglyTypedTiptapNode({
|
|
|
170
170
|
];
|
|
171
171
|
},
|
|
172
172
|
|
|
173
|
-
renderHTML({
|
|
174
|
-
|
|
175
|
-
// correct cell height. Otherwise, the cell will have a height of zero +
|
|
176
|
-
// padding.
|
|
177
|
-
return ["p", HTMLAttributes, node.childCount ? 0 : ["br"]];
|
|
173
|
+
renderHTML({ HTMLAttributes }) {
|
|
174
|
+
return ["p", HTMLAttributes, 0];
|
|
178
175
|
},
|
|
179
176
|
});
|
|
180
177
|
|