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
198 lines (197 loc) • 7.77 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 N = Object.defineProperty;
var I = (p, t, e) => t in p ? N(p, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : p[t] = e;
var c = (p, t, e) => I(p, typeof t != "symbol" ? t + "" : t, e);
import S from "../../../icons/delete.svg.mjs";
import { createContainer as s, createH as D, createButton as f, createInputField as u } from "../../../utils/helpers.mjs";
class F {
constructor(t, e) {
c(this, "editor");
c(this, "container");
c(this, "series", []);
c(this, "onChange");
c(this, "section", []);
c(this, "nameInput", null);
this.editor = t, this.container = s("chart-data-editor"), this.onChange = e, this.initialize();
}
initialize() {
const t = s("space-y-4"), e = s("flex justify-between items-center"), n = D("h4", "text-sm font-medium text-gray-700", this.editor.t("Series Data")), r = f(this.editor.t("Add Series"), () => {
this.addSeries({
name: `Series ${this.series.length + 1}`,
color: this.getNextColor(),
data: []
});
});
r.className = "add-series-btn px-2 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600", e.appendChild(n), e.appendChild(r);
const d = s("series-container space-y-6");
t.appendChild(e), t.appendChild(d), this.container.appendChild(t), this.addInitialSeries();
}
addInitialSeries() {
const t = {
name: this.editor.t("Series 1"),
color: "#3b82f6",
data: [
{
label: this.editor.t("Jan"),
value: 10,
r: 5,
x: 1,
y: 1,
color: this.getNextColor()
},
{
label: this.editor.t("Feb"),
value: 20,
r: 10,
x: 2,
y: 2,
color: this.getNextColor()
},
{
label: this.editor.t("Mar"),
value: 15,
r: 7,
x: 3,
y: 3,
color: this.getNextColor()
}
]
};
this.addSeries(t);
}
getNextColor() {
const t = [
"#3b82f6",
"#ef4444",
"#10b981",
"#f59e0b",
"#6366f1",
"#ec4899",
"#8b5cf6",
"#14b8a6",
"#f97316",
"#06b6d4"
];
return t[this.series.length % t.length];
}
getElement() {
return this.container;
}
getData() {
return this.series;
}
addSeries(t) {
const e = this.container.querySelector(".series-container");
if (!e) return;
const n = this.createSeriesSection(t);
e.appendChild(n), this.section.push(n), this.updateData();
}
createSeriesSection(t) {
const e = s("series-section border rounded-lg p-4"), n = s("flex items-center justify-between mb-4"), r = s("flex items-center gap-3");
this.nameInput = u(
"text",
this.editor.t("Series name"),
t.name,
(g) => {
t.name = g;
}
), this.nameInput.className = "series-name px-2 py-1 border rounded text-sm";
const d = u(
"color",
this.editor.t("Color"),
t.color || "#3b82f6",
(g) => {
t.color = g;
}
);
d.className = "series-color w-8 h-8 rounded cursor-pointer";
const l = f("", () => {
e.remove(), this.updateData();
});
l.className = "delete-series-btn p-1 text-red-500 hover:text-red-700", l.innerHTML = S, r.appendChild(this.nameInput), r.appendChild(d), n.appendChild(r), n.appendChild(l);
const a = s("data-grid"), o = s(
"grid grid-cols-[0.9fr,60px,60px,60px,40px,60px] gap-2 pb-2 border-b"
), h = s(
"text-sm font-medium text-gray-600",
this.editor.t("Label")
), m = s(
"text-sm font-medium text-gray-600",
this.editor.t("Value")
), x = s("text-sm font-medium text-gray-600", this.editor.t("X")), b = s("text-sm font-medium text-gray-600", this.editor.t("Y")), y = s(
"text-sm font-medium text-gray-600",
this.editor.t("Color")
), C = s("text-sm font-medium text-gray-600");
o.appendChild(h), o.appendChild(m), o.appendChild(x), o.appendChild(b), o.appendChild(y), o.appendChild(C), a.appendChild(o);
const i = s("data-rows space-y-2 mt-2");
a.appendChild(i);
const v = f(this.editor.t("+ Add Data Point"), () => {
this.addDataPoint(e);
});
return v.className = "add-point-btn mt-2 px-2 py-1 text-sm text-blue-600 hover:text-blue-700", e.appendChild(n), e.appendChild(a), e.appendChild(v), this.populateSeriesData(i, t.data), e;
}
addDataPoint(t, e) {
var x, b, y, C;
const n = t.querySelector(".data-rows");
if (!n) return;
const r = s(
"grid grid-cols-[0.9fr,60px,60px,60px,40px,60px] gap-2 items-center"
), d = u("text", "label", (e == null ? void 0 : e.label) || "", (i) => {
e && (e.label = i);
});
d.className = "label-input px-2 py-1 border rounded text-sm";
const l = u("number", "value", (x = e == null ? void 0 : e.value) == null ? void 0 : x.toString(), (i) => {
e && (e.value = parseInt(i));
});
l.className = "value-input px-2 py-1 border rounded text-sm";
const a = u("number", "X", ((b = e == null ? void 0 : e.x) == null ? void 0 : b.toString()) || "", (i) => {
e && (e.x = parseInt(i));
});
a.className = "x-input px-2 py-1 border rounded text-sm";
const o = u("number", "Y", ((y = e == null ? void 0 : e.y) == null ? void 0 : y.toString()) || "", (i) => {
e && (e.y = parseInt(i));
});
o.className = "y-input px-2 py-1 border rounded text-sm";
const h = u("color", "Color", ((C = e == null ? void 0 : e.y) == null ? void 0 : C.toString()) || "", (i) => {
h.value = i;
});
h.className = "color-input px-2 py-1 border rounded text-sm";
const m = f("", () => {
r.remove(), this.updateData();
});
m.className = "delete-point-btn p-1 pl-2 text-red-500 hover:text-red-700", m.innerHTML = S, r.appendChild(d), r.appendChild(l), r.appendChild(a), r.appendChild(o), r.appendChild(h), r.appendChild(m), n.appendChild(r), this.updateData();
}
populateSeriesData(t, e) {
e.forEach((n) => {
var r;
this.addDataPoint((r = t.parentElement) == null ? void 0 : r.parentElement, n);
});
}
updateData() {
const t = this.section;
t && (this.series = Array.from(t).map((e) => {
const n = e.querySelector(".series-name").value, r = e.querySelector(".series-color").value, d = e.querySelectorAll(".data-rows > div"), l = Array.from(d).map((a) => ({
label: a.querySelector(".label-input").value + " (" + (parseFloat(a.querySelector(".value-input").value) || 0) + ")",
value: parseFloat(a.querySelector(".value-input").value) || 0,
r: parseFloat(a.querySelector(".value-input").value) || 0,
x: parseFloat(a.querySelector(".x-input").value) || 0,
y: parseFloat(a.querySelector(".y-input").value) || 0,
color: a.querySelector(".color-input").value || "#3b82f6"
})).filter((a) => a.label && !isNaN(a.value));
return { name: n, color: r, data: l };
}), this.onChange(this.series));
}
/**
* Уничтожение редактора
*/
destroy() {
const t = this.container.querySelector(".add-series-btn");
t == null || t.removeEventListener("click", () => {
}), this.section.forEach((e) => {
e.removeEventListener("input", () => {
}), e.remove();
}), this.section = [], this.container.parentElement && this.container.parentElement.removeChild(this.container), this.container = null, this.editor = null, this.series = [], this.onChange = null;
}
}
export {
F as MultiSeriesDataEditor
};