From 5e450727e27257bf051a2117181d6ae52f76699c Mon Sep 17 00:00:00 2001 From: Tomoyuki Hata Date: Thu, 4 Feb 2021 02:20:33 +0900 Subject: [PATCH] feat: Support read only mode --- docs/index.html | 168 +++++++++++++++++---------------- src/LayoutBlockTool.ts | 8 ++ src/container.ts | 37 ++++---- src/item.ts | 30 +++--- src/itemContent/itemContent.ts | 66 +++++++------ 5 files changed, 164 insertions(+), 145 deletions(-) diff --git a/docs/index.html b/docs/index.html index c83eb72..d06ddb1 100644 --- a/docs/index.html +++ b/docs/index.html @@ -18,6 +18,11 @@
+
+ + read only mode +
+ @@ -66,95 +71,93 @@ const editorJSConfig = {}; - const editorJS = new EditorJS({ - data, - tools: { - layout: { - class: EditorJSLayout.LayoutBlockTool, - config: { - EditorJS, - editorJSConfig, - enableLayoutEditing: false, - enableLayoutSaving: true, - initialData: { - itemContent: { - 1: { - blocks: [], - }, - }, - layout: { - type: "container", - id: "", - className: "", - style: "border: 1px solid #000000; ", - children: [ - { - type: "item", - id: "", - className: "", - style: - "border: 1px solid #000000; display: inline-block; ", - itemContentId: "1", - }, - ], + const tools = { + layout: { + class: EditorJSLayout.LayoutBlockTool, + config: { + EditorJS, + editorJSConfig, + enableLayoutEditing: false, + enableLayoutSaving: true, + initialData: { + itemContent: { + 1: { + blocks: [], }, }, + layout: { + type: "container", + id: "", + className: "", + style: "border: 1px solid #000000; ", + children: [ + { + type: "item", + id: "", + className: "", + style: "border: 1px solid #000000; display: inline-block; ", + itemContentId: "1", + }, + ], + }, }, }, - twoColumns: { - class: EditorJSLayout.LayoutBlockTool, - config: { - EditorJS, - editorJSConfig, - enableLayoutEditing: false, - enableLayoutSaving: false, - initialData: { - itemContent: { - 1: { - blocks: [], - }, - 2: { - blocks: [], - }, + }, + twoColumns: { + class: EditorJSLayout.LayoutBlockTool, + config: { + EditorJS, + editorJSConfig, + enableLayoutEditing: false, + enableLayoutSaving: false, + initialData: { + itemContent: { + 1: { + blocks: [], }, - layout: { - type: "container", - id: "", - className: "", - style: - "border: 1px solid #000000; display: flex; justify-content: space-around; padding: 16px; ", - children: [ - { - type: "item", - id: "", - className: "", - style: "border: 1px solid #000000; padding: 8px; ", - itemContentId: "1", - }, - { - type: "item", - id: "", - className: "", - style: "border: 1px solid #000000; padding: 8px; ", - itemContentId: "2", - }, - ], + 2: { + blocks: [], }, }, + layout: { + type: "container", + id: "", + className: "", + style: + "border: 1px solid #000000; display: flex; justify-content: space-around; padding: 16px; ", + children: [ + { + type: "item", + id: "", + className: "", + style: "border: 1px solid #000000; padding: 8px; ", + itemContentId: "1", + }, + { + type: "item", + id: "", + className: "", + style: "border: 1px solid #000000; padding: 8px; ", + itemContentId: "2", + }, + ], + }, }, - shortcut: "CMD+2", - toolbox: { - icon: ` - - - - - `, - title: "2 columns", - }, + }, + shortcut: "CMD+2", + toolbox: { + icon: ` + + + + + `, + title: "2 columns", }, }, - }); + }; + + const editorJS = new EditorJS({ data, tools }); document.querySelector("#button").addEventListener("click", async () => { const outputData = await editorJS.save(); @@ -163,6 +166,13 @@ outputData ); }); + + new EditorJS({ + holder: "read-only-editorjs", + data, + readOnly: true, + tools, + }); diff --git a/src/LayoutBlockTool.ts b/src/LayoutBlockTool.ts index 733aaea..65a7d09 100644 --- a/src/LayoutBlockTool.ts +++ b/src/LayoutBlockTool.ts @@ -49,6 +49,10 @@ interface LayoutBlockToolDispatchData { } class LayoutBlockTool implements BlockTool { + static get isReadOnlySupported() { + return true; + } + static get shortcut() { return "CMD+L"; } @@ -68,6 +72,7 @@ class LayoutBlockTool implements BlockTool { } #config!: LayoutBlockToolConfig; + #readOnly: boolean; #wrapper: HTMLDivElement; #itemContent: LayoutBlockItemContentData; @@ -76,7 +81,9 @@ class LayoutBlockTool implements BlockTool { constructor({ config, data, + readOnly, }: BlockToolConstructorOptions) { + this.#readOnly = readOnly; this.#wrapper = document.createElement("div"); this.#itemContent = {}; @@ -152,6 +159,7 @@ class LayoutBlockTool implements BlockTool { dispatchData: this.#dispatchData, editorJSConfig: this.#config.editorJSConfig, itemContentData: this.#itemContent, + readOnly: this.#readOnly, }) ); } diff --git a/src/container.ts b/src/container.ts index 8635d2f..841d4e7 100644 --- a/src/container.ts +++ b/src/container.ts @@ -22,19 +22,23 @@ interface ValidatedLayoutBlockContainerData extends LayoutBlockContainerData { )[]; } -const renderContainer = ({ - EditorJS, - data, - dispatchData, - editorJSConfig, - itemContentData, -}: { +interface RenderContext { EditorJS: LayoutBlockToolConfig["EditorJS"]; - data: LayoutBlockContainerData; dispatchData: LayoutBlockToolDispatchData; editorJSConfig: LayoutBlockToolConfig["editorJSConfig"]; + readOnly: boolean; +} + +interface RenderContainerProps extends RenderContext { + data: LayoutBlockContainerData; itemContentData: LayoutBlockItemContentData; -}) => { +} + +const renderContainer = ({ + data, + itemContentData, + ...context +}: RenderContainerProps) => { const wrapper = document.createElement("div"); wrapper.id = data.id; @@ -47,10 +51,8 @@ const renderContainer = ({ switch (child.type) { case "container": { childElement = renderContainer({ - EditorJS, + ...context, data: child, - dispatchData, - editorJSConfig, itemContentData, }); @@ -59,10 +61,8 @@ const renderContainer = ({ case "item": { childElement = renderItem({ - EditorJS, + ...context, data: child, - dispatchData, - editorJSConfig, itemContentData, }); @@ -83,4 +83,9 @@ const renderContainer = ({ }; export { renderContainer }; -export type { LayoutBlockContainerData, ValidatedLayoutBlockContainerData }; +export type { + LayoutBlockContainerData, + RenderContainerProps, + RenderContext, + ValidatedLayoutBlockContainerData, +}; diff --git a/src/item.ts b/src/item.ts index 812d43b..cfa1290 100644 --- a/src/item.ts +++ b/src/item.ts @@ -1,7 +1,4 @@ -import type { - LayoutBlockToolConfig, - LayoutBlockToolDispatchData, -} from "./LayoutBlockTool"; +import type { RenderContext } from "./container"; import { renderItemContent } from "./itemContent"; import type { LayoutBlockItemContentData } from "./itemContent"; @@ -15,19 +12,12 @@ interface LayoutBlockItemData { interface ValidatedLayoutBlockItemData extends LayoutBlockItemData {} -const renderItem = ({ - EditorJS, - data, - dispatchData, - editorJSConfig, - itemContentData, -}: { - EditorJS: LayoutBlockToolConfig["EditorJS"]; +interface RenderItemProps extends RenderContext { data: LayoutBlockItemData; - dispatchData: LayoutBlockToolDispatchData; - editorJSConfig: LayoutBlockToolConfig["editorJSConfig"]; itemContentData: LayoutBlockItemContentData; -}) => { +} + +const renderItem = ({ data, itemContentData, ...context }: RenderItemProps) => { const wrapper = document.createElement("div"); wrapper.id = data.id; @@ -38,10 +28,8 @@ const renderItem = ({ wrapper.append( renderItemContent({ - EditorJS, + ...context, data: editorJSData, - dispatchData, - editorJSConfig, itemContentId: data.itemContentId, }) ); @@ -50,4 +38,8 @@ const renderItem = ({ }; export { renderItem }; -export type { LayoutBlockItemData, ValidatedLayoutBlockItemData }; +export type { + LayoutBlockItemData, + RenderItemProps, + ValidatedLayoutBlockItemData, +}; diff --git a/src/itemContent/itemContent.ts b/src/itemContent/itemContent.ts index 172b00d..176b8a4 100644 --- a/src/itemContent/itemContent.ts +++ b/src/itemContent/itemContent.ts @@ -1,9 +1,6 @@ import type { OutputData } from "@editorjs/editorjs"; import { v4 as uuidv4 } from "uuid"; -import type { - LayoutBlockToolConfig, - LayoutBlockToolDispatchData, -} from "../LayoutBlockTool"; +import type { RenderContext } from "../container"; import { createDialog } from "./createDialog"; interface LayoutBlockItemContentData { @@ -13,45 +10,48 @@ interface LayoutBlockItemContentData { interface ValidatedLayoutBlockItemContentData extends LayoutBlockItemContentData {} +interface RenderItemContentProps extends RenderContext { + data: OutputData; + itemContentId: string; +} + const renderItemContent = ({ EditorJS, data, dispatchData, editorJSConfig, itemContentId, -}: { - EditorJS: LayoutBlockToolConfig["EditorJS"]; - data: OutputData; - dispatchData: LayoutBlockToolDispatchData; - editorJSConfig: LayoutBlockToolConfig["editorJSConfig"]; - itemContentId: string; -}) => { + readOnly, +}: RenderItemContentProps) => { const editorJSHolderID = uuidv4(); const wrapper = document.createElement("div"); wrapper.id = editorJSHolderID; - wrapper.style.cursor = "pointer"; - wrapper.addEventListener("click", () => { - const dialog = createDialog({ - EditorJS, - data, - editorJSConfig, - onClose: async ({ editorJSData }) => - dispatchData(({ itemContent, layout }) => ({ - itemContent: { - ...itemContent, - [itemContentId]: { - blocks: editorJSData.blocks, + if (!readOnly) { + wrapper.style.cursor = "pointer"; + + wrapper.addEventListener("click", () => { + const dialog = createDialog({ + EditorJS, + data, + editorJSConfig, + onClose: async ({ editorJSData }) => + dispatchData(({ itemContent, layout }) => ({ + itemContent: { + ...itemContent, + [itemContentId]: { + blocks: editorJSData.blocks, + }, }, - }, - layout: layout, - })), - }); + layout: layout, + })), + }); - document.body.append(dialog); - dialog.showModal(); - }); + document.body.append(dialog); + dialog.showModal(); + }); + } new EditorJS({ ...editorJSConfig, @@ -65,4 +65,8 @@ const renderItemContent = ({ }; export { renderItemContent }; -export type { LayoutBlockItemContentData, ValidatedLayoutBlockItemContentData }; +export type { + LayoutBlockItemContentData, + RenderItemContentProps, + ValidatedLayoutBlockItemContentData, +};