Skip to content

Commit 82e068c

Browse files
fix: Multi-editor drag & drop (#1341)
* WIP * Fixed multi-editor drag and drop * WIP: Added side menu detection area flag * Small changes * Source blocks are now deleted correctly & fixed error sometimes being thrown after drag & drop * Removed logs * Implemented PR feedback * Updated test snapshot * Moved/refactored tests
1 parent bf15c04 commit 82e068c

File tree

14 files changed

+434
-211
lines changed

14 files changed

+434
-211
lines changed
Lines changed: 169 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,207 +1,203 @@
11
import {
2+
BlockNoteEditorOptions,
23
BlockNoteSchema,
3-
combineByGroup,
4-
filterSuggestionItems,
54
locales,
65
} from "@blocknote/core";
76
import "@blocknote/core/fonts/inter.css";
87
import { BlockNoteView } from "@blocknote/mantine";
98
import "@blocknote/mantine/style.css";
9+
import { useCreateBlockNote } from "@blocknote/react";
1010
import {
11-
SuggestionMenuController,
12-
getDefaultReactSlashMenuItems,
13-
useCreateBlockNote,
14-
} from "@blocknote/react";
15-
import {
16-
getMultiColumnSlashMenuItems,
1711
multiColumnDropCursor,
1812
locales as multiColumnLocales,
1913
withMultiColumn,
2014
} from "@blocknote/xl-multi-column";
21-
import { useMemo } from "react";
22-
export default function App() {
23-
// Creates a new editor instance.
24-
const editor = useCreateBlockNote({
25-
schema: withMultiColumn(BlockNoteSchema.create()),
26-
dropCursor: multiColumnDropCursor,
27-
dictionary: {
28-
...locales.en,
29-
multi_column: multiColumnLocales.en,
30-
},
31-
initialContent: [
32-
{
33-
type: "paragraph",
34-
content: "Welcome to this demo!",
35-
},
36-
{
37-
type: "paragraph",
38-
},
39-
{
40-
type: "paragraph",
41-
content: [
42-
{
43-
type: "text",
44-
text: "Blocks:",
45-
styles: { bold: true },
46-
},
47-
],
48-
},
49-
{
50-
type: "paragraph",
51-
content: "Paragraph",
52-
},
53-
{
54-
type: "columnList",
55-
children: [
56-
{
57-
type: "column",
58-
props: {
59-
width: 0.8,
60-
},
61-
children: [
62-
{
63-
type: "paragraph",
64-
content: "Hello to the left!",
65-
},
66-
],
67-
},
68-
{
69-
type: "column",
70-
props: {
71-
width: 1.2,
72-
},
73-
children: [
74-
{
75-
type: "paragraph",
76-
content: "Hello to the right!",
77-
},
78-
],
15+
16+
const schema = withMultiColumn(BlockNoteSchema.create());
17+
const options = {
18+
schema: withMultiColumn(BlockNoteSchema.create()),
19+
dropCursor: multiColumnDropCursor,
20+
dictionary: {
21+
...locales.en,
22+
multi_column: multiColumnLocales.en,
23+
},
24+
initialContent: [
25+
{
26+
type: "paragraph",
27+
content: "Welcome to this demo!",
28+
},
29+
{
30+
type: "paragraph",
31+
},
32+
{
33+
type: "paragraph",
34+
content: [
35+
{
36+
type: "text",
37+
text: "Blocks:",
38+
styles: { bold: true },
39+
},
40+
],
41+
},
42+
{
43+
type: "paragraph",
44+
content: "Paragraph",
45+
},
46+
{
47+
type: "columnList",
48+
children: [
49+
{
50+
type: "column",
51+
props: {
52+
width: 0.8,
7953
},
80-
],
81-
},
82-
{
83-
type: "heading",
84-
content: "Heading",
85-
},
86-
{
87-
type: "bulletListItem",
88-
content: "Bullet List Item",
89-
},
90-
{
91-
type: "numberedListItem",
92-
content: "Numbered List Item",
93-
},
94-
{
95-
type: "checkListItem",
96-
content: "Check List Item",
97-
},
98-
{
99-
type: "codeBlock",
100-
props: { language: "javascript" },
101-
content: "console.log('Hello, world!');",
102-
},
103-
{
104-
type: "table",
105-
content: {
106-
type: "tableContent",
107-
rows: [
108-
{
109-
cells: ["Table Cell", "Table Cell", "Table Cell"],
110-
},
54+
children: [
11155
{
112-
cells: ["Table Cell", "Table Cell", "Table Cell"],
56+
type: "paragraph",
57+
content: "Hello to the left!",
11358
},
59+
],
60+
},
61+
{
62+
type: "column",
63+
props: {
64+
width: 1.2,
65+
},
66+
children: [
11467
{
115-
cells: ["Table Cell", "Table Cell", "Table Cell"],
68+
type: "paragraph",
69+
content: "Hello to the right!",
11670
},
11771
],
11872
},
119-
},
120-
{
121-
type: "file",
122-
},
123-
{
124-
type: "image",
125-
props: {
126-
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
127-
caption:
128-
"From https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
129-
},
130-
},
131-
{
132-
type: "video",
133-
props: {
134-
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
135-
caption:
136-
"From https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
137-
},
138-
},
139-
{
140-
type: "audio",
141-
props: {
142-
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
143-
caption:
144-
"From https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
145-
},
146-
},
147-
{
148-
type: "paragraph",
149-
},
150-
{
151-
type: "paragraph",
152-
content: [
153-
{
154-
type: "text",
155-
text: "Inline Content:",
156-
styles: { bold: true },
157-
},
158-
],
159-
},
160-
{
161-
type: "paragraph",
162-
content: [
73+
],
74+
},
75+
{
76+
type: "heading",
77+
content: "Heading",
78+
},
79+
{
80+
type: "bulletListItem",
81+
content: "Bullet List Item",
82+
},
83+
{
84+
type: "numberedListItem",
85+
content: "Numbered List Item",
86+
},
87+
{
88+
type: "checkListItem",
89+
content: "Check List Item",
90+
},
91+
{
92+
type: "codeBlock",
93+
props: { language: "javascript" },
94+
content: "console.log('Hello, world!');",
95+
},
96+
{
97+
type: "table",
98+
content: {
99+
type: "tableContent",
100+
rows: [
163101
{
164-
type: "text",
165-
text: "Styled Text",
166-
styles: {
167-
bold: true,
168-
italic: true,
169-
textColor: "red",
170-
backgroundColor: "blue",
171-
},
102+
cells: ["Table Cell", "Table Cell", "Table Cell"],
172103
},
173104
{
174-
type: "text",
175-
text: " ",
176-
styles: {},
105+
cells: ["Table Cell", "Table Cell", "Table Cell"],
177106
},
178107
{
179-
type: "link",
180-
content: "Link",
181-
href: "https://www.blocknotejs.org",
108+
cells: ["Table Cell", "Table Cell", "Table Cell"],
182109
},
183110
],
184111
},
185-
{
186-
type: "paragraph",
112+
},
113+
{
114+
type: "file",
115+
},
116+
{
117+
type: "image",
118+
props: {
119+
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
120+
caption:
121+
"From https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
122+
},
123+
},
124+
{
125+
type: "video",
126+
props: {
127+
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
128+
caption:
129+
"From https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
130+
},
131+
},
132+
{
133+
type: "audio",
134+
props: {
135+
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
136+
caption:
137+
"From https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
187138
},
188-
],
189-
});
139+
},
140+
{
141+
type: "paragraph",
142+
},
143+
{
144+
type: "paragraph",
145+
content: [
146+
{
147+
type: "text",
148+
text: "Inline Content:",
149+
styles: { bold: true },
150+
},
151+
],
152+
},
153+
{
154+
type: "paragraph",
155+
content: [
156+
{
157+
type: "text",
158+
text: "Styled Text",
159+
styles: {
160+
bold: true,
161+
italic: true,
162+
textColor: "red",
163+
backgroundColor: "blue",
164+
},
165+
},
166+
{
167+
type: "text",
168+
text: " ",
169+
styles: {},
170+
},
171+
{
172+
type: "link",
173+
content: "Link",
174+
href: "https://www.blocknotejs.org",
175+
},
176+
],
177+
},
178+
{
179+
type: "paragraph",
180+
},
181+
],
182+
// sideMenuDetection: "editor",
183+
} satisfies Partial<
184+
BlockNoteEditorOptions<
185+
typeof schema.blockSchema,
186+
typeof schema.inlineContentSchema,
187+
typeof schema.styleSchema
188+
>
189+
>;
190190

191-
const slashMenuItems = useMemo(() => {
192-
return combineByGroup(
193-
getDefaultReactSlashMenuItems(editor),
194-
getMultiColumnSlashMenuItems(editor)
195-
);
196-
}, [editor]);
191+
export default function App() {
192+
// Creates a new editor instance.
193+
const editor1 = useCreateBlockNote(options);
194+
const editor2 = useCreateBlockNote(options);
197195

198196
// Renders the editor instance using a React component.
199197
return (
200-
<BlockNoteView editor={editor} slashMenu={false}>
201-
<SuggestionMenuController
202-
triggerCharacter={"/"}
203-
getItems={async (query) => filterSuggestionItems(slashMenuItems, query)}
204-
/>
205-
</BlockNoteView>
198+
<div style={{ display: "flex", gap: "10px" }}>
199+
<BlockNoteView editor={editor1} />
200+
{/*<BlockNoteView editor={editor2} />*/}
201+
</div>
206202
);
207203
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Paragraph</p><h1>Heading</h1><ol><li><p>Numbered List Item</p></li></ol><ul><li><p>Bullet List Item</p></li><li><input type="checkbox"><p class="bn-inline-content">Check List Item</p></li></ul><pre><code class="bn-inline-content language-javascript">console.log("Hello World");</code></pre><table><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr></table><p>Add image</p><p data-text-color="red"></p>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p data-text-color="red">Paragraph</p><h2 data-level="2">Heading</h2><ol start="2"><li><p data-start="2">Numbered List Item</p></li></ol><ul><li><p data-background-color="red">Bullet List Item</p></li><li><input type="checkbox" checked="" data-checked="true"><p class="bn-inline-content">Check List Item</p></li></ul><pre><code class="bn-inline-content language-typescript">console.log("Hello World");</code></pre><table><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr><tr><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td><td colspan="1" rowspan="1"><p>Table Cell</p></td></tr></table><figure data-name="1280px-Placeholder_view_vector.svg.png" data-url="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Placeholder_view_vector.svg/1280px-Placeholder_view_vector.svg.png" data-caption="Placeholder" data-preview-width="256"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Placeholder_view_vector.svg/1280px-Placeholder_view_vector.svg.png" alt="1280px-Placeholder_view_vector.svg.png" width="256"><figcaption>Placeholder</figcaption></figure><p></p>

0 commit comments

Comments
 (0)