-
-
Notifications
You must be signed in to change notification settings - Fork 698
refactor: unified drop cursor extension #2550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nperez0111
wants to merge
9
commits into
main
Choose a base branch
from
dnd-fixes
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,295
−555
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
d1b4f2f
docs: playground search
nperez0111 0e8ecc2
feat: clean up the drop cursor & multi column drop cursor
nperez0111 65e3864
chore: rm `prosemirror-dropcursor` package
nperez0111 6426b83
chore: minor fixes
nperez0111 b9aa388
Merge branch 'main' into dnd-fixes
nperez0111 e2f55e0
chore: update docs link
nperez0111 5e22ae5
build: fix install-playwright script
nperez0111 2872072
chore: change example.json
nperez0111 9f3f5cb
Merge branch 'main' into dnd-fixes
nperez0111 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "playground": true, | ||
| "docs": false, | ||
| "author": "nperez0111", | ||
| "tags": ["Intermediate", "UI Components", "Drag & Drop", "Customization"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # Drag & Drop Exclusion | ||
|
|
||
| This example demonstrates how to use the `DRAG_EXCLUSION_CLASSNAME` to create separate drag & drop areas that don't interfere with BlockNote's built-in block drag & drop functionality. | ||
|
|
||
| ## Features | ||
|
|
||
| - **Drag Exclusion**: Elements with the `bn-drag-exclude` classname are treated as separate drag & drop operations | ||
| - **Independent Drag Areas**: Create custom drag & drop functionality alongside BlockNote's editor | ||
| - **No Interference**: Custom drag operations won't trigger BlockNote's block reordering | ||
| - **Side-by-side Demo**: Shows the editor and custom drag area working independently | ||
|
|
||
| ## How It Works | ||
|
|
||
| By adding the `DRAG_EXCLUSION_CLASSNAME` (`bn-drag-exclude`) to an element, you tell BlockNote's drag & drop handlers to ignore all drag events within that element and its children. This allows you to implement your own custom drag & drop logic without conflicts. | ||
|
|
||
| The exclusion check works by traversing up the DOM tree from the drag event target, checking if any ancestor has the exclusion classname. If found, BlockNote's handlers return early, leaving your custom handlers in full control. | ||
|
|
||
| ## Code Highlights | ||
|
|
||
| ### Import the constant: | ||
|
|
||
| ```tsx | ||
| import { DRAG_EXCLUSION_CLASSNAME } from "@blocknote/core"; | ||
| ``` | ||
|
|
||
| ### Apply it to your custom drag area: | ||
|
|
||
| ```tsx | ||
| <div className={"drag-demo-section " + DRAG_EXCLUSION_CLASSNAME}> | ||
| {/* Your custom drag & drop UI */} | ||
| <div draggable onDragStart={handleDragStart} onDrop={handleDrop}> | ||
| Custom draggable items | ||
| </div> | ||
| </div> | ||
| ``` | ||
|
|
||
| ## Use Cases | ||
|
|
||
| - **Custom UI elements**: Add draggable components within or near the editor | ||
| - **File upload areas**: Create drag-and-drop file upload zones | ||
| - **Sortable lists**: Implement custom sortable lists alongside the editor | ||
| - **External integrations**: Integrate with third-party drag & drop libraries | ||
|
|
||
| **Relevant Docs:** | ||
|
|
||
| - [Side Menu (Drag Handle)](/docs/react/components/side-menu) | ||
| - [Editor Setup](/docs/getting-started/editor-setup) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <title>Drag & Drop Exclusion</title> | ||
| <script> | ||
| <!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY --> | ||
| </script> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script type="module" src="./main.tsx"></script> | ||
| </body> | ||
| </html> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY | ||
| import React from "react"; | ||
| import { createRoot } from "react-dom/client"; | ||
| import App from "./src/App.jsx"; | ||
|
|
||
| const root = createRoot(document.getElementById("root")!); | ||
| root.render( | ||
| <React.StrictMode> | ||
| <App /> | ||
| </React.StrictMode> | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| { | ||
| "name": "@blocknote/example-ui-components-drag-n-drop", | ||
| "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY", | ||
| "type": "module", | ||
| "private": true, | ||
| "version": "0.12.4", | ||
| "scripts": { | ||
| "start": "vite", | ||
| "dev": "vite", | ||
| "build:prod": "tsc && vite build", | ||
| "preview": "vite preview" | ||
| }, | ||
| "dependencies": { | ||
| "@blocknote/ariakit": "latest", | ||
| "@blocknote/core": "latest", | ||
| "@blocknote/mantine": "latest", | ||
| "@blocknote/react": "latest", | ||
| "@blocknote/shadcn": "latest", | ||
| "@mantine/core": "^8.3.11", | ||
| "@mantine/hooks": "^8.3.11", | ||
| "@mantine/utils": "^6.0.22", | ||
| "react": "^19.2.3", | ||
| "react-dom": "^19.2.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/react": "^19.2.3", | ||
| "@types/react-dom": "^19.2.3", | ||
| "@vitejs/plugin-react": "^4.7.0", | ||
| "vite": "^5.4.20" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| import "@blocknote/core/fonts/inter.css"; | ||
| import { BlockNoteView } from "@blocknote/mantine"; | ||
| import "@blocknote/mantine/style.css"; | ||
| import { useCreateBlockNote } from "@blocknote/react"; | ||
| import { useState } from "react"; | ||
| import "./styles.css"; | ||
|
|
||
| export default function App() { | ||
| // Creates a new editor instance. | ||
| const editor = useCreateBlockNote({ | ||
| initialContent: [ | ||
| { | ||
| type: "paragraph", | ||
| content: "Welcome to the Drag & Drop Exclusion demo!", | ||
| }, | ||
| { | ||
| type: "paragraph", | ||
| content: | ||
| "Try dragging the blocks in the editor - they will work as normal.", | ||
| }, | ||
| { | ||
| type: "paragraph", | ||
| content: | ||
| "Now try dragging the colored boxes on the right - they won't interfere with the editor's drag & drop!", | ||
| }, | ||
| ], | ||
| }); | ||
|
|
||
| const [draggedItems, setDraggedItems] = useState([ | ||
| { id: "1", color: "#FF6B6B", label: "Red Item" }, | ||
| { id: "2", color: "#4ECDC4", label: "Teal Item" }, | ||
| { id: "3", color: "#45B7D1", label: "Blue Item" }, | ||
| { id: "4", color: "#FFA07A", label: "Orange Item" }, | ||
| ]); | ||
|
|
||
| const [droppedItems, setDroppedItems] = useState<typeof draggedItems>([]); | ||
|
|
||
| const handleDragStart = ( | ||
| e: React.DragEvent, | ||
| item: (typeof draggedItems)[0], | ||
| ) => { | ||
| e.dataTransfer.effectAllowed = "move"; | ||
| e.dataTransfer.setData("custom-item", JSON.stringify(item)); | ||
| }; | ||
|
|
||
| const handleDragOver = (e: React.DragEvent) => { | ||
| e.preventDefault(); | ||
| e.dataTransfer.dropEffect = "move"; | ||
| }; | ||
|
|
||
| const handleDrop = (e: React.DragEvent) => { | ||
| e.preventDefault(); | ||
| const data = e.dataTransfer.getData("custom-item"); | ||
| if (data) { | ||
| const item = JSON.parse(data); | ||
| setDroppedItems((prev) => [...prev, item]); | ||
| setDraggedItems((prev) => prev.filter((i) => i.id !== item.id)); | ||
| } | ||
| }; | ||
|
|
||
| const handleReset = () => { | ||
| setDraggedItems([ | ||
| { id: "1", color: "#FF6B6B", label: "Red Item" }, | ||
| { id: "2", color: "#4ECDC4", label: "Teal Item" }, | ||
| { id: "3", color: "#45B7D1", label: "Blue Item" }, | ||
| { id: "4", color: "#FFA07A", label: "Orange Item" }, | ||
| ]); | ||
| setDroppedItems([]); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="app-container"> | ||
| <div className="editor-section"> | ||
| <h2>BlockNote Editor</h2> | ||
| <BlockNoteView editor={editor} /> | ||
| </div> | ||
|
|
||
| <div className={`drag-demo-section bn-drag-exclude`}> | ||
| <h2>Separate Drag & Drop Area</h2> | ||
| <p className="info-text"> | ||
| This area uses the <code>bn-drag-exclude</code> classname, so dragging | ||
| items here won't interfere with the editor. | ||
| </p> | ||
|
|
||
| <div className="drag-columns"> | ||
| <div className="drag-column"> | ||
| <h3>Draggable Items</h3> | ||
| <div className="items-container"> | ||
| {draggedItems.map((item) => ( | ||
| <div | ||
| key={item.id} | ||
| className="draggable-item" | ||
| draggable | ||
| onDragStart={(e) => handleDragStart(e, item)} | ||
| style={{ backgroundColor: item.color }} | ||
| > | ||
| {item.label} | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
|
|
||
| <div | ||
| className="drag-column drop-zone" | ||
| onDragOver={handleDragOver} | ||
| onDrop={handleDrop} | ||
| > | ||
| <h3>Drop Zone</h3> | ||
| <div className="items-container"> | ||
| {droppedItems.length === 0 ? ( | ||
| <p className="placeholder">Drop items here</p> | ||
| ) : ( | ||
| droppedItems.map((item) => ( | ||
| <div | ||
| key={item.id} | ||
| className="draggable-item" | ||
| style={{ backgroundColor: item.color }} | ||
| > | ||
| {item.label} | ||
| </div> | ||
| )) | ||
| )} | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <button className="reset-button" onClick={handleReset}> | ||
| Reset Items | ||
| </button> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.