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/inline-content-draggable/.bnexample.json b/examples/06-custom-schema/inline-content-draggable/.bnexample.json new file mode 100644 index 000000000..1f5f98054 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/.bnexample.json @@ -0,0 +1,6 @@ +{ + "playground": true, + "docs": false, + "author": "hectorzhuang", + "tags": [] +} diff --git a/examples/06-custom-schema/inline-content-draggable/App.tsx b/examples/06-custom-schema/inline-content-draggable/App.tsx new file mode 100644 index 000000000..045aaa280 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/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/inline-content-draggable/README.md b/examples/06-custom-schema/inline-content-draggable/README.md new file mode 100644 index 000000000..0b2a37823 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/README.md @@ -0,0 +1 @@ +# Inline Content Draggable diff --git a/examples/06-custom-schema/inline-content-draggable/index.html b/examples/06-custom-schema/inline-content-draggable/index.html new file mode 100644 index 000000000..ce79fe670 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/index.html @@ -0,0 +1,14 @@ + + + + + + Draggable Inline Content + + +
+ + + diff --git a/examples/06-custom-schema/inline-content-draggable/main.tsx b/examples/06-custom-schema/inline-content-draggable/main.tsx new file mode 100644 index 000000000..f88b490fb --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/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"; + +const root = createRoot(document.getElementById("root")!); +root.render( + + + +); diff --git a/examples/06-custom-schema/inline-content-draggable/package.json b/examples/06-custom-schema/inline-content-draggable/package.json new file mode 100644 index 000000000..2e9823da2 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/package.json @@ -0,0 +1,37 @@ +{ + "name": "@blocknote/example-inline-content-draggable", + "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY", + "private": true, + "version": "0.12.4", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint . --max-warnings 0" + }, + "dependencies": { + "@blocknote/core": "latest", + "@blocknote/react": "latest", + "@blocknote/ariakit": "latest", + "@blocknote/mantine": "latest", + "@blocknote/shadcn": "latest", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.0.25", + "@types/react-dom": "^18.0.9", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^8.10.0", + "vite": "^5.3.4" + }, + "eslintConfig": { + "extends": [ + "../../../.eslintrc.js" + ] + }, + "eslintIgnore": [ + "dist" + ] +} diff --git a/examples/06-custom-schema/inline-content-draggable/tsconfig.json b/examples/06-custom-schema/inline-content-draggable/tsconfig.json new file mode 100644 index 000000000..1bd8ab3c5 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/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": "Node", + "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/inline-content-draggable/vite.config.ts b/examples/06-custom-schema/inline-content-draggable/vite.config.ts new file mode 100644 index 000000000..852465e28 --- /dev/null +++ b/examples/06-custom-schema/inline-content-draggable/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/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index efb6d5f3e..99198c7d3 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -286,6 +286,14 @@ export class SideMenuView< return; } + // if ( + // this.sideMenuDetection === "editor" || + // (event as any).synthetic || + // !event.dataTransfer?.types.includes("blocknote/html") + // ) { + // return; + // } + this.editor._tiptapEditor.commands.blur(); // Finds the BlockNote editor element that the drop event occurred in (if @@ -335,14 +343,6 @@ export class SideMenuView< } } - if ( - this.sideMenuDetection === "editor" || - (event as any).synthetic || - !event.dataTransfer?.types.includes("blocknote/html") - ) { - return; - } - const pos = this.pmView.posAtCoords({ left: event.clientX, top: event.clientY, 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 63d81c014..4c3cd5fd0 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 e136417a6..40e7bad57 100644 --- a/playground/src/examples.gen.tsx +++ b/playground/src/examples.gen.tsx @@ -1238,6 +1238,27 @@ "pathFromRoot": "examples/06-custom-schema", "slug": "custom-schema" } + }, + { + "projectSlug": "inline-content-draggable", + "fullSlug": "custom-schema/inline-content-draggable", + "pathFromRoot": "examples/06-custom-schema/inline-content-draggable", + "config": { + "playground": true, + "docs": true, + "author": "hectorchong", + "tags": [ + "Intermediate", + "Inline Content", + "Custom Schemas", + "Draggable" + ] + }, + "title": "Draggable Inline Content", + "group": { + "pathFromRoot": "examples/06-custom-schema", + "slug": "custom-schema" + } } ] },