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
288 lines (287 loc) • 8.65 kB
JavaScript
var y = Object.defineProperty;
var C = (p, t, e) => t in p ? y(p, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : p[t] = e;
var d = (p, t, e) => C(p, typeof t != "symbol" ? t + "" : t, e);
/* empty css */
/* empty css */
import { createToolbarButton as I } from "../ToolbarPlugin/utils.mjs";
import { PopupManager as A } from "../../core/ui/PopupManager.mjs";
import { createContainer as u, createButton as h, createInputField as T } from "../../utils/helpers.mjs";
import B from "../../icons/style.svg.mjs";
import { AVAILABLE_STYLES as S } from "./constants.mjs";
class P {
constructor() {
d(this, "name", "block-style");
d(this, "editor", null);
d(this, "toolbarButton", null);
d(this, "popup", null);
d(this, "selectedElement", null);
}
initialize(t) {
this.editor = t, this.popup = new A(t, {
title: t.t("Block Style Editor"),
className: "block-style-editor",
closeOnClickOutside: !0,
items: this.createPopupItems(),
buttons: [
{
label: t.t("Apply"),
variant: "primary",
onClick: () => this.applyStyles()
},
{
label: t.t("Cancel"),
variant: "secondary",
onClick: () => {
var e;
return (e = this.popup) == null ? void 0 : e.hide();
}
}
]
}), this.addToolbarButton(), this.editor.on("selectionchange", () => this.handleSelectionChange());
}
addToolbarButton() {
var e;
const t = document.querySelector(".editor-toolbar");
t && (this.toolbarButton = I({
icon: B,
title: (e = this.editor) == null ? void 0 : e.t("Block Style"),
onClick: () => this.showPopup()
}), t.appendChild(this.toolbarButton));
}
handleSelectionChange() {
var i, o, n, l;
const t = window.getSelection();
if (!t || t.rangeCount === 0) return;
const s = t.getRangeAt(0).commonAncestorContainer.parentElement;
if (this.editor) {
if (s === ((i = this.editor) == null ? void 0 : i.getContainer())) {
this.selectedElement = null, (o = this.toolbarButton) == null || o.classList.remove("active");
return;
}
s && this.isBlockElement(s) ? (this.selectedElement = s, (n = this.toolbarButton) == null || n.classList.add("active")) : (this.selectedElement = null, (l = this.toolbarButton) == null || l.classList.remove("active"));
}
}
isBlockElement(t) {
return [
"DIV",
"P",
"H1",
"H2",
"H3",
"H4",
"H5",
"H6",
"SECTION",
"ARTICLE",
"HEADER",
"FOOTER",
"NAV",
"ASIDE",
"MAIN",
"FIGURE",
"FIGCAPTION",
"BLOCKQUOTE",
"UL",
"OL",
"LI",
"DL",
"DT",
"DD",
"PRE",
"HR",
"ADDRESS",
"TABLE",
"THEAD",
"TBODY",
"TFOOT",
"TR",
"TH",
"TD",
"CAPTION",
"FORM",
"FIELDSET",
"LEGEND",
"DETAILS",
"SUMMARY",
"MENU",
"DIALOG",
"IFRAME",
"CANVAS",
"VIDEO",
"AUDIO",
"PICTURE",
"SOURCE",
"TRACK",
"MAP",
"OBJECT",
"PARAM",
"EMBED",
"NOSCRIPT",
"PROGRESS",
"METER",
"TIME",
"MARK",
"RUBY",
"RT",
"RP",
"BDI",
"BDO",
"WBR",
"INS",
"DEL",
"CODE",
"KBD",
"SAMP",
"VAR",
"CITE",
"Q",
"ABBR",
"DFN",
"SMALL",
"STRONG",
"EM",
"I",
"B",
"U",
"S",
"STRIKE",
"SUB",
"SUP",
"SPAN",
"BR",
"IMG",
"A",
"BUTTON",
"INPUT",
"TEXTAREA",
"SELECT",
"OPTION",
"OPTGROUP",
"LABEL",
"OUTPUT",
"DATALIST",
"KEYGEN",
"ISINDEX",
"BASE",
"LINK",
"META",
"STYLE",
"SCRIPT",
"TITLE",
"HEAD",
"BODY",
"HTML"
].includes(t.tagName);
}
createPopupItems() {
return [
{
type: "custom",
id: "style-editor",
content: () => this.createStyleEditor()
},
{
type: "custom",
id: "class-editor",
content: () => this.createClassEditor()
}
];
}
createStyleEditor() {
var n, l, a;
const t = u("popup-item"), e = document.createElement("label");
e.textContent = ((n = this.editor) == null ? void 0 : n.t("Inline Styles")) || "Inline Styles", t.appendChild(e);
const s = u("style-list");
(((a = (l = this.selectedElement) == null ? void 0 : l.getAttribute("style")) == null ? void 0 : a.split(";")) || []).forEach((c) => {
if (c.trim()) {
const [r, m] = c.split(":").map((E) => E.trim());
if (r && m) {
const E = this.createStyleItem(r, m);
s.appendChild(E);
}
}
});
const o = h("Add Style", () => this.addStyle(s));
return o.className = "add-button", t.appendChild(s), t.appendChild(o), t;
}
createStyleItem(t, e) {
const s = u("style-item"), i = document.createElement("select");
i.className = "style-property-select", Object.keys(S).forEach((l) => {
const a = document.createElement("option");
a.value = l, a.textContent = l, a.selected = l === t, i.appendChild(a);
});
const o = document.createElement("select");
o.className = "style-value-select", i.addEventListener("change", () => {
this.updateValueSelect(o, i.value);
}), this.updateValueSelect(o, i.value, e);
const n = h("×", () => s.remove());
return n.className = "remove-button", s.appendChild(i), s.appendChild(o), s.appendChild(n), s;
}
/**
* Обновляет выпадающий список значений в зависимости от выбранного свойства.
*/
updateValueSelect(t, e, s = "") {
t.innerHTML = "", (S[e] || []).forEach((o) => {
const n = document.createElement("option");
n.value = o, n.textContent = o, n.selected = o === s, t.appendChild(n);
});
}
addStyle(t) {
const e = this.createStyleItem("", "");
t.appendChild(e);
}
createClassEditor() {
var n, l, a;
const t = u("popup-item"), e = document.createElement("label");
e.textContent = ((n = this.editor) == null ? void 0 : n.t("CSS Classes")) || "CSS Classes", t.appendChild(e);
const s = u("class-list");
(((a = (l = this.selectedElement) == null ? void 0 : l.getAttribute("class")) == null ? void 0 : a.split(" ")) || []).forEach((c) => {
if (c.trim()) {
const r = this.createClassItem(c);
s.appendChild(r);
}
});
const o = h("Add Class", () => this.addClass(s));
return o.className = "add-button", t.appendChild(s), t.appendChild(o), t;
}
createClassItem(t) {
const e = u("class-item"), s = T("text", "Enter class (e.g., my-class)", t);
s.className = "class-input";
const i = h("×", () => e.remove());
return i.className = "remove-button", e.appendChild(s), e.appendChild(i), e;
}
addClass(t) {
const e = this.createClassItem("");
t.appendChild(e);
}
showPopup() {
if (!this.selectedElement || !this.popup) return;
const t = document.createElement("div"), e = this.createStyleEditor(), s = this.createClassEditor();
t.appendChild(e), t.appendChild(s), this.popup.setContent(t), this.popup.show();
}
applyStyles() {
var s, i, o;
if (!this.selectedElement || !this.popup) return;
(s = this.editor) == null || s.ensureEditorFocus();
const t = (i = this.popup.getElement()) == null ? void 0 : i.querySelector(".style-list"), e = (o = this.popup.getElement()) == null ? void 0 : o.querySelector(".class-list");
if (t) {
const n = Array.from(t.querySelectorAll(".style-item")).map((l) => {
const a = l.querySelector(".style-property-select"), c = l.querySelector(".style-value-select"), r = a.value.trim(), m = c.value.trim();
return r && m ? `${r}: ${m}` : "";
}).filter((l) => l).join("; ");
this.selectedElement.setAttribute("style", n);
}
if (e) {
const n = Array.from(e.querySelectorAll(".class-input")).map((l) => l.value.trim()).filter((l) => l).join(" ");
this.selectedElement.setAttribute("class", n);
}
this.popup.hide();
}
destroy() {
var t, e, s;
(t = this.toolbarButton) == null || t.remove(), this.toolbarButton = null, (e = this.editor) == null || e.off("selectionchange"), (s = this.popup) == null || s.destroy(), this.popup = null, this.editor = null;
}
}
export {
P as BlockStylePlugin
};