Skip to content

POC: A babel plugin that converts Reactjs components into Editorjs block tools. #1842

@sahilmob

Description

@sahilmob
  1. Describe a problem.
    Editorjs custom blocks API is great for simple tools, however, when it comes to more complex tools, you have to deal with adding/removing/updating dom nodes, adding/removing event listeners manually, and so on.

  2. Describe the solution you'd like. Mockups are welcome.
    What if we could hand these tasks to a UI library like Reactjs that can manage the dom, with you worrying about attaching/detaching event listeners for example?

For that, I have created a POC for a babel plugin called babel-transform-editor-jsx-blocks
that will wrap Reactjs components with Editorjs's block class definition, mount and unmount the react component into the root of that block, and provide you with a way to get/set the block state.

for example:

import React from "react";

export const TITLE = "Image";
export const ICON =
  '<svg width="17" height="15" viewBox="0 0 336 276" xmlns="http://www.w3.org/2000/svg"><path d="M291 150V79c0-19-15-34-34-34H79c-19 0-34 15-34 34v42l67-44 81 72 56-29 42 30zm0 52l-43-30-56 30-81-67-66 39v23c0 19 15 34 34 34h178c17 0 31-13 34-29zM79 0h178c44 0 79 35 79 79v118c0 44-35 79-79 79H79c-44 0-79-35-79-79V79C0 35 35 0 79 0z"/></svg>';

const MyComponent = ({ editorContext, blockState, setBlockState }) => {
  // do what ever you want to do here with editorContext, blockState, setBlockState.
  return <div>My Tool</div>;
};

export default MyComponent;

The result after transpilation:

import { render, unmountComponentAtNode } from "react-dom";
import React from "react";

const MyComponent = (props) => {
  return /*#__PURE__*/ React.createElement("div", null, "My Tool");
};

export default class MyComponentBlock {
  root = null;
  blockState = null;
  editorContext = null;

  static get toolbox() {
    return {
      title: "Image",
      icon: '<svg width="17" height="15" viewBox="0 0 336 276" xmlns="http://www.w3.org/2000/svg"><path d="M291 150V79c0-19-15-34-34-34H79c-19 0-34 15-34 34v42l67-44 81 72 56-29 42 30zm0 52l-43-30-56 30-81-67-66 39v23c0 19 15 34 34 34h178c17 0 31-13 34-29zM79 0h178c44 0 79 35 79 79v118c0 44-35 79-79 79H79c-44 0-79-35-79-79V79C0 35 35 0 79 0z"/></svg>',
    };
  }

  constructor(editorContext) {
    this.editorContext = editorContext;
    this.root = document.createElement("div");
    this.setBlockState = this.setBlockState.bind(this);
  }

  setBlockState = (newState) => {
    this.blockState = newState;
  };
  render = () => {
    render(
      /*#__PURE__*/ React.createElement(MyComponent, {
        editorContext: this.editorContext,
        blockState: this.blockState,
        setBlockState: this.setBlockState,
      }),
      this.root
    );
    return this.root;
  };
  save = () => {
    return this.blockState;
  };
  destroy = () => {
    unmountComponentAtNode(this.root);
  };
}

I would love to hear everybody's thoughts about this POC, so I do know if it is worth developing further or not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions