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
3 lines (2 loc) • 14.7 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 */
"use strict";var O=Object.defineProperty;var D=(f,e,t)=>e in f?O(f,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):f[e]=t;var l=(f,e,t)=>D(f,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("../../../core/ui/PopupManager.cjs"),q=require("../services/FormManager.cjs"),A=require("./FieldEditor.cjs"),H=require("./FormPreview.cjs"),o=require("../../../utils/helpers.cjs"),U=require("./TemplatesModal.cjs");class m{constructor(e){l(this,"editor");l(this,"popup",null);l(this,"formManager");l(this,"fieldEditor",null);l(this,"formPreview",null);l(this,"callback",null);l(this,"selectedFieldId",null);l(this,"previewContainer",null);l(this,"fieldsListContainer",null);l(this,"fieldEditorContainer",null);l(this,"isEditMode",!1);l(this,"existingFormElement",null);l(this,"templatesModal",null);l(this,"handleEscapeKey",e=>{var t,i;e.key==="Escape"&&((t=this.popup)!=null&&t.isOpen())&&((i=this.popup)==null||i.hide(),this.destroy())});l(this,"dragStartIndex",null);this.editor=e,this.formManager=new q.FormManager(e),this.templatesModal=new U.TemplatesModal(e),this.popup=new N.PopupManager(e,{title:e.t("Form Builder"),className:"form-builder-modal",closeOnClickOutside:!0,buttons:[{label:e.t("Cancel"),variant:"secondary",onClick:()=>{var t;(t=this.popup)==null||t.hide(),this.destroy()}},{label:e.t("Save Form"),variant:"primary",onClick:()=>this.saveForm()}],items:[{type:"custom",id:"form-builder-content",content:()=>this.createContent()}]}),this.setupCloseHandlers()}setupCloseHandlers(){this.handleEscapeKey=e=>{var t;e.key==="Escape"&&((t=this.popup)!=null&&t.isOpen())&&(this.popup.hide(),this.destroy())},this.editor.getDOMContext().addEventListener("keydown",this.handleEscapeKey)}createContent(){const e=o.createContainer("form-builder-modal-content"),t=o.createContainer("form-builder-header-panel flex justify-between items-center mb-2"),i=o.createContainer("form-builder-title text-xl font-bold");i.textContent=this.isEditMode?this.editor.t("Edit Form"):this.editor.t("Form Builder");const n=o.createButton(this.editor.t("Templates"),()=>this.openTemplatesModal(),"secondary");t.appendChild(i),t.appendChild(n),e.appendChild(t);const r=this.createFormSettings();e.appendChild(r);const s=o.createContainer("form-builder-main"),d=this.createFieldsPanel();s.appendChild(d);const h=this.createFieldEditorPanel();s.appendChild(h),e.appendChild(s);const a=this.createPreviewPanel();return e.appendChild(a),e}createFormSettings(){const e=o.createContainer("form-settings-panel"),t=o.createContainer("settings-title");t.textContent=this.editor.t("Form Settings"),e.appendChild(t);const i=o.createContainer("setting-group"),n=o.createLabel(this.editor.t("Method:")),r=o.createSelectField([{value:"GET",label:"GET"},{value:"POST",label:"POST"},{value:"PUT",label:"PUT"},{value:"DELETE",label:"DELETE"},{value:"PATCH",label:"PATCH"}],this.formManager.getFormMethod(),a=>{this.formManager.updateFormMethod(a)});i.appendChild(n),i.appendChild(r),e.appendChild(i);const s=o.createContainer("setting-group"),d=o.createLabel(this.editor.t("Action URL:")),h=o.createInputField("text",this.editor.t("Enter form action URL"),this.formManager.getFormAction(),a=>{this.formManager.updateFormAction(a)});return h.id="form-action-url",s.appendChild(d),s.appendChild(h),e.appendChild(s),e}createFieldsPanel(){const e=o.createContainer("fields-panel"),t=o.createContainer("fields-header"),i=o.createContainer("fields-title");i.textContent=this.editor.t("Form Fields");const n=o.createButton("+",()=>this.addField(),"primary");return n.className="add-field-button",t.appendChild(i),t.appendChild(n),e.appendChild(t),this.fieldsListContainer=o.createContainer("fields-list"),e.appendChild(this.fieldsListContainer),this.renderFieldsList(),e}createFieldEditorPanel(){const e=o.createContainer("field-editor-panel"),t=o.createContainer("editor-title");return t.textContent=this.editor.t("Field Editor"),e.appendChild(t),this.fieldEditorContainer=o.createContainer("field-editor-content"),e.appendChild(this.fieldEditorContainer),this.fieldEditor||(this.fieldEditor=new A.FieldEditor((i,n)=>this.updateField(i,n),i=>this.removeField(i),i=>this.cloneField(i),this.editor,this.formManager,(i,n)=>this.onFieldTypeChange(i,n),i=>this.onOptionsChange(i))),e}createPreviewPanel(){const e=o.createContainer("preview-panel"),t=o.createContainer("preview-title");t.textContent=this.editor.t("Form Preview"),e.appendChild(t);const i=o.createContainer("preview-content");return e.appendChild(i),this.formPreview||(this.formPreview=new H.FormPreview(i,this.editor)),this.previewContainer=i,e}renderFieldsList(){if(!this.fieldsListContainer)return;this.fieldsListContainer.innerHTML="";const e=this.formManager.getFields();if(e.length===0){const t=o.createContainer("no-fields");t.textContent=this.editor.t("No fields added yet"),this.fieldsListContainer.appendChild(t);return}e.forEach((t,i)=>{const n=o.createContainer("field-item");n.setAttribute("draggable","true"),n.addEventListener("dragstart",c=>this.handleDragStart(c,i)),n.addEventListener("dragover",c=>this.handleDragOver(c,i)),n.addEventListener("drop",c=>this.handleDrop(c,i)),this.selectedFieldId===t.id&&n.classList.add("selected");const r=o.createContainer("field-title");r.textContent=t.label||this.editor.t("Untitled Field");const s=o.createContainer("field-type");s.textContent=t.type;const d=o.createContainer("field-actions"),h=o.createButton("↑",()=>this.moveField(t.id,i-1),"secondary");h.className="field-action-button",h.disabled=i===0;const a=o.createButton("↓",()=>this.moveField(t.id,i+1),"secondary");a.className="field-action-button",a.disabled=i===e.length-1;const p=o.createButton("×",()=>this.removeField(t.id),"danger");p.className="field-action-button",d.appendChild(h),d.appendChild(a),d.appendChild(p),n.appendChild(r),n.appendChild(s),n.appendChild(d),n.addEventListener("click",()=>this.selectField(t.id)),this.fieldsListContainer.appendChild(n)}),this.updatePreview()}selectField(e){this.selectedFieldId=e,this.renderFieldsList(),this.renderFieldEditor()}renderFieldEditor(){if(!(!this.fieldEditorContainer||!this.fieldEditor))if(this.fieldEditorContainer.innerHTML="",this.selectedFieldId){const e=this.formManager.getField(this.selectedFieldId);if(e){const t=this.fieldEditor.createFieldEditor(e);this.fieldEditorContainer.appendChild(t)}}else{const e=o.createContainer("no-field-message");e.textContent=this.editor.t("Select a field to edit"),this.fieldEditorContainer.appendChild(e)}}updateFieldEditorTitle(){if(!this.fieldEditorContainer||!this.selectedFieldId)return;const e=this.formManager.getField(this.selectedFieldId);if(!e)return;const t=this.fieldEditorContainer.querySelector(".field-title");t&&(t.textContent=e.label||this.editor.t("Untitled Field"))}addField(e="text"){this.formManager.addField(e);const t=this.formManager.getFields();t.length>0&&(this.selectedFieldId=t[t.length-1].id),this.renderFieldsList(),this.renderFieldEditor()}renderFieldsListWithoutPreview(){if(!this.fieldsListContainer)return;this.fieldsListContainer.innerHTML="";const e=this.formManager.getFields();if(e.length===0){const t=o.createContainer("no-fields");t.textContent=this.editor.t("No fields added yet"),this.fieldsListContainer.appendChild(t);return}e.forEach((t,i)=>{const n=o.createContainer("field-item");this.selectedFieldId===t.id&&n.classList.add("selected");const r=o.createContainer("field-title");r.textContent=t.label||this.editor.t("Untitled Field");const s=o.createContainer("field-type");s.textContent=t.type;const d=o.createContainer("field-actions"),h=o.createButton("↑",()=>this.moveField(t.id,i-1),"secondary");h.className="field-action-button",h.disabled=i===0;const a=o.createButton("↓",()=>this.moveField(t.id,i+1),"secondary");a.className="field-action-button",a.disabled=i===e.length-1;const p=o.createButton("×",()=>this.removeField(t.id),"danger");p.className="field-action-button",d.appendChild(h),d.appendChild(a),d.appendChild(p),n.appendChild(r),n.appendChild(s),n.appendChild(d),n.addEventListener("click",()=>this.selectField(t.id)),this.fieldsListContainer.appendChild(n)})}updateField(e,t){this.formManager.updateField(e,t),this.renderFieldsListWithoutPreview(),this.updateFieldEditorTitle(),this.updatePreview()}removeField(e){if(confirm(this.editor.t("Are you sure you want to delete this field?"))){const i=this.formManager.getFields().findIndex(r=>r.id===e);this.formManager.removeField(e);const n=this.formManager.getFields();n.length>0?this.selectedFieldId===e&&(i<n.length?this.selectedFieldId=n[i].id:this.selectedFieldId=n[n.length-1].id):this.selectedFieldId=null,this.renderFieldsListWithoutPreview(),this.renderFieldEditor()}}cloneField(e){const t=this.formManager.getField(e);if(t){const i={...t,id:`field_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,label:`${t.label} (Copy)`};this.formManager.addField(t.type,i),this.selectedFieldId=i.id,this.renderFieldsListWithoutPreview(),this.renderFieldEditor()}}moveField(e,t){this.formManager.moveField(e,t),this.renderFieldsListWithoutPreview()}updatePreview(){if(!this.previewContainer||!this.formPreview)return;const e=this.formManager.getFormConfig();e&&e.fields.length>0?this.formPreview.createPreview(e):this.previewContainer.innerHTML='<p class="no-preview-message">No fields to preview</p>'}saveForm(){var t,i,n;const e=this.formManager.getFormConfig();e&&(this.isEditMode&&this.existingFormElement?confirm(this.editor.t("Are you sure you want to update this form?"))&&(this.existingFormElement.outerHTML=this.formManager.createForm(e),(t=this.popup)==null||t.hide(),this.destroy()):((i=this.callback)==null||i.call(this,e),(n=this.popup)==null||n.hide(),this.destroy()))}show(e,t=!1,i=null){var n;this.callback=e,this.isEditMode=t,this.existingFormElement=i,t&&i?(this.formManager.loadForm(i),this.updatePopupForEditMode(),this.updateFormSettings(),this.renderFieldsListWithoutPreview(),this.renderFieldEditor()):(this.selectedFieldId=null,this.updatePopupForCreateMode()),(n=this.popup)==null||n.show(),setTimeout(()=>{const r=this.editor.getDOMContext().getElementById("form-action-url");r&&r.focus()},0),this.updatePreview()}updatePopupForEditMode(){var i,n;const e=(i=this.popup)==null?void 0:i.getElement().querySelector(".popup-header-title");e&&(e.textContent=this.editor.t("Edit Form"));const t=(n=this.popup)==null?void 0:n.getElement().querySelector('.popup-footer button[data-variant="primary"]');t&&(t.textContent=this.editor.t("Update Form"))}updatePopupForCreateMode(){var i,n;const e=(i=this.popup)==null?void 0:i.getElement().querySelector(".popup-header-title");e&&(e.textContent=this.editor.t("Form Builder"));const t=(n=this.popup)==null?void 0:n.getElement().querySelector('.popup-footer button[data-variant="primary"]');t&&(t.textContent=this.editor.t("Save Form"))}updateFormSettings(){var i,n;const e=(i=this.popup)==null?void 0:i.getElement().querySelector(".form-settings-panel select");e&&(e.value=this.formManager.getFormMethod());const t=(n=this.popup)==null?void 0:n.getElement().querySelector('.form-settings-panel input[type="text"]');t&&(t.value=this.formManager.getFormAction()||"")}destroy(){this.editor.getDOMContext().removeEventListener("keydown",this.handleEscapeKey),this.popup&&(this.popup.destroy(),this.popup=null),this.fieldEditor&&(this.fieldEditor=null),this.formPreview&&(this.formPreview=null)}openTemplatesModal(){var t,i;(t=this.popup)==null||t.hide();const e=this.editor.saveCursorPosition();(i=this.templatesModal)==null||i.show(n=>{if(n&&n.config){const r=new m(this.editor);r.show(s=>{e&&this.editor.restoreCursorPosition(e);const d=this.formManager.createForm(s);this.editor.insertContent(d),this.editor.insertContent(o.createLineBreak())},!1,null),r.loadFormConfig(n.config)}})}loadFormConfig(e){this.formManager.loadFormConfig(e),this.selectedFieldId=null,this.updateFormSettings(),this.renderFieldsListWithoutPreview(),this.renderFieldEditor(),this.updatePreview()}handleDragStart(e,t){var i;this.dragStartIndex=t,(i=e.dataTransfer)==null||i.setData("text/plain",t.toString())}handleDragOver(e,t){e.preventDefault()}handleDrop(e,t){if(e.preventDefault(),this.dragStartIndex!==null&&this.dragStartIndex!==t){const n=this.formManager.getFields()[this.dragStartIndex];this.formManager.moveField(n.id,t),this.renderFieldsListWithoutPreview(),this.dragStartIndex=null}}onFieldTypeChange(e,t){var s,d,h,a,p,c,C,F,g,v,E,M,b,w,P,y,L,x,S,I,k,T,B;const i=this.formManager.getField(e);if(!i)return;const n={name:((s=i.options)==null?void 0:s.name)||e,placeholder:((d=i.options)==null?void 0:d.placeholder)||"",className:((h=i.options)==null?void 0:h.className)||"",readonly:((a=i.options)==null?void 0:a.readonly)||!1,disabled:((p=i.options)==null?void 0:p.disabled)||!1};switch(t){case"select":case"radio":if(n.options=((c=i.options)==null?void 0:c.options)||[],n.multiple=t==="select"&&((C=i.options)==null?void 0:C.multiple)||!1,n.options.length===0){const u=t==="radio"?this.editor.t("New Radio"):this.editor.t("Option 1");n.options=[u]}break;case"checkbox":n.value=((F=i.options)==null?void 0:F.value)||i.label||this.editor.t("New Checkbox"),n.checked=((g=i.options)==null?void 0:g.checked)||!1;break;case"number":case"range":n.min=((v=i.options)==null?void 0:v.min)||"",n.max=((E=i.options)==null?void 0:E.max)||"",n.step=((M=i.options)==null?void 0:M.step)||"";break;case"textarea":n.rows=((b=i.options)==null?void 0:b.rows)||3,n.cols=((w=i.options)==null?void 0:w.cols)||50;break;case"file":n.accept=((P=i.options)==null?void 0:P.accept)||"",n.multiple=((y=i.options)==null?void 0:y.multiple)||!1;break;case"date":case"time":case"datetime-local":case"month":case"week":n.min=((L=i.options)==null?void 0:L.min)||"",n.max=((x=i.options)==null?void 0:x.max)||"";break;case"text":case"email":case"password":case"tel":case"url":n.maxlength=((S=i.options)==null?void 0:S.maxlength)||"",n.minlength=((I=i.options)==null?void 0:I.minlength)||"";break;case"color":n.value=((k=i.options)==null?void 0:k.value)||"#000000";break;case"image":n.src=((T=i.options)==null?void 0:T.src)||"",n.alt=((B=i.options)==null?void 0:B.alt)||"";break}const r={type:t,options:n};if(i.validation){const u={...i.validation};t!=="email"&&t!=="url"&&(delete u.email,delete u.url),t!=="number"&&t!=="range"&&delete u.numeric,r.validation=u}this.formManager.updateField(e,r),this.renderFieldEditor(),this.updatePreview()}onOptionsChange(e){this.renderFieldEditor(),this.updatePreview()}}exports.FormBuilderModal=m;