DEV Community

Sagar Gurung
Sagar Gurung

Posted on

Integrate Draw.io and MathType with TinyMCE in NextJs Application

In this article, we will explore how to integrate the Draw.io and MathType with TinyMCE rich text editor for diagram creation, writing mathematical expressions within a React application. For ease, I have used mantine components library. You can check this out on mantine.dev. This integration allows users to create and embed diagrams directly into their content using a seamless workflow.

Setting Up the Project

First, ensure you have a React project set up. If not, you can create one using Create React App:

npx create-react-app tinymce-drawio-integration
cd tinymce-drawio-integration
Enter fullscreen mode Exit fullscreen mode

Installing Dependencies

Next, we need to install TinyMCE, Draw.io, and other necessary packages:

npm install @tinymce/tinymce-react react-drawio @mantine/hooks @mantine/core @wiris/mathtype-tinymce6
Enter fullscreen mode Exit fullscreen mode

Next, you'll need to create a new component for our integration. Let's name it Editor.tsx.

Creating Editor Component

In Editor.tsx, we will implement the TinyMCE editor and integrate the Draw.io diagram editor within a modal. Here’s the complete code:

import React, { FC, useRef, useState } from "react";
import { Editor as TinyMCEEditor } from "@tinymce/tinymce-react";
import { DrawIoEmbed, DrawIoEmbedRef, EventExport } from "react-drawio";
import { useDisclosure } from "@mantine/hooks";
import { Button, Modal } from "@mantine/core";

const Editor = () => {
  const [opened, { open, close }] = useDisclosure(false);
  const [editorContent, setEditorContent] = useState("");
  const drawioRef = useRef<DrawIoEmbedRef>(null);

  const exportData = () => {
    if (drawioRef.current) {
      drawioRef.current.exportDiagram({
        format: "xmlsvg",
      });
    }
  };

  const handleEditorChange = (content: string) => {
    setEditorContent(content);
  };

  const handleSaveDrawio = (data: EventExport) => {
    setEditorContent(
      (prevState) =>
        prevState + `<img src="${data.data}" alt="Drawio Diagram"/>`
    );
    close();
  };

  return (
    <div>
      <TinyMCEEditor
        id={id}
        apiKey="YOUR_TINYMCE_API_KEY"
        value={editorContent}
        init={{
          height: 500,
          draggable_modal: true,
          extended_valid_elements: "*[.*]",
          plugins: [
            "advlist",
            "autolink",
            "lists",
            "link",
            "image",
            "charmap",
            "preview",
            "anchor",
            "searchreplace",
            "visualblocks",
            "code",
            "fullscreen",
            "insertdatetime",
            "media",
            "table",
            "help",
            "wordcount",
            "tiny_mce_wiris",
          ],
          toolbar:
            "undo redo | formatselect | bold italic backcolor | \
            alignleft aligncenter alignright alignjustify | \
            bullist numlist outdent indent | removeformat | help | image | table | drawio | tiny_mce_wiris_formulaEditor | tiny_mce_wiris_formulaEditorChemistry",
          setup: (editor) => {
            editor.ui.registry.addButton("drawio", {
              text: "Draw",
              onAction: () => {
                open();
              },
            });
          },
          external_plugins: {
            tiny_mce_wiris: `http://localhost:3000/tinymce_plugins/mathtype/mathtype-tinymce6/plugin.min.js`,
          },
        }}
        onEditorChange={handleEditorChange}
      />
      <Modal
        opened={opened}
        onClose={close}
        size="80vw"
        withCloseButton={false}
      >
        <div className="h-[80vh] relative">
          <Button
            className="bg-accent absolute right-14 top-4"
            onClick={exportData}
            size="compact-xs"
          >
            Export
          </Button>
          <DrawIoEmbed
            ref={drawioRef}
            onExport={handleSaveDrawio}
            urlParameters={{
              ui: "kennedy",
              spin: true,
              noSaveBtn: true,
              libraries: true,
              saveAndExit: false,
              noExitBtn: true,
            }}
          />
        </div>
      </Modal>
    </div>
  );
};

export default Editor;
Enter fullscreen mode Exit fullscreen mode

Explanation

1.TinyMCE Editor: We configure the TinyMCE editor with various plugins and a custom toolbar. The setup function adds a custom button for opening the Draw.io modal.

2.Draw.io Integration: We use the react-drawio package to embed Draw.io. The DrawIoEmbed component is wrapped inside a Modal from @mantine/core.

3.State Management: The component maintains the editor content in the editorContent state. The useDisclosure hook from @mantine/hooks manages the modal's open and close state.

4.Export and Embed Diagram: When the user exports the diagram, it triggers the exportData function, which calls the exportDiagram method from the DrawIoEmbedRef. The resulting SVG data is then embedded into the TinyMCE editor content.

5.MathType Integration: Copy the mathType plugin installed in node_modules, paste it inside public folder and provide the path to plugin in editor external_plugins section.

external_plugins: {
tiny_mce_wiris:`http://localhost:3000/tinymce_plugins/mathtype/math 
 type-tinymce6/plugin.min.js`,
},
Enter fullscreen mode Exit fullscreen mode

Customizing the Integration
1.API Key: Replace "YOUR_TINYMCE_API_KEY" with your TinyMCE API key.
2.UI and Features: Adjust the urlParameters in the DrawIoEmbed component to customize the Draw.io editor interface.

Running the Application

After setting up the component, you can now use it within your application. Import and use MyComponent in your main application file:

import React from "react";
import ReactDOM from "react-dom";
import Editor from "./Editor";

const App = () => {
  return (
    <div>
      <h1>React TinyMCE and Draw.io Integration</h1>
      <Editor />
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
Enter fullscreen mode Exit fullscreen mode

Now, start your application:

npm start
Enter fullscreen mode Exit fullscreen mode

You should see the TinyMCE editor with a custom "Draw" button. Clicking this button will open the Draw.io editor in a modal, allowing you to create and embed diagrams seamlessly.

Conclusion

Integrating TinyMCE and Draw.io in a React application enhances the user experience by combining rich text editing with powerful diagram creation capabilities. This integration can be particularly useful for applications requiring detailed content creation, such as documentation tools, educational platforms, and collaborative workspaces.

Top comments (0)