Diagram Block
In this example, we register the @blocknote/diagram-block block in a custom schema. The block renders diagrams from Mermaid source code, showing the rendered diagram in place of the source and revealing an editable source popup when selected - built from the same SourceBlockWithPreview component the math block uses, so the block itself is only a few dozen lines.
Try it out: Click a diagram to edit its Mermaid source!
Relevant Docs:
import { createHighlighter } from "@blocknote/code-block";import { BlockNoteSchema } from "@blocknote/core";import { filterSuggestionItems, insertOrUpdateBlockForSlashMenu,} from "@blocknote/core/extensions";import "@blocknote/core/fonts/inter.css";import { BlockNoteView } from "@blocknote/mantine";import "@blocknote/mantine/style.css";import { createReactDiagramBlockSpec } from "@blocknote/diagram-block";import { getDefaultReactSlashMenuItems, SuggestionMenuController, useCreateBlockNote,} from "@blocknote/react";import { TbSitemap } from "react-icons/tb";// Our schema with block specs, which contain the configs and implementations// for blocks that we want our editor to use.const schema = BlockNoteSchema.create().extend({ blockSpecs: { // Creates an instance of the Diagram block and adds it to the schema. // TODO: naing diagram: createReactDiagramBlockSpec(), },});// Slash menu item to insert a Diagram block.// TODO: extract?const insertDiagram = (editor: typeof schema.BlockNoteEditor) => ({ title: "Diagram", subtext: "Insert a diagram rendered from Mermaid source", onItemClick: () => insertOrUpdateBlockForSlashMenu(editor, { type: "diagram", content: "graph TD\n A[Start] --> B[Stop]", }), aliases: ["mermaid", "diagram", "flowchart", "chart", "graph"], group: "Advanced", icon: <TbSitemap />,});export default function App() { const editor = useCreateBlockNote({ // Configures the syntax highlighting extension to use Mermaid syntax // highlighting in the Diagram block's source popup. syntaxHighlighting: { createHighlighter, highlightBlock: (block) => block.type === "diagram" ? "mermaid" : block.props.language, }, schema, initialContent: [ { type: "paragraph", content: "Click a diagram to edit its Mermaid source:", }, { type: "diagram", content: `graph TD A[Write docs] --> B{Diagram needed?} B -->|Yes| C[Type /diagram] B -->|No| D[Keep writing] C --> D`, }, { type: "paragraph", content: "Press the '/' key to open the Slash Menu and add another", }, ], }); // Renders the editor instance using a React component. return ( <BlockNoteView editor={editor} slashMenu={false}> {/* Replaces the default Slash Menu. */} <SuggestionMenuController triggerCharacter={"/"} getItems={async (query) => { // Gets all default slash menu items. const defaultItems = getDefaultReactSlashMenuItems(editor); // Finds index of last item in "Advanced" group. const lastAdvancedIndex = defaultItems.findLastIndex( (item) => item.group === "Advanced", ); // Inserts the Diagram item at the end of the "Advanced" group. defaultItems.splice(lastAdvancedIndex + 1, 0, insertDiagram(editor)); // Returns filtered items based on the query. return filterSuggestionItems(defaultItems, query); }} /> </BlockNoteView> );}