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':