mini-canvas-editor
Version:
Canvas editor component for JavaScript application. Easy to integrate and use.
2 lines (1 loc) • 30.3 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("mini-canvas-core")):"function"==typeof define&&define.amd?define(["exports","mini-canvas-core"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).miniCanvasEditor={},e.miniCanvasCore)}(this,(function(e,t){"use strict";var s;function i(e,t,s,i){return new(s||(s=Promise))((function(n,o){function a(e){try{c(i.next(e))}catch(e){o(e)}}function r(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?n(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(a,r)}c((i=i.apply(e,t||[])).next())}))}e.EditorMode=void 0,(s=e.EditorMode||(e.EditorMode={})).select="select",s.rect="rect",s.brush="brush",s.textbox="textbox","function"==typeof SuppressedError&&SuppressedError;class n{static attrs(e,t){Object.keys(t).forEach((s=>{const i=t[s];e.setAttribute(s,"string"==typeof i?i:i.toString())}))}static element(e,t){const s=document.createElement(e);return t&&n.attrs(s,t),s}static div(e){return n.element("div",e)}}const o="http://www.w3.org/2000/svg";class a{static createSvg(e,t){const s=document.createElementNS(o,"svg");s.setAttribute("viewBox","0 -960 960 960"),s.classList.add(t);const i=document.createElementNS(o,"path");return i.setAttribute("d",e),s.appendChild(i),s}}a.cursor="m320-410 79-110h170L320-716v306ZM551-80 406-392 240-160v-720l560 440H516l144 309-109 51ZM399-520Z",a.rect="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0 0v-560 560Z",a.eye="M480-320q75 0 127.5-52.5T660-500q0-75-52.5-127.5T480-680q-75 0-127.5 52.5T300-500q0 75 52.5 127.5T480-320Zm0-72q-45 0-76.5-31.5T372-500q0-45 31.5-76.5T480-608q45 0 76.5 31.5T588-500q0 45-31.5 76.5T480-392Zm0 192q-146 0-266-81.5T40-500q54-137 174-218.5T480-800q146 0 266 81.5T920-500q-54 137-174 218.5T480-200Zm0-300Zm0 220q113 0 207.5-59.5T832-500q-50-101-144.5-160.5T480-720q-113 0-207.5 59.5T128-500q50 101 144.5 160.5T480-280Z",a.eyeOff="m644-428-58-58q9-47-27-88t-93-32l-58-58q17-8 34.5-12t37.5-4q75 0 127.5 52.5T660-500q0 20-4 37.5T644-428Zm128 126-58-56q38-29 67.5-63.5T832-500q-50-101-143.5-160.5T480-720q-29 0-57 4t-55 12l-62-62q41-17 84-25.5t90-8.5q151 0 269 83.5T920-500q-23 59-60.5 109.5T772-302Zm20 246L624-222q-35 11-70.5 16.5T480-200q-151 0-269-83.5T40-500q21-53 53-98.5t73-81.5L56-792l56-56 736 736-56 56ZM222-624q-29 26-53 57t-41 67q50 101 143.5 160.5T480-280q20 0 39-2.5t39-5.5l-36-38q-11 3-21 4.5t-21 1.5q-75 0-127.5-52.5T300-500q0-11 1.5-21t4.5-21l-84-82Zm319 93Zm-151 75Z",a.locked="M240-80q-33 0-56.5-23.5T160-160v-400q0-33 23.5-56.5T240-640h40v-80q0-83 58.5-141.5T480-920q83 0 141.5 58.5T680-720v80h40q33 0 56.5 23.5T800-560v400q0 33-23.5 56.5T720-80H240Zm0-80h480v-400H240v400Zm240-120q33 0 56.5-23.5T560-360q0-33-23.5-56.5T480-440q-33 0-56.5 23.5T400-360q0 33 23.5 56.5T480-280ZM360-640h240v-80q0-50-35-85t-85-35q-50 0-85 35t-35 85v80ZM240-160v-400 400Z",a.close="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z",a.text="M420-160v-520H200v-120h560v120H540v520H420Z",a.image="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z",a.brush="M240-120q-45 0-89-22t-71-58q26 0 53-20.5t27-59.5q0-50 35-85t85-35q50 0 85 35t35 85q0 66-47 113t-113 47Zm0-80q33 0 56.5-23.5T320-280q0-17-11.5-28.5T280-320q-17 0-28.5 11.5T240-280q0 23-5.5 42T220-202q5 2 10 2h10Zm230-160L360-470l358-358q11-11 27.5-11.5T774-828l54 54q12 12 12 28t-12 28L470-360Zm-190 80Z",a.erase="M690-240h190v80H610l80-80Zm-500 80-85-85q-23-23-23.5-57t22.5-58l440-456q23-24 56.5-24t56.5 23l199 199q23 23 23 57t-23 57L520-160H190Zm296-80 314-322-198-198-442 456 64 64h262Zm-6-240Z",a.arrowUp="M440-160v-487L216-423l-56-57 320-320 320 320-56 57-224-224v487h-80Z",a.arrowDown="M440-800v487L216-537l-56 57 320 320 320-320-56-57-224 224v-487h-80Z",a.menu="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z";class r{constructor(){this.listeners=[],this.forward=e=>{this.listeners.length>0&&this.listeners.forEach((t=>t(e)))}}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);if(!(t>=0))throw new Error("Unknown listener");this.listeners.splice(t,1)}count(){return this.listeners.length}}function c(e,t,s){const i=new r,o=n.element("span",{class:`mce-icon-button mce-icon-button-${s}`,title:t}),c=a.createSvg(e,"mce-icon-button-icon"),h=c.querySelector("path");return o.appendChild(c),o.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),i.forward()}),!1),{view:o,onClicked:i,setIcon(e){h.setAttribute("d",e)}}}class h{static create(e,t,s,i){var o;const r=document.createElement("div");r.className="mce-layers-panel-item";const d=c(l(t),"Toggle visibility","sm"),u=c(a.close,"Delete layer","sm");let v,p;const b=n.div({class:"mce-layers-panel-item-label"}),m=n.element("input",{class:"mce-layers-panel-item-label-input"});m.readOnly=!0,m.value=null!==(o=t.get("label"))&&void 0!==o?o:t.type,b.appendChild(m),r.appendChild(d.view),r.appendChild(b),i||(v=c(a.arrowUp,"Move layer up","sm"),r.appendChild(v.view)),s||(p=c(a.arrowDown,"Move layer down","sm"),r.appendChild(p.view)),r.appendChild(u.view);const g=new h(r,e,t,m,d);return r.addEventListener("click",g.onItemClicked,!1),m.addEventListener("input",g.onLabelChanged,!1),d.onClicked.subscribe(g.onVisibilityClicked),null==v||v.onClicked.subscribe(g.onMoveUpClicked),null==p||p.onClicked.subscribe(g.onMoveDownClicked),u.onClicked.subscribe(g.onDeleteClicked),g}constructor(e,t,s,i,n){this.view=e,this.state=t,this.object=s,this.labelInput=i,this.visibilityButton=n,this.isSelected=!1,this.onItemClicked=e=>{e.preventDefault(),e.stopPropagation(),this.state.selectObject(this.object)},this.onVisibilityClicked=()=>{this.object.selectable&&this.object.visible?(this.object.visible=!0,this.object.selectable=!1,this.state.canvas.getActiveObject()===this.object&&this.state.canvas.discardActiveObject()):this.object.visible&&!this.object.selectable?(this.object.visible=!1,this.object.selectable=!0):(this.object.visible=!0,this.object.selectable=!0),this.visibilityButton.setIcon(l(this.object)),this.state.canvas.requestRenderAll(),this.state.onPropertiesChanged.forward(this.object)},this.onMoveUpClicked=()=>{this.state.canvas.bringObjectForward(this.object),this.state.onLayerOrderChanged.forward()},this.onMoveDownClicked=()=>{this.state.canvas.sendObjectBackwards(this.object),this.state.onLayerOrderChanged.forward()},this.onDeleteClicked=()=>{this.state.canvas.remove(this.object)},this.onLabelChanged=()=>{this.object.set("label",this.labelInput.value),this.state.onPropertiesChanged.forward(this.object)}}setIsSelected(e){this.isSelected=e,this.labelInput.readOnly=!e,this.view.classList.toggle("mce-selected",e)}}function l(e){if(!e.selectable){if(!e.visible)throw new Error("Unsupported state");return a.locked}return e.visible?a.eye:a.eyeOff}function d(e,t){const s=n.div({class:"mce-panel"}),i=n.div({class:"mce-panel-tabs"}),o=n.div({class:"mce-panel-tab"});o.innerText=e,i.appendChild(o);const a=n.div({class:"mce-panel-body"});return a.className="mce-panel-body",a.appendChild(t),s.appendChild(i),s.appendChild(a),{view:s}}class u{static create(e){const t=document.createElement("div");t.className="mce-layers-list";const s=d("Layers",t),i=new u(s.view,e,t);return e.canvas.on("object:added",i.reloadList),e.canvas.on("object:removed",i.reloadList),e.canvas.on("selection:cleared",i.reloadSelection),e.canvas.on("selection:created",i.reloadSelection),e.canvas.on("selection:updated",i.reloadSelection),e.onLayerOrderChanged.subscribe(i.reloadList),i.reloadList(),i}constructor(e,t,s){this.view=e,this.state=t,this.list=s,this.layers=[],this.reloadList=()=>{for(;this.list.firstChild;)this.list.removeChild(this.list.firstChild);this.state.forEachObject(((e,t,s)=>{const i=0===t,n=h.create(this.state,e,i,s);this.layers.push(n),this.list.firstChild?this.list.insertBefore(n.view,this.list.firstChild):this.list.appendChild(n.view)})),this.reloadSelection()},this.reloadSelection=()=>{const e=this.state.canvas.getActiveObjects();for(const t of this.layers)t.setIsSelected(e.includes(t.object))}}}class v{static create(e,t,s){const i=new v(e,s,t);for(const e of t)s.on(e,i.onExternalChanged);return i}constructor(e,t,s){this.state=e,this.object=t,this.events=s,this.accessors=[],this.onChanged=new r,this.onExternalChanged=()=>{for(const e of this.accessors){const t=e.getValue();t!==e.lastValue&&e.onExternalChanged.forward(t)}}}bind(e,t){const s={onExternalChanged:new r,lastValue:e(this.object),getValue:()=>e(this.object),setValue:e=>{t(this.object,e),s.lastValue=e,this.state.canvas.requestRenderAll(),this.onChanged.forward()}};return this.accessors.push(s),s}destroy(){for(const e of this.events)this.object.off(e,this.onExternalChanged)}}function p(e,t){const s=n.div({class:"mce-prop-simple"}),i=n.div({class:"mce-prop-simple-label"});i.innerText=e;const o=n.div({class:"mce-prop-simple-body"});return s.appendChild(i),s.appendChild(o),o.appendChild(t),{view:s}}function b(e,t,s){var i;const o=null!==(i=null==s?void 0:s.decimals)&&void 0!==i?i:1,a=n.element("input",{class:"mce-prop-number-input",type:"number",value:t.getValue().toFixed(o)});return s&&(s.step&&(a.step=s.step.toString()),"number"==typeof s.min&&a.setAttribute("min",String(s.min)),"number"==typeof s.max&&a.setAttribute("max",String(s.max))),a.addEventListener("input",(function(){const e=Number(a.value);t.setValue(e)}),!1),t.onExternalChanged.subscribe((function(e){a.value=e.toFixed(o)})),{view:p(e,a).view,destroy:function(){}}}function m(e){const t=n.div({class:"mce-prop-row"});for(const s of e){const e=n.div({class:"mce-prop-col"});e.appendChild(s.view),t.appendChild(e)}return{view:t,destroy:function(){e.forEach((e=>e.destroy()))}}}function g(e){const t=n.div({class:"mce-prop-rows"});for(const s of e)t.appendChild(s.view);return{view:t,destroy:function(){e.forEach((e=>e.destroy()))}}}function w(e,t){const s=[...t,m([b("X",e.bind((e=>e.left),((e,t)=>e.set("left",t)))),b("Y",e.bind((e=>e.top),((e,t)=>e.set("top",t))))]),m([b("Angle",e.bind((e=>e.angle),((e,t)=>e.set("angle",t))))]),m([b("Opacity",e.bind((e=>Math.round(100*e.opacity)),((e,t)=>e.set("opacity",Math.min(100,Math.max(t,0))/100))),{step:2,decimals:0,min:0,max:100})])];return{view:g(s).view,destroy:function(){s.forEach((e=>e.destroy()))}}}function f(e,t,s){const i=s.getValue(),o=n.element("select",{class:"mce-prop-choice"});o.addEventListener("change",(function(){const e=a[o.selectedIndex];s.setValue(e)}),!1);const a=Object.values(t),r=Object.keys(t).map((e=>{const s=n.element("option",{value:e});return s.text=e,t[e]===i&&(s.selected=!0),o.appendChild(s),s}));return s.onExternalChanged.subscribe((function(e){const t=a.indexOf(e);if(t>=0)for(let e=0;e<r.length;e++)r[e].selected=e===t})),{view:p(e,o).view,destroy:function(){}}}function C(e,t){const s=n.element("input",{class:"mce-prop-color-input",type:"color",value:t.getValue()||"#000"});return s.addEventListener("input",(function(){t.setValue(s.value)}),!1),t.onExternalChanged.subscribe((function(e){s.value=e})),{view:p(e,s).view,destroy:function(){}}}class y{static create(e,s){switch(e){case"rect":return function(e){const t=m([b("W",e.bind((e=>e.getScaledWidth()),((e,t)=>{e.set("width",t),e.set("scaleX",1)}))),b("H",e.bind((e=>e.getScaledHeight()),((e,t)=>{e.set("height",t),e.set("scaleY",1)})))]),s=m([b("Radius",e.bind((e=>e.rx),((e,t)=>{e.set("rx",t),e.set("ry",t)})))]),i=m([C("Fill",e.bind((e=>e.fill),((e,t)=>e.set("fill",t))))]),n=m([b("SW",e.bind((e=>e.strokeWidth),((e,t)=>e.set("strokeWidth",t)))),C("SC",e.bind((e=>e.stroke),((e,t)=>e.set("stroke",t))))]);return w(e,[t,s,i,n])}(s);case"circle":default:return function(e){return w(e,[])}(s);case"textbox":return function(e){const s=m([b("Font size",e.bind((e=>e.fontSize),((e,t)=>e.set("fontSize",t))))]),i=m([b("Line height",e.bind((e=>e.lineHeight),((e,t)=>e.set("lineHeight",t))),{step:.05,decimals:2})]),n=m([C("Color",e.bind((e=>e.fill),((e,t)=>e.set("fill",t))))]),o=m([f("Text align",{Left:"left",Center:"center",Right:"right",Justify:"justify"},e.bind((e=>e.textAlign),((e,t)=>e.set("textAlign",t))))]),a=m([f("Vertical align",{Top:t.MceVerticalAlign.top,Middle:t.MceVerticalAlign.middle,Bottom:t.MceVerticalAlign.bottom},e.bind((e=>e.verticalAlign),((e,t)=>e.set("verticalAlign",t))))]),r=m([f("Font",{Arial:"arial",Verdana:"verdana",Tahoma:"tahoma",Georgia:"georgia","Courier New":"courier new",Serif:"serif"},e.bind((e=>e.fontFamily),((e,t)=>e.set("fontFamily",t))))]),c=m([f("Weight",{Bold:"bold",Normal:"normal"},e.bind((e=>e.fontWeight),((e,t)=>e.set("fontWeight",t))))]),h=m([f("Bg",{Off:t.MceTextBackground.none,Behind:t.MceTextBackground.behind},e.bind((e=>e.textBackground),((e,t)=>e.set("textBackground",t)))),C("Color",e.bind((e=>e.textBackgroundFill),((e,t)=>e.set("textBackgroundFill",t))))]),l=m([b("SW",e.bind((e=>e.strokeWidth),((e,t)=>e.set("strokeWidth",t))),{min:0}),C("SC",e.bind((e=>e.stroke),((e,t)=>e.set("stroke",t))))]);return w(e,[s,i,n,o,a,r,c,h,l])}(s);case"image":return function(e){const t=m([b("W",e.bind((e=>e.getScaledWidth()),((e,t)=>{const s=t/e.getOriginalSize().width;e.set("scaleX",s)}))),b("H",e.bind((e=>e.getScaledHeight()),((e,t)=>{const s=t/e.getOriginalSize().height;e.set("scaleY",s)})))]);return w(e,[t])}(s)}}}class k{static create(e,t){const s=n.div({class:"mce-properties-editor"}),i=v.create(e,["modified","scaling"],t);i.onChanged.subscribe((()=>e.onPropertiesChanged.forward(t)));const o=y.create(t.type,i);return s.appendChild(o.view),new k(s,i,o)}constructor(e,t,s){this.view=e,this.manager=t,this.editor=s}destroy(){this.manager.destroy(),this.editor.destroy()}}class M{static create(e){const t=v.create(e,[],e.canvas);t.onChanged.subscribe((()=>e.onPropertiesChanged.forward(e.canvas)));const s=n.div({class:"mce-properties-editor"}),i=g([m([b("Width",t.bind((e=>e.workspaceWidth),((e,t)=>{e.workspaceBackground.set("width",t),e.workspaceWidth=t})),{decimals:0})]),m([b("Height",t.bind((e=>e.workspaceHeight),((e,t)=>{e.workspaceBackground.set("height",t),e.workspaceHeight=t})),{decimals:0})])]);return s.appendChild(i.view),new M(s)}constructor(e){this.view=e}destroy(){}}class j{static create(e){const t=document.createElement("div"),s=d("Properties",t),i=new j(s.view,e,t);return e.canvas.on("selection:cleared",i.onSelectionUpdated),e.canvas.on("selection:updated",i.onSelectionUpdated),e.canvas.on("selection:created",i.onSelectionUpdated),i.refresh(),i}constructor(e,t,s){this.view=e,this.state=t,this.container=s,this.onSelectionUpdated=()=>{this.refresh()}}refresh(){const e=this.state.canvas.getActiveObjects();if(this.component&&this.container.removeChild(this.component.view),1===e.length){const t=e[0];this.component=k.create(this.state,t)}else this.component=M.create(this.state);this.container.appendChild(this.component.view)}}class x{static create(e,t){const s=n.div({class:"mce-sidebar"}),i=n.div({class:"mce-sidebar-switch"});i.appendChild(a.createSvg(a.menu,"mce-sidebar-switch-icon"));const o=n.div({class:"mce-sidebar-body"});if(!1!==t.properties){const t=j.create(e);o.appendChild(t.view)}if(!1!==t.layers){const t=u.create(e);o.appendChild(t.view)}s.appendChild(i),s.appendChild(o);const r=new x(s);return i.addEventListener("click",r.onSwitchClicked,!1),r}constructor(e){this.view=e,this.onSwitchClicked=()=>{this.view.classList.toggle("mce-visible")}}}class q{constructor(e,t,s,i){this.canvas=e,this.mode=t,this.configuration=s,this.container=i,this.onModeChanged=new r,this.onZoomChanged=new r,this.onLayerOrderChanged=new r,this.onPropertiesChanged=new r,this.onBrushConfigurationChanged=new r,this.brush=Object.assign({brushSize:10,brushColor:"#ff0000"},this.configuration.brush||{}),this.rect=Object.assign({fillColor:"#ff0000"},this.configuration.rect||{})}center(){const e=Math.min(1,this.container.clientWidth/this.canvas.workspaceWidth,this.container.clientHeight/this.canvas.workspaceHeight),s=this.canvas.workspaceWidth*e,i=this.canvas.workspaceHeight*e,n=this.container.clientWidth/2-s/2,o=this.container.clientHeight/2-i/2;this.canvas.setZoom(e),this.canvas.absolutePan(new t.Point(-n,-o)),this.onZoomChanged.forward()}add(e){this.canvas.add(e),this.canvas.requestRenderAll()}selectObject(e){this.canvas.discardActiveObject(),this.canvas.setActiveObject(e),this.canvas.renderAll()}forEachObject(e){const t=this.canvas.getWorkspaceObjects();for(let s=0;s<t.length;s++)e(t[s],s,s+1===t.length)}disableSelection(){this.canvas.selection=!1;const e=new Map;return this.forEachObject((t=>{e.set(t,t.selectable),t.selectable&&t.set("selectable",!1)})),new S(e)}setMode(e){this.mode=e,this.onModeChanged.forward(e)}}class S{constructor(e){this.map=e}revert(){this.map.forEach(((e,t)=>t.set("selectable",e)))}}class E{constructor(e){this.state=e}init(){this.state.canvas.setCursor("move"),this.state.canvas.selection=!0}destroy(){}}class T{static create(e,t){const s=e.disableSelection(),i=new T(e,s,t);return e.canvas.on("mouse:down",i.onDown),e.canvas.on("mouse:move",i.onMove),e.canvas.on("mouse:up",i.onUp),e.canvas.setCursor("crosshair"),i}constructor(e,t,s){this.state=e,this.selectionReverter=t,this.objectFactory=s,this.object=null,this.origX=0,this.origY=0,this.onFinished=new r,this.onDown=e=>{e.e.preventDefault(),e.e.stopPropagation(),this.state.canvas.discardActiveObject();const t=this.state.canvas.getPointer(e.e);this.origX=Math.floor(t.x),this.origY=Math.floor(t.y),this.object=this.objectFactory(),this.object.set("left",this.origX),this.object.set("top",this.origX),this.state.add(this.object)},this.onMove=e=>{if(!this.object)return;const t=this.state.canvas.getPointer(e.e),s=Math.floor(t.x-this.origX),i=Math.floor(t.y-this.origY),n=Math.abs(s),o=Math.abs(i);this.object.set({left:s>0?this.origX:this.origX+s,top:i>0?this.origY:this.origY+i,width:n,height:o}),this.state.canvas.renderAll()},this.onUp=()=>{this.object&&(this.onFinished.forward(this.object),this.object=null)}}destroy(){this.state.canvas.off("mouse:down",this.onDown),this.state.canvas.off("mouse:move",this.onMove),this.state.canvas.off("mouse:up",this.onUp),this.selectionReverter.revert()}}class Z{constructor(e){this.state=e}init(){this.painter=T.create(this.state,(()=>new t.MceRect({fill:this.state.rect.fillColor,stroke:this.state.rect.fillColor,strokeWidth:0}))),this.painter.onFinished.subscribe((t=>{this.state.canvas.setActiveObject(t),this.state.setMode(e.EditorMode.select)}))}destroy(){this.painter&&(this.painter.destroy(),this.painter=void 0)}}class L{constructor(e){this.state=e}init(){this.painter=T.create(this.state,(()=>new t.Rect({fill:"transparent",stroke:"#26aa5a",strokeWidth:1}))),this.painter.onFinished.subscribe((s=>{const i=Math.max(s.getScaledHeight(),10),n=Math.min(i,20),o=new t.MceTextbox("Text",{left:s.left,top:s.top,width:s.getScaledWidth(),maxHeight:i,fontSize:n,fill:"#000000"});this.state.canvas.remove(s),this.state.add(o),this.state.canvas.setActiveObject(o),this.state.setMode(e.EditorMode.select)}))}destroy(){this.painter&&(this.painter.destroy(),this.painter=void 0)}}class O{constructor(e){this.state=e,this.brush=new t.PencilBrush(this.state.canvas),this.reloadBrush=()=>{this.brush.width=this.state.brush.brushSize,this.brush.color=this.state.brush.brushColor}}init(){this.reloadBrush(),this.state.canvas.freeDrawingBrush=this.brush,this.state.canvas.isDrawingMode=!0,this.state.canvas.on("path:created",(e=>{const s=e.path;this.state.canvas.remove(s);const i=new t.McePath(s.path,s);this.state.canvas.add(i)})),this.state.onBrushConfigurationChanged.subscribe(this.reloadBrush)}destroy(){this.state.canvas.freeDrawingBrush=void 0,this.state.canvas.isDrawingMode=!1,this.state.onBrushConfigurationChanged.unsubscribe(this.reloadBrush)}}class A{static get(t,s){switch(t){case e.EditorMode.select:return new E(s);case e.EditorMode.rect:return new Z(s);case e.EditorMode.brush:return new O(s);case e.EditorMode.textbox:return new L(s)}}}function B(){const e=n.div({class:"mce-workspace"}),t=document.createElement("canvas");return t.width=1,t.height=1,e.appendChild(t),{view:e,nativeCanvas:t}}const W={imageSmoothingEnabled:!0,preserveObjectStacking:!0,controlsAboveOverlay:!0,enableRetinaScaling:!0,skipOffscreen:!0};class H{static createBlank(e,s,i){const{view:n,nativeCanvas:o}=B(),a=t.MceCanvas.createBlank(e,s,o,W);return H.create(n,a,i)}static createFromJSON(e,s){return i(this,void 0,void 0,(function*(){const{view:i,nativeCanvas:n}=B(),o=yield t.MceCanvas.createFromJSON(e,n,W);return H.create(i,o,s)}))}static create(t,s,i){const n=i.initialMode||e.EditorMode.select,o=new q(s,n,i,t),a=new H(t,s,o);return s.on("mouse:wheel",a.onWheel),o.onModeChanged.subscribe(a.reloadMode),a.reloadMode(),a}constructor(e,s,i){this.view=e,this.canvas=s,this.state=i,this.reloadLayout=()=>{if(!this.view.parentElement)throw new Error("Workspace is not attached to the DOM");this.canvas.setWidth(this.view.clientWidth),this.canvas.setHeight(this.view.clientHeight)},this.onWheel=e=>{e.e.preventDefault(),e.e.stopPropagation();const s=e.e.deltaY;let i=this.canvas.getZoom();i*=Math.pow(.999,s),i>20&&(i=20),i<.01&&(i=.01),this.canvas.zoomToPoint(new t.Point(e.e.offsetX,e.e.offsetY),i),this.state.onZoomChanged.forward()},this.reloadMode=()=>{this.currentMode&&this.currentMode.destroy(),this.currentMode=A.get(this.state.mode,this.state),this.currentMode.init()}}startAutoLayout(e){setTimeout((()=>{this.reloadLayout(),e&&this.state.center()})),window.addEventListener("resize",this.reloadLayout,!1)}destroy(){return i(this,void 0,void 0,(function*(){this.currentMode&&this.currentMode.destroy(),window.removeEventListener("resize",this.reloadLayout,!1),yield this.canvas.dispose()}))}}class F{static create(e,t,s){const i=n.div({class:"mce-toolbox-item",title:t});i.appendChild(a.createSvg(e,"mce-toolbox-item-icon"));const o=new F(i,s);return i.addEventListener("click",(e=>{e.preventDefault(),o.onClicked.forward(o)}),!1),o}constructor(e,t){this.view=e,this.mode=t,this.onClicked=new r}setIsSelected(e){this.view.classList.toggle("mce-selected",e)}}class P{static create(e){const t=n.div({class:"mce-toolbox-item",title:"Zoom / Center"}),s=n.div({class:"mce-toolbox-item-zoom"});t.appendChild(s);const i=new P(t,s,e);return t.addEventListener("click",i.onClick,!1),i.reloadZoom(),e.onZoomChanged.subscribe(i.reloadZoom),i}constructor(e,t,s){this.view=e,this.text=t,this.state=s,this.reloadZoom=()=>{const e=Math.round(100*this.state.canvas.getZoom());this.text.innerText=`${e}%`},this.onClick=()=>{this.state.center(),this.reloadZoom()}}}function I(e){return i(this,void 0,void 0,(function*(){const s=yield new Promise((e=>{const t=document.createElement("input");t.type="file",t.accept="image/*",t.addEventListener("change",(()=>{if(t.files&&t.files.length>0){const s=t.files[0],i=new FileReader;i.onload=()=>{const t=new Image;t.onload=()=>{e(t)},t.src=i.result},i.readAsDataURL(s)}else e(null)})),t.click()}));if(s){const i=Math.max(s.width/e.canvas.workspaceWidth,s.height/e.canvas.workspaceHeight),n=new t.MceImage(s,{left:0,top:0,width:s.width,height:s.height,scaleX:1/i,scaleY:1/i});e.add(n)}}))}class D{static create(t,s){const i=n.div({class:"mce-toolbox"}),o=n.div({class:"mce-toolbox-top"}),r=n.div({class:"mce-toolbox-bottom"});i.appendChild(o),i.appendChild(r);let c=null;const h=[F.create(a.cursor,"Select",e.EditorMode.select),!1!==s.rect&&F.create(a.rect,"Rect",e.EditorMode.rect),!1!==s.textbox&&F.create(a.text,"Textbox",e.EditorMode.textbox),!1!==s.brush&&F.create(a.brush,"Brush",e.EditorMode.brush),!1!==s.image&&(c=F.create(a.image,"Image",null))].filter(Boolean),l=new D(i,t,h);for(const e of h)o.appendChild(e.view),e.mode&&e.onClicked.subscribe(l.onItemClicked);c&&c.onClicked.subscribe(l.onOpenImageClicked);const d=P.create(t);return r.appendChild(d.view),l.reloadSelection(),t.onModeChanged.subscribe(l.reloadSelection),l}constructor(e,t,s){this.view=e,this.state=t,this.items=s,this.onItemClicked=e=>{e.mode&&this.state.setMode(e.mode)},this.onOpenImageClicked=()=>i(this,void 0,void 0,(function*(){I(this.state)})),this.reloadSelection=()=>{this.items.forEach((e=>{e.setIsSelected(e.mode===this.state.mode)}))}}}class z{static create(e){const t=new z(e);return window.addEventListener("resize",t.reload,!1),t.reload(),t}constructor(e){this.root=e,this.reload=()=>{this.root.clientWidth<400?this.root.classList.add("mce-mobile"):this.root.classList.remove("mce-mobile")}}destroy(){window.removeEventListener("resize",this.reload,!1)}}function V(e,t){const s=new r,i=n.element("span",{class:"mce-toolbar-label"});i.textContent=e;const o=n.element("input",{class:"mce-toolbar-color-input",type:"color",value:t});o.addEventListener("change",(function(){s.forward(o.value)}),!1);const a=n.div({class:"mce-toolbar-item"});return a.appendChild(i),a.appendChild(o),{view:a,onChanged:s}}class N{static create(e){const t=n.div({class:"mce-toolbar-brush"}),s=V("Fill",e.rect.fillColor);t.appendChild(s.view);const i=new N(t,e);return s.onChanged.subscribe(i.onFillColorChanged),i}constructor(e,t){this.view=e,this.state=t,this.onFillColorChanged=e=>{this.state.brush.brushColor=e,this.state.onBrushConfigurationChanged.forward()}}destroy(){}}class U{static create(e){const t=n.div({class:"mce-toolbar-brush"}),s=function(e,t){const s=new r,i=n.element("span",{class:"mce-toolbar-label"});i.textContent=e;const o=n.element("input",{class:"mce-toolbar-number-input",type:"number",min:"0.5",step:"0.5",value:String(t)});o.addEventListener("change",(function(){const e=Number(o.value);s.forward(e)}),!1);const a=n.div({class:"mce-toolbar-item"});return a.appendChild(i),a.appendChild(o),{view:a,onChanged:s}}("Size",e.brush.brushSize),i=V("Color",e.brush.brushColor);t.appendChild(s.view),t.appendChild(i.view);const o=new U(t,e);return s.onChanged.subscribe(o.onBrushSizeChanged),i.onChanged.subscribe(o.onBrushColorChanged),o}constructor(e,t){this.view=e,this.state=t,this.onBrushSizeChanged=e=>{this.state.brush.brushSize=e,this.state.onBrushConfigurationChanged.forward()},this.onBrushColorChanged=e=>{this.state.brush.brushColor=e,this.state.onBrushConfigurationChanged.forward()}}destroy(){}}class R{static create(t,s){switch(t){case e.EditorMode.rect:return N.create(s);case e.EditorMode.brush:return U.create(s)}return null}}class X{static create(e){const t=n.div({class:"mce-toolbar"}),s=new X(t,e);return e.onModeChanged.subscribe(s.reload),s.reload(),s}constructor(e,t){this.view=e,this.state=t,this.current=null,this.reload=()=>{this.current&&(this.view.removeChild(this.current.view),this.current=null);const e=R.create(this.state.mode,this.state);e?(this.current=e,this.view.appendChild(this.current.view),this.view.classList.remove("mce-hidden")):this.view.classList.add("mce-hidden")}}destroy(){this.current&&this.current.destroy()}}class Y{static createBlank(e,t,s,i){const n=H.createBlank(t,s,i);return Y.create(e,n,i)}static createFromImage(e,s,i,n){var o,a,r;const c=null!==(o=i.workspaceWidth)&&void 0!==o?o:s.width,h=null!==(a=i.workspaceHeight)&&void 0!==a?a:s.height,l=Y.createBlank(e,c,h,n),d={width:s.width,height:s.height,selectable:null===(r=i.selectable)||void 0===r||r};if(i.fitToWorkspace){const e=Math.max(c/s.width,h/s.height);d.left=(c-s.width*e)/2,d.top=(h-s.height*e)/2,d.scaleX=e,d.scaleY=e}const u=new t.MceImage(s,d);if(l.add(u),!1===i.selectable&&i.select)throw new Error("Cannot select an image that is not selectable");return!1!==i.selectable&&i.select&&l.state.canvas.setActiveObject(u),l}static createFromJSON(e,t,s){return i(this,void 0,void 0,(function*(){const i=yield H.createFromJSON(e,s);return Y.create(t,i,s)}))}static create(e,t,s){const i=n.div({class:"mce-editor"}),o=t.state,a=D.create(o,s),r=X.create(o);if(i.appendChild(a.view),i.appendChild(r.view),i.appendChild(t.view),!1!==s.sidebar){const e=x.create(o,"object"==typeof s.sidebar?s.sidebar:{});i.appendChild(e.view)}e.appendChild(i),t.startAutoLayout(!0);const c=z.create(i),h=new Y(i,t,o,c);return o.canvas.on("object:added",h.onAnyChange),o.canvas.on("object:modified",h.onAnyChange),o.canvas.on("object:moving",h.onAnyChange),o.canvas.on("object:removed",h.onAnyChange),o.canvas.on("object:resizing",h.onAnyChange),o.canvas.on("object:rotating",h.onAnyChange),o.canvas.on("object:scaling",h.onAnyChange),o.canvas.on("object:skewing",h.onAnyChange),o.canvas.on("text:changed",h.onAnyChange),o.canvas.on("text:editing:exited",h.onAnyChange),o.canvas.on("selection:cleared",h.onAnyChange),o.canvas.on("selection:created",h.onAnyChange),o.canvas.on("selection:updated",h.onAnyChange),o.onLayerOrderChanged.subscribe(h.onAnyChange),o.onPropertiesChanged.subscribe(h.onAnyChange),h}constructor(e,t,s,i){this.view=e,this.workspace=t,this.state=s,this.layoutController=i,this.onChanged=new r,this.onAnyChange=()=>{this.onChanged.forward()}}getWidth(){return this.state.canvas.workspaceWidth}getHeight(){return this.state.canvas.workspaceHeight}getWorkspaceObjects(){return this.state.canvas.getWorkspaceObjects()}add(e){this.state.add(e)}toJSON(){return this.state.canvas.toImageJSON()}cloneToStaticCanvas(){return t.MceStaticCanvas.createFromJSON(this.toJSON())}render(){const e=this.state.canvas.getZoom(),s=this.state.canvas.width,i=this.state.canvas.height,n=this.state.canvas.viewportTransform,o=this.state.canvas.getActiveObjects().map((e=>{const t=e.controls,s=e.hasBorders;return e.controls={},e.hasBorders=!1,{object:e,controls:t,hasBorders:s}}));this.state.canvas.setWidth(this.state.canvas.workspaceWidth),this.state.canvas.setHeight(this.state.canvas.workspaceHeight),this.state.canvas.setZoom(1),this.state.canvas.absolutePan(new t.Point(0,0)),this.state.canvas.workspaceBackground.visible=!1;const a=this.state.canvas.toCanvasElement(1,{left:0,top:0,width:this.state.canvas.workspaceWidth,height:this.state.canvas.workspaceHeight});return this.state.canvas.setZoom(e),this.state.canvas.setWidth(s),this.state.canvas.setHeight(i),this.state.canvas.setViewportTransform(n),this.state.canvas.workspaceBackground.visible=!0,o.forEach((({object:e,controls:t,hasBorders:s})=>{e.controls=t,e.hasBorders=s})),a}destroy(){var e;return i(this,void 0,void 0,(function*(){yield this.workspace.destroy(),this.layoutController.destroy(),null===(e=this.view.parentElement)||void 0===e||e.removeChild(this.view)}))}}e.Editor=Y}));