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) • 15.1 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 w=Object.defineProperty;var E=(g,e,r)=>e in g?w(g,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):g[e]=r;var l=(g,e,r)=>E(g,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("../../../core/ui/PopupManager.cjs"),T=require("../services/ChartRenderer.cjs"),L=require("./MultiSeriesDataEditor.cjs"),b=require("./ChartDataEditor.cjs"),v=require("../constants/chartTypes.cjs"),o=require("../../../utils/helpers.cjs"),f=[{key:"bar-sales",name:"Bar: Sales",type:"bar",data:[{label:"Jan",value:120},{label:"Feb",value:90},{label:"Mar",value:150},{label:"Apr",value:80},{label:"May",value:200}]},{key:"pie-expenses",name:"Pie: Expenses",type:"pie",data:[{label:"Rent",value:40},{label:"Salary",value:30},{label:"Marketing",value:15},{label:"Other",value:15}]},{key:"line-visitors",name:"Line: Visitors",type:"line",data:[{label:"Mon",value:100},{label:"Tue",value:120},{label:"Wed",value:90},{label:"Thu",value:140},{label:"Fri",value:180},{label:"Sat",value:220},{label:"Sun",value:160}]},{key:"doughnut-browsers",name:"Doughnut: Browsers",type:"doughnut",data:[{label:"Chrome",value:65},{label:"Firefox",value:15},{label:"Safari",value:10},{label:"Edge",value:7},{label:"Other",value:3}]}];class A{constructor(e){l(this,"editor");l(this,"popup");l(this,"renderer");l(this,"currentEditor");l(this,"selectedType","bar");l(this,"onInsert",null);l(this,"previewTimeout",null);l(this,"editingChart",null);l(this,"chartTitle","");l(this,"xAxisLabel","");l(this,"yAxisLabel","");l(this,"showLegend",!0);l(this,"chartWidth",800);l(this,"chartHeight",400);l(this,"showGrid",!0);l(this,"chartMode","default");l(this,"chartOrientation","vertical");this.editor=e,this.renderer=new T.ChartRenderer(e),this.popup=new S.PopupManager(e,{title:e.t("Insert"),className:"chart-menu",closeOnClickOutside:!0,buttons:[{label:e.t("Cancel"),variant:"secondary",onClick:()=>this.popup.hide()},{label:e.t("Insert"),variant:"primary",onClick:()=>this.handleSubmit()}],items:this.createPopupItems()}),this.currentEditor=new b.ChartDataEditor(e,r=>this.schedulePreviewUpdate([{name:"Series 1",data:r}]))}createPopupItems(){return[{type:"custom",id:"chart-type-selector",content:()=>this.createChartTypeSelector()},{type:"custom",id:"meta-fields",content:()=>this.createMetaFields()},{type:"custom",id:"chart-dimensions",content:()=>this.createDimensionsSelector()},{type:"custom",id:"display-settings",content:()=>this.createDisplaySettings()},{type:"custom",id:"template-selector",content:()=>this.createTemplateSelector()},{type:"custom",id:"data-editor-container",content:()=>this.createDataEditorContainer()},{type:"custom",id:"preview-container",content:()=>this.createPreviewContainer()},{type:"custom",id:"export-btn",content:()=>this.createExportButton()}]}createMetaFields(){const e=o.createContainer("meta-fields flex flex-col gap-3 mb-4"),r=o.createContainer("flex flex-col gap-1"),i=o.createSpan("text-sm font-medium text-gray-700");i.textContent=this.editor.t("Chart Title");const t=document.createElement("input");t.type="text",t.placeholder=this.editor.t("Enter chart title..."),t.value=this.chartTitle,t.className="meta-input px-3 py-2 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all",t.oninput=u=>{this.chartTitle=u.target.value,this.schedulePreviewUpdate(this.currentEditor.getData())},r.appendChild(i),r.appendChild(t);const s=o.createContainer("flex flex-col gap-1"),a=o.createSpan("text-sm font-medium text-gray-700");a.textContent=this.editor.t("X Axis Label");const n=document.createElement("input");n.type="text",n.placeholder=this.editor.t("Enter X axis label..."),n.value=this.xAxisLabel,n.className="meta-input px-3 py-2 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all",n.oninput=u=>{this.xAxisLabel=u.target.value,this.schedulePreviewUpdate(this.currentEditor.getData())},s.appendChild(a),s.appendChild(n);const c=o.createContainer("flex flex-col gap-1"),d=o.createSpan("text-sm font-medium text-gray-700");d.textContent=this.editor.t("Y Axis Label");const h=document.createElement("input");return h.type="text",h.placeholder=this.editor.t("Enter Y axis label..."),h.value=this.yAxisLabel,h.className="meta-input px-3 py-2 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all",h.oninput=u=>{this.yAxisLabel=u.target.value,this.schedulePreviewUpdate(this.currentEditor.getData())},c.appendChild(d),c.appendChild(h),e.appendChild(r),e.appendChild(s),e.appendChild(c),e}createTemplateSelector(){const e=o.createContainer("template-selector flex flex-col gap-2 mb-4"),r=o.createSpan("text-sm font-medium text-gray-700");r.textContent=this.editor.t("Templates"),e.appendChild(r);const i=document.createElement("select");i.className="template-select px-3 py-2 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all bg-white";const t=document.createElement("option");return t.value="",t.textContent=this.editor.t("Select template..."),i.appendChild(t),f.forEach(s=>{const a=document.createElement("option");a.value=s.key,a.textContent=s.name,i.appendChild(a)}),i.onchange=s=>{var n,c;const a=s.target.value;if(a){const d=f.find(h=>h.key===a);if(d){this.selectedType=d.type,this.updateEditor(d.type);const h=(n=this.popup.getElement())==null?void 0:n.querySelectorAll("[data-type]");h==null||h.forEach(C=>C.classList.remove("selected"));const u=(c=this.popup.getElement())==null?void 0:c.querySelector(`[data-type="${d.type}"]`);u&&u.classList.add("selected"),setTimeout(()=>{this.currentEditor&&("setData"in this.currentEditor&&this.currentEditor.setData(d.data),this.updatePreview(d.data))},100)}}},e.appendChild(i),e}createChartTypeSelector(){const e=o.createContainer("chart-type-selector"),r=o.createSpan("text-sm font-medium text-gray-700 mb-4 block");r.textContent=this.editor.t("Chart Type"),e.appendChild(r);const i=o.createContainer("grid");return Object.entries(v.CHART_TYPE_CONFIGS).forEach(([t,s])=>{const a=o.createContainer(`chart-type-option ${t===this.selectedType?"selected":""}`);a.setAttribute("data-type",t);const n=o.createContainer("w-10 h-10 mb-3 mx-auto flex items-center justify-center");n.innerHTML=s.icon;const c=o.createSpan();c.textContent=this.editor.t(s.name),a.appendChild(n),a.appendChild(c),a.onclick=()=>{i.querySelectorAll(".chart-type-option").forEach(d=>{d.classList.remove("selected")}),a.classList.add("selected"),this.selectedType=t,this.updateEditor(t)},i.appendChild(a)}),e.appendChild(i),e}createDataEditorContainer(){const e=o.createContainer("data-editor-container mb-6");return this.updateEditor("bar",e),e}createPreviewContainer(){const e=o.createContainer("preview-container h-64 bg-gray-50 rounded-lg flex items-center justify-center");return e.innerHTML='<div class="text-gray-400">Chart preview will appear here</div>',e}createExportButton(){const e=o.createContainer("export-container flex justify-center mt-4"),r=o.createButton("",()=>this.exportPreviewAsPNG());r.className="export-btn px-4 py-2 rounded-lg bg-gradient-to-r from-green-500 to-green-600 text-white hover:from-green-600 hover:to-green-700 transition-all duration-200 shadow-md hover:shadow-lg flex items-center gap-2 font-medium";const i=o.createContainer("w-4 h-4");i.innerHTML='<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>';const t=o.createSpan();return t.textContent=this.editor.t("Export as PNG"),r.appendChild(i),r.appendChild(t),e.appendChild(r),e}exportPreviewAsPNG(){var i,t,s;const e=(i=this.popup.getElement())==null?void 0:i.querySelector(".preview-container");if(!e)return;const r=e.querySelector("img.svg-chart");if(r&&r.src){const a=document.createElement("a");a.href=r.src,a.download="chart.png",(this.editor.getInnerContainer()||document.body).appendChild(a),a.click(),(t=a.parentNode)==null||t.removeChild(a)}else{const a=e.querySelector("canvas");if(a){const n=document.createElement("a");n.href=a.toDataURL("image/png"),n.download="chart.png",(this.editor.getInnerContainer()||document.body).appendChild(n),n.click(),(s=n.parentNode)==null||s.removeChild(n)}}}updateEditor(e,r){const i=v.CHART_TYPE_CONFIGS[e],t=r??this.popup.getElement().querySelector(".data-editor-container");t&&(t.innerHTML="",i.supportsMultipleSeries?this.currentEditor=new L.MultiSeriesDataEditor(this.editor,s=>this.schedulePreviewUpdate(s)):this.currentEditor=new b.ChartDataEditor(this.editor,s=>this.schedulePreviewUpdate([{name:this.editor.t("Series 1"),data:s}]),i.requiresXY,e==="scatter"),t.appendChild(this.currentEditor.getElement()))}schedulePreviewUpdate(e){this.previewTimeout&&window.clearTimeout(this.previewTimeout),this.previewTimeout=window.setTimeout(()=>{this.updatePreview(e)},100)}updatePreview(e){var s;const r=(s=this.popup.getElement())==null?void 0:s.querySelector(".preview-container");if(!r)return;const i={width:350,height:250,title:this.chartTitle,xAxis:{title:this.xAxisLabel},yAxis:{title:this.yAxisLabel},legend:{show:this.showLegend},grid:{show:this.showGrid},mode:this.chartMode,orientation:this.chartOrientation},t=this.renderer.createChart(this.selectedType,e,i);t.style.position="absolute",t.style.top="50%",t.style.left="50%",t.style.transform="translate(-50%, -50%)",r.innerHTML="",r.appendChild(t)}handleSubmit(){const e=this.currentEditor.getData();if(!e||Array.isArray(e)&&e.length===0)return;const r={width:this.chartWidth,height:this.chartHeight,title:this.chartTitle,xAxis:{title:this.xAxisLabel},yAxis:{title:this.yAxisLabel},legend:{show:this.showLegend},grid:{show:this.showGrid},mode:this.chartMode,orientation:this.chartOrientation};if(this.editingChart){this.editingChart.setAttribute("data-chart-type",this.selectedType),this.editingChart.setAttribute("data-chart-data",JSON.stringify(e));const i=this.renderer.createChart(this.selectedType,e,r);this.editingChart.innerHTML="",this.editingChart.appendChild(i)}else{const i=o.createContainer("chart-container");i.style.width=r.width+"px",i.style.height=r.height+"px",i.setAttribute("data-chart-type",this.selectedType),i.setAttribute("data-chart-data",JSON.stringify(e));const t=this.renderer.createChart(this.selectedType,e,r);i.appendChild(t),this.onInsert&&this.onInsert(i)}this.popup.hide()}show(e){this.editingChart=null,this.onInsert=e,this.popup.show()}edit(e,r=!1){var s;this.editingChart=e;const i=e.getAttribute("data-chart-type"),t=e.getAttribute("data-chart-data");if(i&&t)try{const a=JSON.parse(t),n=(s=this.popup.getElement())==null?void 0:s.querySelector(`[data-type="${i}"]`);n&&n.classList.add("selected"),this.selectedType=i,this.updateEditor(i),setTimeout(()=>{this.currentEditor.setData(a),this.updatePreview(a)},100),r||this.popup.show()}catch(a){console.error("Failed to parse chart data:",a)}}redrawChart(e,r,i,t){const s=this.renderer.createChart(r,i,t);e.innerHTML="",e.appendChild(s)}createDimensionsSelector(){const e=o.createContainer("dimensions-selector flex gap-4 mb-4"),r=o.createContainer("flex flex-col gap-1"),i=o.createSpan("text-sm font-medium text-gray-700");i.textContent=this.editor.t("Width");const t=document.createElement("input");t.type="number",t.min="200",t.max="1200",t.step="50",t.value=this.chartWidth.toString(),t.className="dimension-input px-2 py-1 rounded border border-gray-300 text-sm",t.onchange=c=>{this.chartWidth=parseInt(c.target.value),this.schedulePreviewUpdate(this.currentEditor.getData())},r.appendChild(i),r.appendChild(t);const s=o.createContainer("flex flex-col gap-1"),a=o.createSpan("text-sm font-medium text-gray-700");a.textContent=this.editor.t("Height");const n=document.createElement("input");return n.type="number",n.min="150",n.max="800",n.step="50",n.value=this.chartHeight.toString(),n.className="dimension-input px-2 py-1 rounded border border-gray-300 text-sm",n.onchange=c=>{this.chartHeight=parseInt(c.target.value),this.schedulePreviewUpdate(this.currentEditor.getData())},s.appendChild(a),s.appendChild(n),e.appendChild(r),e.appendChild(s),e}createDisplaySettings(){const e=o.createContainer("display-settings flex flex-col gap-3 mb-4 p-3 bg-gray-50 rounded-lg"),r=o.createSpan("text-sm font-medium text-gray-700 mb-2");r.textContent=this.editor.t("Display Settings"),e.appendChild(r);const i=o.createContainer("flex items-center gap-2"),t=document.createElement("input");t.type="checkbox",t.checked=this.showLegend,t.className="setting-checkbox",t.onchange=p=>{this.showLegend=p.target.checked,this.schedulePreviewUpdate(this.currentEditor.getData())};const s=o.createSpan("text-sm");s.textContent=this.editor.t("Show Legend"),i.appendChild(t),i.appendChild(s);const a=o.createContainer("flex items-center gap-2"),n=document.createElement("input");n.type="checkbox",n.checked=this.showGrid,n.className="setting-checkbox",n.onchange=p=>{this.showGrid=p.target.checked,this.schedulePreviewUpdate(this.currentEditor.getData())};const c=o.createSpan("text-sm");c.textContent=this.editor.t("Show Grid"),a.appendChild(n),a.appendChild(c);const d=o.createContainer("flex items-center gap-2"),h=o.createSpan("text-sm");h.textContent=this.editor.t("Bar/Area Mode");const u=document.createElement("select");u.className="mode-select px-2 py-1 rounded border border-gray-300 text-sm",["default","stacked","grouped"].forEach(p=>{const m=document.createElement("option");m.value=p,m.textContent=this.editor.t(p.charAt(0).toUpperCase()+p.slice(1)),u.appendChild(m)}),u.value=this.chartMode,u.onchange=p=>{this.chartMode=p.target.value,this.schedulePreviewUpdate(this.currentEditor.getData())},d.appendChild(h),d.appendChild(u);const C=o.createContainer("flex items-center gap-2"),y=o.createSpan("text-sm");y.textContent=this.editor.t("Orientation");const x=document.createElement("select");return x.className="orientation-select px-2 py-1 rounded border border-gray-300 text-sm",["vertical","horizontal"].forEach(p=>{const m=document.createElement("option");m.value=p,m.textContent=this.editor.t(p.charAt(0).toUpperCase()+p.slice(1)),x.appendChild(m)}),x.value=this.chartOrientation,x.onchange=p=>{this.chartOrientation=p.target.value,this.schedulePreviewUpdate(this.currentEditor.getData())},C.appendChild(y),C.appendChild(x),e.appendChild(i),e.appendChild(a),e.appendChild(d),e.appendChild(C),e}destroy(){this.previewTimeout&&(window.clearTimeout(this.previewTimeout),this.previewTimeout=null),this.popup.destroy(),this.currentEditor&&this.currentEditor.destroy(),this.editor=null,this.popup=null,this.renderer=null,this.currentEditor=null,this.onInsert=null,this.editingChart=null}}exports.ChartMenu=A;