Skip to content

Commit

Permalink
fix: Multi-editor drag & drop (#1341)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
matthewlipski authored Jan 14, 2025
1 parent bf15c04 commit 82e068c
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 211 deletions.
342 changes: 169 additions & 173 deletions examples/01-basic/04-all-blocks/App.tsx
Original file line number Diff line number Diff line change
@@ -1,207 +1,203 @@
import {
BlockNoteEditorOptions,
BlockNoteSchema,
combineByGroup,
filterSuggestionItems,
locales,
} from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
import {
SuggestionMenuController,
getDefaultReactSlashMenuItems,
useCreateBlockNote,
} from "@blocknote/react";
import {
getMultiColumnSlashMenuItems,
multiColumnDropCursor,
locales as multiColumnLocales,
withMultiColumn,
} from "@blocknote/xl-multi-column";
import { useMemo } from "react";
export default function App() {
// Creates a new editor instance.
const editor = useCreateBlockNote({
schema: withMultiColumn(BlockNoteSchema.create()),
dropCursor: multiColumnDropCursor,
dictionary: {
...locales.en,
multi_column: multiColumnLocales.en,
},
initialContent: [
{
type: "paragraph",
content: "Welcome to this demo!",
},
{
type: "paragraph",
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Blocks:",
styles: { bold: true },
},
],
},
{
type: "paragraph",
content: "Paragraph",
},
{
type: "columnList",
children: [
{
type: "column",
props: {
width: 0.8,
},
children: [
{
type: "paragraph",
content: "Hello to the left!",
},
],
},
{
type: "column",
props: {
width: 1.2,
},
children: [
{
type: "paragraph",
content: "Hello to the right!",
},
],

const schema = withMultiColumn(BlockNoteSchema.create());
const options = {
schema: withMultiColumn(BlockNoteSchema.create()),
dropCursor: multiColumnDropCursor,
dictionary: {
...locales.en,
multi_column: multiColumnLocales.en,
},
initialContent: [
{
type: "paragraph",
content: "Welcome to this demo!",
},
{
type: "paragraph",
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Blocks:",
styles: { bold: true },
},
],
},
{
type: "paragraph",
content: "Paragraph",
},
{
type: "columnList",
children: [
{
type: "column",
props: {
width: 0.8,
},
],
},
{
type: "heading",
content: "Heading",
},
{
type: "bulletListItem",
content: "Bullet List Item",
},
{
type: "numberedListItem",
content: "Numbered List Item",
},
{
type: "checkListItem",
content: "Check List Item",
},
{
type: "codeBlock",
props: { language: "javascript" },
content: "console.log('Hello, world!');",
},
{
type: "table",
content: {
type: "tableContent",
rows: [
{
cells: ["Table Cell", "Table Cell", "Table Cell"],
},
children: [
{
cells: ["Table Cell", "Table Cell", "Table Cell"],
type: "paragraph",
content: "Hello to the left!",
},
],
},
{
type: "column",
props: {
width: 1.2,
},
children: [
{
cells: ["Table Cell", "Table Cell", "Table Cell"],
type: "paragraph",
content: "Hello to the right!",
},
],
},
},
{
type: "file",
},
{
type: "image",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
},
},
{
type: "video",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
},
},
{
type: "audio",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
},
},
{
type: "paragraph",
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Inline Content:",
styles: { bold: true },
},
],
},
{
type: "paragraph",
content: [
],
},
{
type: "heading",
content: "Heading",
},
{
type: "bulletListItem",
content: "Bullet List Item",
},
{
type: "numberedListItem",
content: "Numbered List Item",
},
{
type: "checkListItem",
content: "Check List Item",
},
{
type: "codeBlock",
props: { language: "javascript" },
content: "console.log('Hello, world!');",
},
{
type: "table",
content: {
type: "tableContent",
rows: [
{
type: "text",
text: "Styled Text",
styles: {
bold: true,
italic: true,
textColor: "red",
backgroundColor: "blue",
},
cells: ["Table Cell", "Table Cell", "Table Cell"],
},
{
type: "text",
text: " ",
styles: {},
cells: ["Table Cell", "Table Cell", "Table Cell"],
},
{
type: "link",
content: "Link",
href: "https://www.blocknotejs.org",
cells: ["Table Cell", "Table Cell", "Table Cell"],
},
],
},
{
type: "paragraph",
},
{
type: "file",
},
{
type: "image",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg",
},
},
{
type: "video",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm",
},
},
{
type: "audio",
props: {
url: "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
caption:
"From https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
},
],
});
},
{
type: "paragraph",
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Inline Content:",
styles: { bold: true },
},
],
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Styled Text",
styles: {
bold: true,
italic: true,
textColor: "red",
backgroundColor: "blue",
},
},
{
type: "text",
text: " ",
styles: {},
},
{
type: "link",
content: "Link",
href: "https://www.blocknotejs.org",
},
],
},
{
type: "paragraph",
},
],
// sideMenuDetection: "editor",
} satisfies Partial<
BlockNoteEditorOptions<
typeof schema.blockSchema,
typeof schema.inlineContentSchema,
typeof schema.styleSchema
>
>;

const slashMenuItems = useMemo(() => {
return combineByGroup(
getDefaultReactSlashMenuItems(editor),
getMultiColumnSlashMenuItems(editor)
);
}, [editor]);
export default function App() {
// Creates a new editor instance.
const editor1 = useCreateBlockNote(options);
const editor2 = useCreateBlockNote(options);

// Renders the editor instance using a React component.
return (
<BlockNoteView editor={editor} slashMenu={false}>
<SuggestionMenuController
triggerCharacter={"/"}
getItems={async (query) => filterSuggestionItems(slashMenuItems, query)}
/>
</BlockNoteView>
<div style={{ display: "flex", gap: "10px" }}>
<BlockNoteView editor={editor1} />
{/*<BlockNoteView editor={editor2} />*/}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +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>
Original file line number Diff line number Diff line change
@@ -0,0 +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>
Loading

0 comments on commit 82e068c

Please sign in to comment.