diff --git a/src/components/ReactEditor.tsx b/src/components/ReactEditor.tsx index 57258e7..29f1aed 100644 --- a/src/components/ReactEditor.tsx +++ b/src/components/ReactEditor.tsx @@ -1,26 +1,139 @@ import { memo, useEffect, useRef } from "react"; import EditorJS from "@editorjs/editorjs"; -import type { OutputData } from "@editorjs/editorjs"; +import type { + BlockToolData, + OutputBlockData, + ToolConstructable, + OutputData, +} from "@editorjs/editorjs"; import { EDITOR_JS_TOOLS } from "@/utils/tools"; +// @ts-expect-error Undo is not a valid tool +import Undo from "editorjs-undo"; +// @ts-expect-error DragDrop is not a valid tool +import DragDrop from "editorjs-drag-drop"; + +type ColumnData = { + columnsData: OutputBlockData[]; +}; + +type ColumnConfig = { + tools: ToolConstructable[] | any; +}; + +class ColumnTool { + private data: ColumnData; + private wrapper: HTMLElement | undefined; + private tools: { [name: symbol]: any }; + private editors: EditorJS[]; + + constructor({ data, config }: { data?: ColumnData; config?: ColumnConfig }) { + this.data = data ?? { columnsData: [] }; + this.wrapper = undefined; + this.tools = config?.tools ?? EDITOR_JS_TOOLS; + this.editors = []; + } + + static get toolbox() { + return { + title: "Column", + icon: ``, + }; + } + + static get enableLineBreaks() { + return true; + } + + createColumn() { + const column = document.createElement("div"); + column.classList.add( + "flex", + "flex-col", + "w-1/2", + "border", + "border-gray-300", + "rounded-md" + ); + return column; + } + + render() { + console.log(this.tools); + if (!this.wrapper) this.wrapper = document.createElement("div"); + + const child = document.createElement("div"); + child.classList.add("flex", "flex-row", "w-full", "space-x-4"); + + const blocksData: BlockToolData[] = []; + + for (let i = 0; i < 2; i++) { + const column = this.createColumn(); + const editor = new EditorJS({ + holder: column, + tools: this.tools, + async onChange(api) { + const data = await api.saver.save(); + blocksData[i] = data.blocks; + }, + }); + child.appendChild(column); + this.editors.push(editor); + } + this.wrapper.appendChild(child); + + this.data.columnsData = blocksData; + + return this.wrapper; + } + + save() { + return { + blocksData: this.data.columnsData, + }; + } + + destroy() { + this.editors.forEach((editor) => editor.destroy()); + this.wrapper?.remove(); + } +} type Props = { data?: OutputData; onChange(val: OutputData): void; holder: string; + autofocus?: boolean; }; -const EditorBlock = ({ data, onChange, holder }: Props) => { +const EditorBlock = ({ data, onChange, holder, autofocus }: Props) => { const ref = useRef(); useEffect(() => { if (!ref.current) { const editor = new EditorJS({ holder: holder, - tools: EDITOR_JS_TOOLS, + tools: { + ...EDITOR_JS_TOOLS, + column: { + class: ColumnTool, + config: { + tools: EDITOR_JS_TOOLS, + }, + }, + }, data, + autofocus, + onReady: () => { + new Undo({ editor }); + new DragDrop(editor); + }, async onChange(api) { - const data = await api.saver.save(); - onChange(data); + try { + const data = await api.saver.save(); + onChange(data); + } catch (error) { + console.log("Saving failed: ", error); + } }, }); ref.current = editor; @@ -37,4 +150,3 @@ const EditorBlock = ({ data, onChange, holder }: Props) => { }; export default memo(EditorBlock); - diff --git a/src/pages/test/editor.tsx b/src/pages/test/editor.tsx index d0ac6b3..ebafa09 100644 --- a/src/pages/test/editor.tsx +++ b/src/pages/test/editor.tsx @@ -9,7 +9,7 @@ const ReactEditorJS = dynamic(() => import('@/components/ReactEditor'), { }) export default function Editor() { - const [data, setData] = useState() + const [data, setData] = useState({blocks: [], time: 0, version: ''}) const {mutate, isLoading, data: data2, isError} = api.pages.updatePage.useMutation(); if (data2) console.log(data2) @@ -34,7 +34,7 @@ export default function Editor() {

EditorJS with React

- +

Output

{JSON.stringify(data, null, 2)}
diff --git a/src/utils/tools.js b/src/utils/tools.js index dd7653f..8b5580d 100644 --- a/src/utils/tools.js +++ b/src/utils/tools.js @@ -4,10 +4,7 @@ import List from "@editorjs/list"; import SimpleImage from "@editorjs/simple-image"; import Table from "@editorjs/table"; import Button from "editorjs-button"; -import Undo from "editorjs-undo"; -import DragDrop from "editorjs-drag-drop"; import Color from "editorjs-text-color-plugin"; -import { ItalicInlineTool, StrongInlineTool, UnderlineInlineTool } from "editorjs-inline-tool"; export const EDITOR_JS_TOOLS = { paragraph: { @@ -22,10 +19,5 @@ export const EDITOR_JS_TOOLS = { image: SimpleImage, table: Table, button: Button, - undo: Undo, - dragDrop: DragDrop, - italic: ItalicInlineTool, - strong: StrongInlineTool, - underline: UnderlineInlineTool, color: Color, -} +};