UNPKG

on-codemerge

Version:

A WYSIWYG editor for on-codemerge is a user-friendly interface that allows users to edit and view their code in real time, exactly as it will appear in the final product

235 lines (234 loc) 7.46 kB
/*! on-codemerge v1.3.1 @author Pavel Kuzmin @license MIT @homepage https://s00d.github.io/on-codemerge/ @repository git+https://github.com/s00d/on-codemerge.git Copyright (c) 2026 Pavel Kuzmin - Built on 2026-07-02T13:39:17.947Z */ var s = Object.defineProperty; var a = (n, t, e) => t in n ? s(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e; var c = (n, t, e) => a(n, typeof t != "symbol" ? t + "" : t, e); import r from "../../../icons/delete.svg.mjs"; import k from "../../../icons/duplicate.svg.mjs"; import h from "../../../icons/move.svg.mjs"; import l from "../../../icons/split-horizontal.svg.mjs"; import m from "../../../icons/split-vertical.svg.mjs"; import { ContextMenu as u } from "../../../core/ui/ContextMenu.mjs"; import { SplitBlockCommand as p } from "../commands/SplitBlockCommand.mjs"; import { MergeBlocksCommand as d } from "../commands/MergeBlocksCommand.mjs"; import { BlockCommand as B } from "../commands/BlockCommand.mjs"; import { DuplicateBlockCommand as v } from "../commands/DuplicateBlockCommand.mjs"; import { DeleteBlockCommand as b } from "../commands/DeleteBlockCommand.mjs"; class I { constructor(t) { c(this, "editor"); c(this, "contextMenu"); c(this, "activeBlock", null); this.editor = t, this.contextMenu = new u( t, [ { title: t.t("Insert"), icon: "➕", subMenu: [ { title: t.t("Text Block"), action: "insert-text", onClick: () => this.handleAction("insert-text") }, { title: t.t("Container Block"), action: "insert-container", onClick: () => this.handleAction("insert-container") }, { title: t.t("Split Container"), action: "insert-split", onClick: () => this.handleAction("insert-split") } ] }, { title: t.t("Split"), icon: l, subMenu: [ { title: t.t("Horizontally"), icon: l, action: "split-horizontal", onClick: () => this.handleAction("split-horizontal") }, { title: t.t("Vertically"), icon: m, action: "split-vertical", onClick: () => this.handleAction("split-vertical") } ] }, { title: t.t("Merge"), icon: "🔗", action: "merge", onClick: () => this.handleAction("merge") }, { type: "divider" }, { title: t.t("Move"), icon: h, subMenu: [ { title: t.t("Up"), action: "move-up", onClick: () => this.handleAction("move-up") }, { title: t.t("Down"), action: "move-down", onClick: () => this.handleAction("move-down") } ] }, { title: t.t("Duplicate"), icon: k, action: "duplicate", onClick: () => this.handleAction("duplicate") }, { type: "divider" }, { title: t.t("Settings"), icon: "🔧", subMenu: [ { title: t.t("Make Editable"), action: "make-editable", onClick: () => this.handleAction("make-editable") }, { title: t.t("Make Read-only"), action: "make-readonly", onClick: () => this.handleAction("make-readonly") } ] }, { title: t.t("Remove"), icon: r, action: "remove", className: "text-red-600", onClick: () => this.handleAction("remove") } ], { orientation: "vertical" } ); } handleAction(t) { if (this.activeBlock) { switch (t) { case "insert-text": this.insertBlock("text"); break; case "insert-container": this.insertBlock("container"); break; case "insert-split": this.insertBlock("split"); break; case "split-horizontal": this.splitBlock("horizontal"); break; case "split-vertical": this.splitBlock("vertical"); break; case "merge": this.mergeBlocks(); break; case "move-up": this.moveBlock("up"); break; case "move-down": this.moveBlock("down"); break; case "duplicate": this.duplicateBlock(); break; case "make-editable": this.setBlockEditable(!0); break; case "make-readonly": this.setBlockEditable(!1); break; case "remove": this.removeBlock(); break; } this.hide(); } } insertBlock(t) { new B(this.editor).execute({ type: t }); } splitBlock(t) { if (!this.activeBlock || !this.canSplit(this.activeBlock)) return; const e = new p(this.editor); e.setData({ direction: t, block: this.activeBlock }), e.execute(); } mergeBlocks() { if (!this.activeBlock) return; const t = this.getAdjacentBlocks(this.activeBlock); if (t.length < 2) return; const e = new d(this.editor); e.setData({ blocks: t }), e.execute(); } moveBlock(t) { var e, o; if (this.activeBlock) if (t === "up") { const i = this.activeBlock.previousElementSibling; i && i.classList.contains("editor-block") && ((e = i.parentNode) == null || e.insertBefore(this.activeBlock, i)); } else { const i = this.activeBlock.nextElementSibling; i && i.classList.contains("editor-block") && ((o = i.parentNode) == null || o.insertBefore(i, this.activeBlock)); } } duplicateBlock() { if (!this.activeBlock) return; const t = new v(this.editor); t.setData({ block: this.activeBlock }), t.execute(); } setBlockEditable(t) { if (!this.activeBlock) return; const e = this.activeBlock.querySelector(".block-content"); e && (e.contentEditable = t.toString()); } removeBlock() { if (!this.activeBlock) return; const t = new b(this.editor); t.setBlock(this.activeBlock), t.execute(); } canSplit(t) { return t.classList.contains("editor-block") && !t.classList.contains("split-container") && t.getAttribute("data-block-type") === "text"; } getAdjacentBlocks(t) { const e = []; e.push(t); let o = t.previousElementSibling; for (; o && o.classList.contains("editor-block") && o.getAttribute("data-block-type") === "text"; ) e.unshift(o), o = o.previousElementSibling; let i = t.nextElementSibling; for (; i && i.classList.contains("editor-block") && i.getAttribute("data-block-type") === "text"; ) e.push(i), i = i.nextElementSibling; return e; } show(t, e, o) { this.activeBlock = t, this.contextMenu.show(t, e, o); } hide() { this.contextMenu.hide(), this.activeBlock = null; } destroy() { this.contextMenu && typeof this.contextMenu.destroy == "function" && this.contextMenu.destroy(), this.editor = null, this.contextMenu = null, this.activeBlock = null; } } export { I as BlockContextMenu };