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

728 lines (727 loc) 30.4 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 A = Object.defineProperty; var B = (N, t, e) => t in N ? A(N, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : N[t] = e; var U = (N, t, e) => B(N, typeof t != "symbol" ? t + "" : t, e); import { createContainer as n, createButton as I, createLabel as x, createSelectField as R, createInputField as y, createCheckbox as F } from "../../../utils/helpers.mjs"; class V { constructor(t, e, o, s, d, a, p) { U(this, "editor"); U(this, "formManager"); U(this, "onUpdate"); U(this, "onRemove"); U(this, "onClone"); U(this, "onTypeChange"); U(this, "onOptionsChange"); this.onUpdate = t, this.onRemove = e, this.onClone = o, this.editor = s, this.formManager = d, this.onTypeChange = a, this.onOptionsChange = p; } /** * Create field editor */ createFieldEditor(t) { const e = n( "field-editor-container mb-4 p-4 border border-gray-200 rounded bg-gray-50" ), o = n("field-header flex justify-between items-center mb-3"), s = n("field-title text-lg font-semibold"); s.textContent = t.label || this.editor.t("Untitled Field"); const d = n("field-actions flex gap-2"), a = I( this.editor.t("Copy"), () => this.onClone(t.id), "secondary" ), p = I( this.editor.t("Remove"), () => this.onRemove(t.id), "danger" ); d.appendChild(a), d.appendChild(p), o.appendChild(s), o.appendChild(d), e.appendChild(o); const c = this.createMainSettings(t); e.appendChild(c); const r = this.createOptionsSettings(t); e.appendChild(r); const l = this.createValidationSettings(t); return e.appendChild(l), e; } /** * Create main field settings */ createMainSettings(t) { var i; const e = n("main-settings mb-4"), o = n("section-title text-md font-medium mb-2"); o.textContent = this.editor.t("Main Settings"), e.appendChild(o); const s = n("setting-group mb-3"), d = x(this.editor.t("Field Type:")), a = R(this.getFieldTypeOptions(), t.type, (h) => { const m = h; this.onUpdate(t.id, { type: m }), this.onTypeChange && this.onTypeChange(t.id, m); }); s.appendChild(d), s.appendChild(a), e.appendChild(s); const p = n("setting-group mb-3"), c = x(this.editor.t("Field Label:")), r = y( "text", this.editor.t("Enter field label"), t.label, (h) => this.onUpdate(t.id, { label: h }) ); p.appendChild(c), p.appendChild(r), e.appendChild(p); const l = n("setting-group mb-3"), u = x(this.editor.t("Placeholder:")), b = y( "text", this.editor.t("Enter placeholder text"), ((i = t.options) == null ? void 0 : i.placeholder) || "", (h) => this.onUpdate(t.id, { options: { ...t.options, placeholder: h } }) ); return l.appendChild(u), l.appendChild(b), e.appendChild(l), e; } /** * Create field options settings */ createOptionsSettings(t) { var g, S, L, O, C, E; const e = n("options-settings mb-4"), o = n("section-title text-md font-medium mb-2"); o.textContent = this.editor.t("Additional Options"), e.appendChild(o); const s = n("setting-group mb-3"), d = x(this.editor.t("Field Name (name):")), a = y( "text", this.editor.t("Enter field name"), ((g = t.options) == null ? void 0 : g.name) || "", (w) => this.onUpdate(t.id, { options: { ...t.options, name: w } }) ); s.appendChild(d), s.appendChild(a), e.appendChild(s); const p = n("setting-group mb-3"), c = x(this.editor.t("Field ID:")), r = y( "text", this.editor.t("Enter field ID"), ((S = t.options) == null ? void 0 : S.id) || "", (w) => this.onUpdate(t.id, { options: { ...t.options, id: w } }) ); p.appendChild(c), p.appendChild(r), e.appendChild(p); const l = n("setting-group mb-3"), u = x(this.editor.t("CSS Class:")), b = y( "text", this.editor.t("Enter CSS class"), ((L = t.options) == null ? void 0 : L.className) || "", (w) => this.onUpdate(t.id, { options: { ...t.options, className: w } }) ); l.appendChild(u), l.appendChild(b), e.appendChild(l); const i = n("checkboxes-group flex flex-wrap gap-4 mb-3"), h = F( this.editor.t("Read Only"), ((O = t.options) == null ? void 0 : O.readonly) || !1, (w) => this.onUpdate(t.id, { options: { ...t.options, readonly: w } }) ), m = F( this.editor.t("Disabled"), ((C = t.options) == null ? void 0 : C.disabled) || !1, (w) => this.onUpdate(t.id, { options: { ...t.options, disabled: w } }) ), v = F( this.editor.t("Multiple Selection"), ((E = t.options) == null ? void 0 : E.multiple) || !1, (w) => this.onUpdate(t.id, { options: { ...t.options, multiple: w } }) ); i.appendChild(h), i.appendChild(m), i.appendChild(v), e.appendChild(i); const k = this.createTypeSpecificOptions(t); if (k && e.appendChild(k), t.type === "select" || t.type === "radio") { const w = this.createOptionsList(t); e.appendChild(w); } return e; } /** * Create type-specific options */ createTypeSpecificOptions(t) { const e = n("type-specific-options mb-3"), o = n("section-title text-sm font-medium mb-2"); switch (o.textContent = this.editor.t("Type-Specific Options"), e.appendChild(o), t.type) { case "checkbox": this.addCheckboxOptions(e, t); break; case "number": case "range": this.addNumberOptions(e, t); break; case "textarea": this.addTextareaOptions(e, t); break; case "file": this.addFileOptions(e, t); break; case "date": case "time": case "datetime-local": case "month": case "week": this.addDateOptions(e, t); break; case "text": case "email": case "password": case "tel": case "url": this.addTextOptions(e, t); break; case "color": this.addColorOptions(e, t); break; case "image": this.addImageOptions(e, t); break; default: return null; } return e; } /** * Add checkbox-specific options */ addCheckboxOptions(t, e) { var l, u; const o = n("setting-group mb-2"), s = x(this.editor.t("Checkbox Text:")), d = ((l = e.options) == null ? void 0 : l.value) || e.label || "", a = y( "text", this.editor.t("Enter text to display next to checkbox"), d, (b) => { const i = this.formManager.getField(e.id), h = (i == null ? void 0 : i.options) || {}; this.onUpdate(e.id, { options: { ...h, value: b } }); } ); o.appendChild(s), o.appendChild(a), t.appendChild(o); const p = n("setting-group mb-2"), c = ((u = e.options) == null ? void 0 : u.checked) || !1, r = F( this.editor.t("Checked by Default"), c, (b) => { const i = this.formManager.getField(e.id), h = (i == null ? void 0 : i.options) || {}; this.onUpdate(e.id, { options: { ...h, checked: b } }); } ); p.appendChild(r), t.appendChild(p); } /** * Add number-specific options */ addNumberOptions(t, e) { var m, v, k; const o = n("setting-group mb-2"), s = x(this.editor.t("Minimum Value:")), d = ((m = e.options) == null ? void 0 : m.min) !== void 0 ? String(e.options.min) : "", a = y( "number", this.editor.t("Enter minimum value"), d, (g) => this.onUpdate(e.id, { options: { ...e.options, min: g ? parseFloat(g) : void 0 } }) ); o.appendChild(s), o.appendChild(a), t.appendChild(o); const p = n("setting-group mb-2"), c = x(this.editor.t("Maximum Value:")), r = ((v = e.options) == null ? void 0 : v.max) !== void 0 ? String(e.options.max) : "", l = y( "number", this.editor.t("Enter maximum value"), r, (g) => this.onUpdate(e.id, { options: { ...e.options, max: g ? parseFloat(g) : void 0 } }) ); p.appendChild(c), p.appendChild(l), t.appendChild(p); const u = n("setting-group mb-2"), b = x(this.editor.t("Step Value:")), i = ((k = e.options) == null ? void 0 : k.step) !== void 0 ? String(e.options.step) : "", h = y( "number", this.editor.t("Enter step value"), i, (g) => this.onUpdate(e.id, { options: { ...e.options, step: g ? parseFloat(g) : void 0 } }) ); u.appendChild(b), u.appendChild(h), t.appendChild(u); } /** * Add textarea-specific options */ addTextareaOptions(t, e) { var u, b; const o = n("setting-group mb-2"), s = x(this.editor.t("Rows:")), d = ((u = e.options) == null ? void 0 : u.rows) !== void 0 ? String(e.options.rows) : "4", a = y( "number", this.editor.t("Enter number of rows"), d, (i) => this.onUpdate(e.id, { options: { ...e.options, rows: i ? parseInt(i) : 4 } }) ); o.appendChild(s), o.appendChild(a), t.appendChild(o); const p = n("setting-group mb-2"), c = x(this.editor.t("Columns:")), r = ((b = e.options) == null ? void 0 : b.cols) !== void 0 ? String(e.options.cols) : "50", l = y( "number", this.editor.t("Enter number of columns"), r, (i) => this.onUpdate(e.id, { options: { ...e.options, cols: i ? parseInt(i) : 50 } }) ); p.appendChild(c), p.appendChild(l), t.appendChild(p); } /** * Add file-specific options */ addFileOptions(t, e) { var c, r; const o = n("setting-group mb-2"), s = x(this.editor.t("Accepted File Types:")), d = y( "text", this.editor.t("e.g., .pdf,.doc,.jpg"), ((c = e.options) == null ? void 0 : c.accept) || "", (l) => this.onUpdate(e.id, { options: { ...e.options, accept: l } }) ); o.appendChild(s), o.appendChild(d), t.appendChild(o); const a = n("setting-group mb-2"), p = F( this.editor.t("Allow Multiple Files"), ((r = e.options) == null ? void 0 : r.multiple) || !1, (l) => this.onUpdate(e.id, { options: { ...e.options, multiple: l } }) ); a.appendChild(p), t.appendChild(a); } /** * Add date-specific options */ addDateOptions(t, e) { var r, l, u, b; const o = n("setting-group mb-2"), s = x(this.editor.t("Minimum Date:")), d = y( "date", this.editor.t("Select minimum date"), ((l = (r = e.options) == null ? void 0 : r.min) == null ? void 0 : l.toString()) || "", (i) => this.onUpdate(e.id, { options: { ...e.options, min: i } }) ); o.appendChild(s), o.appendChild(d), t.appendChild(o); const a = n("setting-group mb-2"), p = x(this.editor.t("Maximum Date:")), c = y( "date", this.editor.t("Select maximum date"), ((b = (u = e.options) == null ? void 0 : u.max) == null ? void 0 : b.toString()) || "", (i) => this.onUpdate(e.id, { options: { ...e.options, max: i } }) ); a.appendChild(p), a.appendChild(c), t.appendChild(a); } /** * Add text-specific options */ addTextOptions(t, e) { var m, v, k, g, S, L, O; const o = n("setting-group mb-2"), s = x(this.editor.t("Size:")), d = y( "number", this.editor.t("Enter field size"), ((v = (m = e.options) == null ? void 0 : m.size) == null ? void 0 : v.toString()) || "", (C) => this.onUpdate(e.id, { options: { ...e.options, size: parseInt(C) || void 0 } }) ); o.appendChild(s), o.appendChild(d), t.appendChild(o); const a = n("setting-group mb-2"), p = x(this.editor.t("Maximum Length:")), c = y( "number", this.editor.t("Enter maximum length"), ((g = (k = e.options) == null ? void 0 : k.maxlength) == null ? void 0 : g.toString()) || "", (C) => this.onUpdate(e.id, { options: { ...e.options, maxlength: parseInt(C) || void 0 } }) ); a.appendChild(p), a.appendChild(c), t.appendChild(a); const r = n("setting-group mb-2"), l = x(this.editor.t("Minimum Length:")), u = y( "number", this.editor.t("Enter minimum length"), ((L = (S = e.options) == null ? void 0 : S.minlength) == null ? void 0 : L.toString()) || "", (C) => this.onUpdate(e.id, { options: { ...e.options, minlength: parseInt(C) || void 0 } }) ); r.appendChild(l), r.appendChild(u), t.appendChild(r); const b = n("setting-group mb-2"), i = x(this.editor.t("Autocomplete:")), h = R( [ { value: "", label: this.editor.t("Default") }, { value: "on", label: this.editor.t("On") }, { value: "off", label: this.editor.t("Off") }, { value: "name", label: this.editor.t("Name") }, { value: "email", label: this.editor.t("Email") }, { value: "tel", label: this.editor.t("Phone") }, { value: "url", label: this.editor.t("URL") }, { value: "current-password", label: this.editor.t("Current Password") }, { value: "new-password", label: this.editor.t("New Password") } ], ((O = e.options) == null ? void 0 : O.autocomplete) || "", (C) => this.onUpdate(e.id, { options: { ...e.options, autocomplete: C } }) ); b.appendChild(i), b.appendChild(h), t.appendChild(b); } /** * Add color-specific options */ addColorOptions(t, e) { var a; const o = n("setting-group mb-2"), s = x(this.editor.t("Default Color:")), d = y( "color", this.editor.t("Select default color"), ((a = e.options) == null ? void 0 : a.value) || "#000000", (p) => this.onUpdate(e.id, { options: { ...e.options, value: p } }) ); o.appendChild(s), o.appendChild(d), t.appendChild(o); } /** * Add image-specific options */ addImageOptions(t, e) { var r, l; const o = n("setting-group mb-2"), s = x(this.editor.t("Image Source:")), d = y( "text", this.editor.t("Enter image URL"), ((r = e.options) == null ? void 0 : r.src) || "", (u) => this.onUpdate(e.id, { options: { ...e.options, src: u } }) ); o.appendChild(s), o.appendChild(d), t.appendChild(o); const a = n("setting-group mb-2"), p = x(this.editor.t("Alt Text:")), c = y( "text", this.editor.t("Enter alt text"), ((l = e.options) == null ? void 0 : l.alt) || "", (u) => this.onUpdate(e.id, { options: { ...e.options, alt: u } }) ); a.appendChild(p), a.appendChild(c), t.appendChild(a); } /** * Create options list for select/radio fields */ createOptionsList(t) { var b; const e = n( "options-list mb-3 p-3 bg-gray-50 rounded border border-gray-200" ), o = n("section-title text-sm font-medium mb-2 text-gray-700"); t.type === "checkbox" ? o.textContent = this.editor.t("Checkbox Options") : t.type === "radio" ? o.textContent = this.editor.t("Radio Options") : o.textContent = this.editor.t("Options"), e.appendChild(o); const s = ((b = t.options) == null ? void 0 : b.options) || [], d = n("text-xs text-gray-500 mb-2"); t.type === "checkbox" ? d.textContent = this.editor.t("Add, edit, or reorder checkbox text options") : t.type === "radio" ? d.textContent = this.editor.t("Add, edit, or reorder radio button text options") : d.textContent = this.editor.t("Add, edit, or reorder options using buttons"), e.appendChild(d); const a = n("options-container space-y-1"); if (a.setAttribute("data-field-id", t.id), s.length === 0) { const i = n("empty-state text-center py-3 text-gray-400 text-xs"); i.innerHTML = `📝 ${this.editor.t("No options")}`, a.appendChild(i); } else s.forEach((i, h) => { const m = n( "option-item bg-white border border-gray-200 rounded p-2 hover:border-gray-300 transition-colors" ), v = n("flex items-center gap-2"), k = n( "option-number text-xs font-medium text-gray-700 bg-blue-100 text-blue-800 px-2 py-1 rounded min-w-[24px] text-center" ); k.textContent = `${h + 1}`; const g = n("text-xs text-gray-500 min-w-[40px]"); t.type === "checkbox" || t.type === "radio" ? g.textContent = this.editor.t("Text:") : g.textContent = this.editor.t("Value:"); const S = y( "text", t.type === "checkbox" || t.type === "radio" ? this.editor.t("Enter checkbox text") : this.editor.t("Enter option value"), i, (C) => { const E = [...s]; E[h] = C, this.onUpdate(t.id, { options: { ...t.options, options: E } }), this.onOptionsChange && this.onOptionsChange(t.id); } ); if (S.className = "flex-1 px-3 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white", S.placeholder = t.type === "checkbox" || t.type === "radio" ? this.editor.t("Checkbox text") : this.editor.t("Option value"), t.type === "select") { const C = y( "text", this.editor.t("Display text (optional)"), i, // Пока используем то же значение (T) => { const M = [...s]; M[h] = T, this.onUpdate(t.id, { options: { ...t.options, options: M } }), this.onOptionsChange && this.onOptionsChange(t.id); } ); C.className = "flex-1 px-3 py-1.5 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white", C.placeholder = this.editor.t("Display text"); const E = n("flex items-center gap-2 mt-1"), w = n("text-xs text-gray-500 min-w-[60px]"); w.textContent = this.editor.t("Display:"), E.appendChild(w), E.appendChild(C), m.appendChild(E); } const L = n("flex gap-1"); if (h > 0) { const C = I( "↑", () => this.moveOption(t.id, h, h - 1), "secondary" ); C.className = "px-1.5 py-0.5 text-xs bg-gray-100 hover:bg-gray-200 text-gray-600 rounded transition-colors", C.title = this.editor.t("Move up"), L.appendChild(C); } if (h < s.length - 1) { const C = I( "↓", () => this.moveOption(t.id, h, h + 1), "secondary" ); C.className = "px-1.5 py-0.5 text-xs bg-gray-100 hover:bg-gray-200 text-gray-600 rounded transition-colors", C.title = this.editor.t("Move down"), L.appendChild(C); } const O = I( "×", () => { var E, w; const C = s.filter((T, M) => M !== h); this.onUpdate(t.id, { options: { ...t.options, options: C } }), (w = (E = this.editor) == null ? void 0 : E.showInfoNotification) == null || w.call( E, t.type === "checkbox" ? this.editor.t("Checkbox removed") : t.type === "radio" ? this.editor.t("Radio option removed") : this.editor.t("Option removed") ), this.onOptionsChange && this.onOptionsChange(t.id); }, "danger" ); O.className = "px-1.5 py-0.5 text-xs bg-red-100 hover:bg-red-200 text-red-600 rounded transition-colors", O.title = this.editor.t("Remove option"), L.appendChild(O), v.appendChild(k), v.appendChild(g), v.appendChild(S), v.appendChild(L), m.appendChild(v), a.appendChild(m); }); e.appendChild(a); const p = n("action-buttons mt-2 space-y-1"), c = I( t.type === "checkbox" ? `➕ ${this.editor.t("Add Checkbox")}` : t.type === "radio" ? `➕ ${this.editor.t("Add Radio")}` : `➕ ${this.editor.t("Add Option")}`, () => { var m, v; const i = t.type === "checkbox" ? this.editor.t("New Checkbox") : t.type === "radio" ? this.editor.t("New Radio") : this.editor.t("New Option"), h = [...s, i]; this.onUpdate(t.id, { options: { ...t.options, options: h } }), (v = (m = this.editor) == null ? void 0 : m.showSuccessNotification) == null || v.call( m, t.type === "checkbox" ? this.editor.t("Checkbox added successfully") : t.type === "radio" ? this.editor.t("Radio option added successfully") : this.editor.t("Option added successfully") ), this.onOptionsChange && this.onOptionsChange(t.id); }, "primary" ); c.className = "w-full py-1.5 px-2 bg-blue-600 hover:bg-blue-700 text-white text-xs font-medium rounded transition-colors"; const r = n("bulk-actions flex gap-1"), l = I( `🗑️ ${this.editor.t("Clear")}`, () => { var i, h; this.onUpdate(t.id, { options: { ...t.options, options: [] } }), (h = (i = this.editor) == null ? void 0 : i.showInfoNotification) == null || h.call(i, this.editor.t("All options cleared")), this.onOptionsChange && this.onOptionsChange(t.id); }, "danger" ); l.className = "flex-1 py-1 px-2 bg-red-600 hover:bg-red-700 text-white text-xs rounded"; const u = I( `📋 ${this.editor.t("Presets")}`, () => this.showPresetOptions(t), "secondary" ); return u.className = "flex-1 py-1 px-2 bg-gray-600 hover:bg-gray-700 text-white text-xs rounded", r.appendChild(l), r.appendChild(u), p.appendChild(c), p.appendChild(r), e.appendChild(p), e; } /** * Move option to new position */ moveOption(t, e, o) { var p, c, r; const s = this.getFieldById(t); if (!s || !((p = s.options) != null && p.options)) return; const d = [...s.options.options], [a] = d.splice(e, 1); d.splice(o, 0, a), this.onUpdate(t, { options: { ...s.options, options: d } }), (r = (c = this.editor) == null ? void 0 : c.showInfoNotification) == null || r.call( c, s.type === "checkbox" ? this.editor.t("Checkbox moved") : s.type === "radio" ? this.editor.t("Radio option moved") : this.editor.t("Option moved") ), this.onOptionsChange && this.onOptionsChange(t); } /** * Show preset options dialog */ showPresetOptions(t) { const e = { countries: [ "United States", "Canada", "United Kingdom", "Germany", "France", "Japan", "Australia", "Brazil", "India", "China" ], months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], colors: [ "Red", "Blue", "Green", "Yellow", "Orange", "Purple", "Black", "White", "Gray", "Pink" ], sizes: ["XS", "S", "M", "L", "XL", "XXL"], "age-groups": ["18-25", "26-35", "36-45", "46-55", "56-65", "65+"], genders: [this.editor.t("Male"), this.editor.t("Female"), this.editor.t("Other")], "yes-no": [this.editor.t("Yes"), this.editor.t("No")], custom: [] }, o = document.createElement("div"); o.className = "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"; const s = document.createElement("div"); s.className = "bg-white rounded-xl shadow-2xl max-w-2xl w-full max-h-[80vh] overflow-hidden"; const d = document.createElement("div"); d.className = "bg-gradient-to-r from-blue-600 to-purple-600 text-white p-6"; const a = document.createElement("h3"); a.className = "text-2xl font-bold mb-2", a.textContent = this.editor.t("Select Preset Options"); const p = document.createElement("p"); p.className = "text-blue-100 text-sm", p.textContent = this.editor.t( "Choose from predefined option sets or create custom options" ), d.appendChild(a), d.appendChild(p), s.appendChild(d); const c = document.createElement("div"); c.className = "p-6 max-h-[60vh] overflow-y-auto"; const r = document.createElement("div"); r.className = "grid grid-cols-1 md:grid-cols-2 gap-4", Object.entries(e).forEach(([i, h]) => { if (i === "custom") return; const m = document.createElement("div"); m.className = "preset-card border border-gray-200 rounded-lg p-4 hover:border-blue-300 hover:shadow-md transition-all duration-200 cursor-pointer bg-white"; const v = document.createElement("div"); v.className = "text-2xl mb-3"; const k = { countries: "🌍", months: "📅", days: "📆", colors: "🎨", sizes: "👕", "age-groups": "👥", genders: "👤", "yes-no": "✅" }; v.textContent = k[i] || "📋"; const g = document.createElement("h4"); g.className = "font-semibold text-gray-800 mb-2", g.textContent = this.editor.t( i.charAt(0).toUpperCase() + i.slice(1).replace("-", " ") ); const S = document.createElement("p"); S.className = "text-sm text-gray-600 mb-3", S.textContent = `${h.length} ${this.editor.t("options")}`; const L = document.createElement("div"); L.className = "text-xs text-gray-500 bg-gray-50 p-2 rounded border", L.textContent = h.slice(0, 3).join(", ") + (h.length > 3 ? "..." : ""), m.appendChild(v), m.appendChild(g), m.appendChild(S), m.appendChild(L), m.addEventListener("click", () => { var O, C; this.onUpdate(t.id, { options: { ...t.options, options: h } }), (C = (O = this.editor) == null ? void 0 : O.showSuccessNotification) == null || C.call( O, `${this.editor.t("Applied")} ${h.length} ${this.editor.t("options")}` ), this.onOptionsChange && this.onOptionsChange(t.id), o.remove(); }), m.addEventListener("mouseenter", () => { m.style.transform = "translateY(-2px)"; }), m.addEventListener("mouseleave", () => { m.style.transform = "translateY(0)"; }), r.appendChild(m); }), c.appendChild(r), s.appendChild(c); const l = document.createElement("div"); l.className = "bg-gray-50 px-6 py-4 border-t border-gray-200 flex justify-end"; const u = document.createElement("button"); u.className = "px-6 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 transition-colors duration-200 font-medium", u.textContent = this.editor.t("Cancel"), u.addEventListener("click", () => o.remove()), l.appendChild(u), s.appendChild(l), o.appendChild(s), o.addEventListener("click", (i) => { i.target === o && o.remove(); }); const b = (i) => { i.key === "Escape" && (o.remove(), this.editor.getDOMContext().removeEventListener("keydown", b)); }; this.editor.getDOMContext().addEventListener("keydown", b), document.body.appendChild(o); } /** * Get field by ID (helper method) */ getFieldById(t) { return this.formManager.getField(t) || null; } /** * Get field type options */ getFieldTypeOptions() { return [ { value: "text", label: this.editor.t("Text Input") }, { value: "textarea", label: this.editor.t("Text Area") }, { value: "select", label: this.editor.t("Dropdown") }, { value: "checkbox", label: this.editor.t("Checkbox") }, { value: "radio", label: this.editor.t("Radio Button") }, { value: "button", label: this.editor.t("Button") }, { value: "file", label: this.editor.t("File Upload") }, { value: "date", label: this.editor.t("Date") }, { value: "time", label: this.editor.t("Time") }, { value: "range", label: this.editor.t("Range") }, { value: "email", label: this.editor.t("Email") }, { value: "password", label: this.editor.t("Password") }, { value: "number", label: this.editor.t("Number") }, { value: "tel", label: this.editor.t("Phone") }, { value: "url", label: this.editor.t("URL") }, { value: "color", label: this.editor.t("Color") }, { value: "datetime-local", label: this.editor.t("Date & Time") }, { value: "month", label: this.editor.t("Month") }, { value: "week", label: this.editor.t("Week") }, { value: "hidden", label: this.editor.t("Hidden Field") }, { value: "image", label: this.editor.t("Image Button") } ]; } /** * Create validation settings */ createValidationSettings(t) { var m, v, k, g, S, L; const e = n("validation-settings mb-4"), o = n("section-title text-md font-medium mb-2"); o.textContent = this.editor.t("Validation"), e.appendChild(o); const s = n("setting-group mb-3"), d = F( this.editor.t("Required Field"), ((m = t.validation) == null ? void 0 : m.required) || !1, (O) => this.onUpdate(t.id, { validation: { ...t.validation, required: O } }) ); s.appendChild(d), e.appendChild(s); const a = n("setting-group mb-3"), p = x(this.editor.t("Regular Expression:")), c = y( "text", this.editor.t("Enter regular expression"), ((v = t.validation) == null ? void 0 : v.pattern) || "", (O) => this.onUpdate(t.id, { validation: { ...t.validation, pattern: O } }) ); a.appendChild(p), a.appendChild(c), e.appendChild(a); const r = n("setting-group mb-3"), l = x(this.editor.t("Minimum Length:")), u = y( "number", this.editor.t("Enter minimum length"), ((g = (k = t.validation) == null ? void 0 : k.minLength) == null ? void 0 : g.toString()) || "", (O) => this.onUpdate(t.id, { validation: { ...t.validation, minLength: parseInt(O) || void 0 } }) ); r.appendChild(l), r.appendChild(u), e.appendChild(r); const b = n("setting-group mb-3"), i = x(this.editor.t("Maximum Length:")), h = y( "number", this.editor.t("Enter maximum length"), ((L = (S = t.validation) == null ? void 0 : S.maxLength) == null ? void 0 : L.toString()) || "", (O) => this.onUpdate(t.id, { validation: { ...t.validation, maxLength: parseInt(O) || void 0 } }) ); return b.appendChild(i), b.appendChild(h), e.appendChild(b), e; } } export { V as FieldEditor };