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
179 lines (178 loc) • 7.46 kB
JavaScript
/*! 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 w = Object.defineProperty;
var v = (l, e, t) => e in l ? w(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
var c = (l, e, t) => v(l, typeof e != "symbol" ? e + "" : e, t);
import { PopupManager as f } from "../../../core/ui/PopupManager.mjs";
import u from "../../../icons/desktop.svg.mjs";
import y from "../../../icons/mobile.svg.mjs";
import C from "../../../icons/responsive.svg.mjs";
import x from "../../../icons/tablet.svg.mjs";
import { createContainer as r, createSpan as p, createButton as k } from "../../../utils/helpers.mjs";
import { SetViewportCommand as V } from "../commands/SetViewportCommand.mjs";
class I {
constructor(e) {
c(this, "editor");
c(this, "popup");
c(this, "viewportChangeHandlers", []);
c(this, "activeViewport");
c(this, "viewports", []);
var o, n;
this.editor = e;
const i = this.editor.getPlugins().get("responsive");
this.activeViewport = ((n = (o = i == null ? void 0 : i.viewportManager) == null ? void 0 : o.getCurrentViewport) == null ? void 0 : n.call(o)) || "responsive", this.viewports = [
{
name: "mobile",
icon: y,
label: e.t("Mobile"),
size: "320px",
description: e.t("Smartphone view"),
hotkey: "Ctrl+1"
},
{
name: "tablet",
icon: x,
label: e.t("Tablet"),
size: "768px",
description: e.t("Tablet view"),
hotkey: "Ctrl+2"
},
{
name: "desktop",
icon: u,
label: e.t("Desktop"),
size: "1024px",
description: e.t("Standard desktop"),
hotkey: "Ctrl+3"
},
{
name: "largeDesktop",
icon: u,
label: e.t("Large Desktop"),
size: "1440px",
description: e.t("Large desktop view"),
hotkey: "Ctrl+4"
},
{
name: "ultraWide",
icon: u,
label: e.t("Ultra Wide"),
size: "1920px",
description: e.t("Ultra wide screen"),
hotkey: "Ctrl+5"
},
{
name: "responsive",
icon: C,
label: e.t("Responsive"),
size: "Fluid",
description: e.t("Fluid width"),
hotkey: "Ctrl+0"
}
], this.popup = new f(e, {
title: e.t("Responsive View"),
className: "responsive-menu",
closeOnClickOutside: !0,
items: [
{
type: "custom",
id: "responsive-content",
content: () => this.createContent()
}
]
}), this.setupHotkeys();
}
createContent() {
const e = r("p-6 space-y-6"), t = r("flex items-center justify-between"), i = p("text-lg font-semibold", this.editor.t("Select Viewport")), o = this.viewports.find((a) => a.name === this.activeViewport), n = p(
"text-sm text-gray-500",
`${o == null ? void 0 : o.label} (${o == null ? void 0 : o.size})`
);
t.appendChild(i), t.appendChild(n), e.appendChild(t);
const s = r("grid grid-cols-2 gap-4");
this.viewports.forEach((a) => {
const h = this.createViewportButton(a);
s.appendChild(h);
}), e.appendChild(s);
const d = this.createInfoPanel();
return e.appendChild(d), this.setupEventListeners(s), e;
}
createViewportButton(e) {
const t = e.name === this.activeViewport, i = k("", () => {
this.setActiveViewport(e.name), this.popup.hide();
});
i.className = `viewport-btn w-full p-4 border-2 rounded-lg transition-all duration-200 ${t ? "border-blue-500 bg-blue-50 shadow-md" : "border-gray-200 hover:border-blue-300 hover:shadow-sm"}`, i.dataset.viewport = e.name;
const o = r("flex flex-col items-center gap-3"), n = r("relative"), s = r("text-2xl");
s.innerHTML = e.icon;
const d = r(
`w-16 h-10 border-2 border-gray-300 rounded ${e.name === "responsive" ? "w-20" : "w-16"}`
);
d.style.background = "linear-gradient(45deg, #f0f0f0 25%, transparent 25%), linear-gradient(-45deg, #f0f0f0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f0f0f0 75%), linear-gradient(-45deg, transparent 75%, #f0f0f0 75%)", d.style.backgroundSize = "4px 4px", d.style.backgroundPosition = "0 0, 0 2px, 2px -2px, -2px 0px", n.appendChild(s), n.appendChild(d);
const a = r("text-center"), h = p("block text-sm font-medium text-gray-900", e.label), m = p("block text-xs text-gray-500 mt-1", e.size), g = p("block text-xs text-gray-400 mt-1", e.description), b = p("block text-xs text-blue-500 mt-1 font-mono", e.hotkey);
return a.appendChild(h), a.appendChild(m), a.appendChild(g), a.appendChild(b), o.appendChild(n), o.appendChild(a), i.appendChild(o), i;
}
createInfoPanel() {
const e = r("mt-6 p-4 bg-gray-50 rounded-lg border"), t = p("block text-sm font-medium text-gray-900 mb-2", this.editor.t("Tips")), i = [
this.editor.t("• Use hotkeys for quick switching"),
this.editor.t("• Responsive mode allows manual resizing"),
this.editor.t("• Viewport state is saved automatically"),
this.editor.t("• Tables adapt automatically to viewport size")
], o = r("space-y-1");
return i.forEach((n) => {
const s = p("block text-xs text-gray-600", n);
o.appendChild(s);
}), e.appendChild(t), e.appendChild(o), e;
}
setupEventListeners(e) {
e.querySelectorAll(".viewport-btn").forEach((t) => {
t.addEventListener("click", () => {
const i = t.dataset.viewport;
this.setActiveViewport(i), this.popup.hide();
});
}), this.editor.getDOMContext().addEventListener("keydown", (t) => {
var i;
t.key === "Escape" && ((i = this.popup) == null || i.hide());
});
}
setupHotkeys() {
this.editor.getDOMContext().addEventListener("keydown", (e) => {
if (e.ctrlKey && !e.shiftKey && !e.altKey) {
const t = e.key, i = {
1: "mobile",
2: "tablet",
3: "desktop",
4: "largeDesktop",
5: "ultraWide",
0: "responsive"
};
i[t] && (e.preventDefault(), this.setActiveViewport(i[t]));
}
});
}
setActiveViewport(e) {
this.activeViewport = e, this.notifyViewportChange(e);
const t = new V(this.editor);
t.setViewport(e), t.execute(), this.popup && this.editor.getDOMContext().querySelectorAll(".viewport-btn").forEach((o) => {
const n = o, s = n.dataset.viewport === e;
n.className = `viewport-btn w-full p-4 border-2 rounded-lg transition-all duration-200 ${s ? "border-blue-500 bg-blue-50 shadow-md" : "border-gray-200 hover:border-blue-300 hover:shadow-sm"}`;
});
}
show() {
var i, o;
const t = this.editor.getPlugins().get("responsive");
this.activeViewport = ((o = (i = t == null ? void 0 : t.viewportManager) == null ? void 0 : i.getCurrentViewport) == null ? void 0 : o.call(i)) || "responsive", this.popup.show();
}
onViewportChange(e) {
this.viewportChangeHandlers.push(e);
}
notifyViewportChange(e) {
this.viewportChangeHandlers.forEach((t) => t(e));
}
getActiveViewport() {
return this.activeViewport;
}
destroy() {
this.popup.destroy(), this.viewportChangeHandlers = [], this.viewports = [], this.editor = null, this.popup = null;
}
}
export {
I as ResponsiveMenu
};