Quick Start
Required Node.js v16 or later.
With TypeScript(recommended)
Install packages.
npm i @editorjs/editorjs @pdejs/core
npm i --save-dev typescript
Add tsconfig.json.
{
  "compilerOptions": {
    "target": "es2016",
    "lib": ["ESNext", "DOM", "DOM.Iterable"],
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "jsx": "react"
  }
}
Write your first plugin as shown below.
/* @jsx h */
import {
  h,
  useMount,
  useWatch,
  useState,
  PDJSX,
  createPlugin,
} from '@pdejs/core';
const Plugin = () => {
  const toolbox: PDJSX.ToolAttributes['static_get_toolbox'] = {
    title: 'Simple',
    icon: '⚔️',
  };
  const save: PDJSX.ToolAttributes['save'] = (blockContent) => {
    return blockContent.innerText;
  };
  const [inputValue, setInputValue] = useState('');
  const [submitValue, setSubmitValue] = useState('');
  const handleFormSubmit = (event: Event) => {
    event.preventDefault();
    setSubmitValue(inputValue);
  };
  const handleInputChange = (event: Event) => {
    if (event.target instanceof HTMLInputElement) {
      setInputValue(event.target.value);
    }
  };
  useMount(() => {
    console.log('[@pdejs/simple] is ready to work!');
  });
  useWatch(() => {
    console.log(`[@pdejs/simple] submitted : `, submitValue);
  }, [submitValue]);
  return (
    <tool save={save} static_get_toolbox={toolbox}>
      <div>
        <form onSubmit={handleFormSubmit}>
          <label>
            type something→
            <input onChange={handleInputChange} value={inputValue} />
          </label>
          <button>submit</button>
        </form>
        <div>
          <span>submitted: </span>
          <span>{submitValue}</span>
        </div>
      </div>
    </tool>
  );
};
export const Simple = createPlugin(<Plugin />);
Create files for completing to setup. We recommend using vite for hosting locally.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Example - Simple</title>
  </head>
  <body>
    <div id="canvas"></div>
    <button id="save">save</button>
    <script type="module" src="/main.ts"></script>
  </body>
</html>
/* @jsx h */
import { Simple } from './plugin';
import EditorJS from '@editorjs/editorjs';
import './style.css';
const canvasElm = document.querySelector<HTMLDivElement>('#canvas');
const saveElm = document.querySelector<HTMLButtonElement>('#save');
if (!canvasElm) {
  throw new Error('Could not find the element#canvas');
}
const editor = new EditorJS({
  holder: canvasElm,
  tools: {
    simple: {
      class: Simple,
    },
  },
  onReady: () => {
    console.log('Editor.js is ready to work!');
  },
  onChange: (_, event) => {
    console.log("Now I know that Editor's content changed!", event);
  },
  autofocus: true,
  placeholder: "Let's write an awesome story!",
});
saveElm?.addEventListener('click', () => {
  editor
    .save()
    .then((outputData) => {
      console.log('saved: ', outputData);
    })
    .catch((error) => {
      console.log('save failded: ', error);
    });
});
It works 🎉

See the source for more information.
With JavaScript
Install packages.
npm i @editorjs/editorjs @pdejs/core
npm i --save-dev @babel/core @babel/cli @babel/plugin-transform-react-jsx @babel/preset-env
Add .babelrc.
{
  "presets": [["@babel/preset-env"]],
  "plugins": ["@babel/plugin-transform-react-jsx"]
}
Other steps are almostly the same way of the With TypeScript.
If you do not want to use @jsx h
Modify compilerOptions.jsxFactory in tsconfig.json or add @babel/plugin-transform-react-jsx for modifying pragma as follows.
tsconfig.json (with tsc)
{
  "compilerOptions": {
    "jsxFactory": "h"
  }
}
.babelrc (with @babel-transform-react-jsx)
{
  "plugins": [["transform-react-jsx", { "pragma": "h" }]]
}