diff --git a/docs/pages/docs/custom-schemas/custom-inline-content.mdx b/docs/pages/docs/custom-schemas/custom-inline-content.mdx
index 20f55490e..eeedcf0ae 100644
--- a/docs/pages/docs/custom-schemas/custom-inline-content.mdx
+++ b/docs/pages/docs/custom-schemas/custom-inline-content.mdx
@@ -47,6 +47,7 @@ type CustomInlineContentConfig = {
type: string;
content: "styled" | "none";
readonly propSchema: PropSchema;
+ draggable?: boolean;
};
```
@@ -84,6 +85,12 @@ type PropSchema<
_In the mentions demo, we add a `user` prop for the user that's being mentioned._
+**`draggable`**
+
+Specifies whether the inline content can be dragged within the editor. If set to `true`, the inline content will be draggable. Defaults to `false` if not specified.
+
+If this is true, you should add `data-drag-handle` to the DOM element that should function as the drag handle.
+
#### Inline Content Implementation (`ReactCustomInlineContentImplementation`)
The Inline Content Implementation defines how the inline content should be rendered to HTML.
diff --git a/examples/06-custom-schema/draggable-inline-content/.bnexample.json b/examples/06-custom-schema/draggable-inline-content/.bnexample.json
new file mode 100644
index 000000000..1f5f98054
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/.bnexample.json
@@ -0,0 +1,6 @@
+{
+ "playground": true,
+ "docs": false,
+ "author": "hectorzhuang",
+ "tags": []
+}
diff --git a/examples/06-custom-schema/draggable-inline-content/App.tsx b/examples/06-custom-schema/draggable-inline-content/App.tsx
new file mode 100644
index 000000000..7d597e3b6
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/App.tsx
@@ -0,0 +1,80 @@
+import { BlockNoteSchema, defaultInlineContentSpecs } from "@blocknote/core";
+import "@blocknote/core/fonts/inter.css";
+import {
+ createReactInlineContentSpec,
+ useCreateBlockNote,
+} from "@blocknote/react";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
+
+const draggableButton = createReactInlineContentSpec(
+ {
+ type: "draggableButton",
+ propSchema: {
+ title: {
+ default: "",
+ },
+ },
+ draggable: true,
+ content: "none"
+ },
+ {
+ render: (props) => {
+ return (
+
+ {props.inlineContent.props.title}
+
+ );
+ },
+ }
+);
+
+const schema = BlockNoteSchema.create({
+ inlineContentSpecs: {
+ draggableButton,
+ ...defaultInlineContentSpecs,
+ },
+});
+
+export default function ReactInlineContent() {
+ const editor = useCreateBlockNote({
+ schema,
+ initialContent: [
+ {
+ type: "paragraph",
+ content: [
+ "I enjoy working with ",
+ {
+ type: "draggableButton",
+ props: {
+ title: "Hector",
+ },
+ },
+ ],
+ },
+ {
+ type: "paragraph",
+ content: [
+ "I love ",
+ {
+ type: "draggableButton",
+ props: {
+ title: "BlockNote",
+ },
+ },
+ ],
+ },
+ ],
+ });
+
+ return ;
+}
diff --git a/examples/06-custom-schema/draggable-inline-content/README.md b/examples/06-custom-schema/draggable-inline-content/README.md
new file mode 100644
index 000000000..3a3d0e5ba
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/README.md
@@ -0,0 +1 @@
+# Draggable Inline Content
diff --git a/examples/06-custom-schema/draggable-inline-content/index.html b/examples/06-custom-schema/draggable-inline-content/index.html
new file mode 100644
index 000000000..76ee82ac6
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ Draggable Inline Content
+
+
+
+
+
+
+
diff --git a/examples/06-custom-schema/draggable-inline-content/main.tsx b/examples/06-custom-schema/draggable-inline-content/main.tsx
new file mode 100644
index 000000000..6284417d6
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/main.tsx
@@ -0,0 +1,11 @@
+// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
+import React from "react";
+import { createRoot } from "react-dom/client";
+import App from "./App.jsx";
+
+const root = createRoot(document.getElementById("root")!);
+root.render(
+
+
+
+);
diff --git a/examples/06-custom-schema/draggable-inline-content/package.json b/examples/06-custom-schema/draggable-inline-content/package.json
new file mode 100644
index 000000000..b177176f2
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@blocknote/example-custom-schema-draggable-inline-content",
+ "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
+ "private": true,
+ "version": "0.12.4",
+ "scripts": {
+ "start": "vite",
+ "dev": "vite",
+ "build:prod": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@blocknote/core": "latest",
+ "@blocknote/react": "latest",
+ "@blocknote/ariakit": "latest",
+ "@blocknote/mantine": "latest",
+ "@blocknote/shadcn": "latest",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0"
+ },
+ "devDependencies": {
+ "@types/react": "^19.1.0",
+ "@types/react-dom": "^19.1.0",
+ "@vitejs/plugin-react": "^4.3.1",
+ "vite": "^5.3.4"
+ }
+}
\ No newline at end of file
diff --git a/examples/06-custom-schema/draggable-inline-content/tsconfig.json b/examples/06-custom-schema/draggable-inline-content/tsconfig.json
new file mode 100644
index 000000000..dbe3e6f62
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/tsconfig.json
@@ -0,0 +1,36 @@
+{
+ "__comment": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": [
+ "DOM",
+ "DOM.Iterable",
+ "ESNext"
+ ],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "composite": true
+ },
+ "include": [
+ "."
+ ],
+ "__ADD_FOR_LOCAL_DEV_references": [
+ {
+ "path": "../../../packages/core/"
+ },
+ {
+ "path": "../../../packages/react/"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/examples/06-custom-schema/draggable-inline-content/vite.config.ts b/examples/06-custom-schema/draggable-inline-content/vite.config.ts
new file mode 100644
index 000000000..f62ab20bc
--- /dev/null
+++ b/examples/06-custom-schema/draggable-inline-content/vite.config.ts
@@ -0,0 +1,32 @@
+// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
+import react from "@vitejs/plugin-react";
+import * as fs from "fs";
+import * as path from "path";
+import { defineConfig } from "vite";
+// import eslintPlugin from "vite-plugin-eslint";
+// https://vitejs.dev/config/
+export default defineConfig((conf) => ({
+ plugins: [react()],
+ optimizeDeps: {},
+ build: {
+ sourcemap: true,
+ },
+ resolve: {
+ alias:
+ conf.command === "build" ||
+ !fs.existsSync(path.resolve(__dirname, "../../packages/core/src"))
+ ? {}
+ : ({
+ // Comment out the lines below to load a built version of blocknote
+ // or, keep as is to load live from sources with live reload working
+ "@blocknote/core": path.resolve(
+ __dirname,
+ "../../packages/core/src/"
+ ),
+ "@blocknote/react": path.resolve(
+ __dirname,
+ "../../packages/react/src/"
+ ),
+ } as any),
+ },
+}));
diff --git a/packages/core/src/schema/inlineContent/types.ts b/packages/core/src/schema/inlineContent/types.ts
index 6ec87055d..913d0d1ec 100644
--- a/packages/core/src/schema/inlineContent/types.ts
+++ b/packages/core/src/schema/inlineContent/types.ts
@@ -5,6 +5,7 @@ import { StyleSchema, Styles } from "../styles/types.js";
export type CustomInlineContentConfig = {
type: string;
content: "styled" | "none"; // | "plain"
+ draggable?: boolean;
readonly propSchema: PropSchema;
// content: "inline" | "none" | "table";
};
diff --git a/packages/react/src/schema/ReactInlineContentSpec.tsx b/packages/react/src/schema/ReactInlineContentSpec.tsx
index 863187755..c18c917fb 100644
--- a/packages/react/src/schema/ReactInlineContentSpec.tsx
+++ b/packages/react/src/schema/ReactInlineContentSpec.tsx
@@ -101,6 +101,7 @@ export function createReactInlineContentSpec<
group: "inline",
selectable: inlineContentConfig.content === "styled",
atom: inlineContentConfig.content === "none",
+ draggable: inlineContentConfig.draggable,
content: (inlineContentConfig.content === "styled"
? "inline*"
: "") as T["content"] extends "styled" ? "inline*" : "",
diff --git a/playground/src/examples.gen.tsx b/playground/src/examples.gen.tsx
index 30d5a2234..ba2b521e9 100644
--- a/playground/src/examples.gen.tsx
+++ b/playground/src/examples.gen.tsx
@@ -1194,6 +1194,22 @@
"slug": "custom-schema"
}
},
+ {
+ "projectSlug": "draggable-inline-content",
+ "fullSlug": "custom-schema/draggable-inline-content",
+ "pathFromRoot": "examples/06-custom-schema/draggable-inline-content",
+ "config": {
+ "playground": true,
+ "docs": false,
+ "author": "hectorzhuang",
+ "tags": []
+ },
+ "title": "Draggable Inline Content",
+ "group": {
+ "pathFromRoot": "examples/06-custom-schema",
+ "slug": "custom-schema"
+ }
+ },
{
"projectSlug": "react-custom-blocks",
"fullSlug": "custom-schema/react-custom-blocks",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5a7453c3f..d91255611 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2399,6 +2399,43 @@ importers:
specifier: ^5.3.4
version: 5.4.15(@types/node@22.14.1)(lightningcss@1.30.1)(terser@5.43.1)
+ examples/06-custom-schema/draggable-inline-content:
+ dependencies:
+ '@blocknote/ariakit':
+ specifier: latest
+ version: link:../../../packages/ariakit
+ '@blocknote/core':
+ specifier: latest
+ version: link:../../../packages/core
+ '@blocknote/mantine':
+ specifier: latest
+ version: link:../../../packages/mantine
+ '@blocknote/react':
+ specifier: latest
+ version: link:../../../packages/react
+ '@blocknote/shadcn':
+ specifier: latest
+ version: link:../../../packages/shadcn
+ react:
+ specifier: ^19.1.0
+ version: 19.1.0
+ react-dom:
+ specifier: ^19.1.0
+ version: 19.1.0(react@19.1.0)
+ devDependencies:
+ '@types/react':
+ specifier: ^19.1.0
+ version: 19.1.8
+ '@types/react-dom':
+ specifier: ^19.1.0
+ version: 19.1.6(@types/react@19.1.8)
+ '@vitejs/plugin-react':
+ specifier: ^4.3.1
+ version: 4.4.1(vite@5.4.15(@types/node@22.14.1)(lightningcss@1.30.1)(terser@5.43.1))
+ vite:
+ specifier: ^5.3.4
+ version: 5.4.15(@types/node@22.14.1)(lightningcss@1.30.1)(terser@5.43.1)
+
examples/06-custom-schema/react-custom-blocks:
dependencies:
'@blocknote/ariakit':