mini-canvas-editor
Version:
Canvas editor component for JavaScript application. Easy to integrate and use.
2 lines (1 loc) • 29.9 kB
JavaScript
import{MceVerticalAlign as e,MceTextBackground as t,Point as s,MceRect as i,Rect as n,MceTextbox as a,PencilBrush as o,McePath as r,MceCanvas as c,MceImage as h,MceStaticCanvas as l}from"mini-canvas-core";var d;function u(e,t,s,i){return new(s||(s=Promise))((function(n,a){function o(e){try{c(i.next(e))}catch(e){a(e)}}function r(e){try{c(i.throw(e))}catch(e){a(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(o,r)}c((i=i.apply(e,t||[])).next())}))}!function(e){e.select="select",e.rect="rect",e.brush="brush",e.textbox="textbox"}(d||(d={})),"function"==typeof SuppressedError&&SuppressedError;class v{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&&v.attrs(s,t),s}static div(e){return v.element("div",e)}}const p="http://www.w3.org/2000/svg";class b{static createSvg(e,t){const s=document.createElementNS(p,"svg");s.setAttribute("viewBox","0 -960 960 960"),s.classList.add(t);const i=document.createElementNS(p,"path");return i.setAttribute("d",e),s.appendChild(i),s}}b.cursor="m320-410 79-110h170L320-716v306ZM551-80 406-392 240-160v-720l560 440H516l144 309-109 51ZM399-520Z",b.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",b.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",b.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",b.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",b.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",b.text="M420-160v-520H200v-120h560v120H540v520H420Z",b.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",b.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",b.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",b.arrowUp="M440-160v-487L216-423l-56-57 320-320 320 320-56 57-224-224v487h-80Z",b.arrowDown="M440-800v487L216-537l-56 57 320 320 320-320-56-57-224 224v-487h-80Z",b.menu="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z";class m{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 g(e,t,s){const i=new m,n=v.element("span",{class:`mce-icon-button mce-icon-button-${s}`,title:t}),a=b.createSvg(e,"mce-icon-button-icon"),o=a.querySelector("path");return n.appendChild(a),n.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),i.forward()}),!1),{view:n,onClicked:i,setIcon(e){o.setAttribute("d",e)}}}class w{static create(e,t,s,i){var n;const a=document.createElement("div");a.className="mce-layers-panel-item";const o=g(f(t),"Toggle visibility","sm"),r=g(b.close,"Delete layer","sm");let c,h;const l=v.div({class:"mce-layers-panel-item-label"}),d=v.element("input",{class:"mce-layers-panel-item-label-input"});d.readOnly=!0,d.value=null!==(n=t.get("label"))&&void 0!==n?n:t.type,l.appendChild(d),a.appendChild(o.view),a.appendChild(l),i||(c=g(b.arrowUp,"Move layer up","sm"),a.appendChild(c.view)),s||(h=g(b.arrowDown,"Move layer down","sm"),a.appendChild(h.view)),a.appendChild(r.view);const u=new w(a,e,t,d,o);return a.addEventListener("click",u.onItemClicked,!1),d.addEventListener("input",u.onLabelChanged,!1),o.onClicked.subscribe(u.onVisibilityClicked),null==c||c.onClicked.subscribe(u.onMoveUpClicked),null==h||h.onClicked.subscribe(u.onMoveDownClicked),r.onClicked.subscribe(u.onDeleteClicked),u}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(f(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 f(e){if(!e.selectable){if(!e.visible)throw new Error("Unsupported state");return b.locked}return e.visible?b.eye:b.eyeOff}function C(e,t){const s=v.div({class:"mce-panel"}),i=v.div({class:"mce-panel-tabs"}),n=v.div({class:"mce-panel-tab"});n.innerText=e,i.appendChild(n);const a=v.div({class:"mce-panel-body"});return a.className="mce-panel-body",a.appendChild(t),s.appendChild(i),s.appendChild(a),{view:s}}class y{static create(e){const t=document.createElement("div");t.className="mce-layers-list";const s=C("Layers",t),i=new y(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=w.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 k{static create(e,t,s){const i=new k(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 m,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 m,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 j(e,t){const s=v.div({class:"mce-prop-simple"}),i=v.div({class:"mce-prop-simple-label"});i.innerText=e;const n=v.div({class:"mce-prop-simple-body"});return s.appendChild(i),s.appendChild(n),n.appendChild(t),{view:s}}function q(e,t,s){var i;const n=null!==(i=null==s?void 0:s.decimals)&&void 0!==i?i:1,a=v.element("input",{class:"mce-prop-number-input",type:"number",value:t.getValue().toFixed(n)});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(n)})),{view:j(e,a).view,destroy:function(){}}}function x(e){const t=v.div({class:"mce-prop-row"});for(const s of e){const e=v.div({class:"mce-prop-col"});e.appendChild(s.view),t.appendChild(e)}return{view:t,destroy:function(){e.forEach((e=>e.destroy()))}}}function S(e){const t=v.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 M(e,t){const s=[...t,x([q("X",e.bind((e=>e.left),((e,t)=>e.set("left",t)))),q("Y",e.bind((e=>e.top),((e,t)=>e.set("top",t))))]),x([q("Angle",e.bind((e=>e.angle),((e,t)=>e.set("angle",t))))]),x([q("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:S(s).view,destroy:function(){s.forEach((e=>e.destroy()))}}}function T(e,t,s){const i=s.getValue(),n=v.element("select",{class:"mce-prop-choice"});n.addEventListener("change",(function(){const e=a[n.selectedIndex];s.setValue(e)}),!1);const a=Object.values(t),o=Object.keys(t).map((e=>{const s=v.element("option",{value:e});return s.text=e,t[e]===i&&(s.selected=!0),n.appendChild(s),s}));return s.onExternalChanged.subscribe((function(e){const t=a.indexOf(e);if(t>=0)for(let e=0;e<o.length;e++)o[e].selected=e===t})),{view:j(e,n).view,destroy:function(){}}}function Z(e,t){const s=v.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:j(e,s).view,destroy:function(){}}}class L{static create(s,i){switch(s){case"rect":return function(e){const t=x([q("W",e.bind((e=>e.getScaledWidth()),((e,t)=>{e.set("width",t),e.set("scaleX",1)}))),q("H",e.bind((e=>e.getScaledHeight()),((e,t)=>{e.set("height",t),e.set("scaleY",1)})))]),s=x([q("Radius",e.bind((e=>e.rx),((e,t)=>{e.set("rx",t),e.set("ry",t)})))]),i=x([Z("Fill",e.bind((e=>e.fill),((e,t)=>e.set("fill",t))))]),n=x([q("SW",e.bind((e=>e.strokeWidth),((e,t)=>e.set("strokeWidth",t)))),Z("SC",e.bind((e=>e.stroke),((e,t)=>e.set("stroke",t))))]);return M(e,[t,s,i,n])}(i);case"circle":default:return function(e){return M(e,[])}(i);case"textbox":return function(s){const i=x([q("Font size",s.bind((e=>e.fontSize),((e,t)=>e.set("fontSize",t))))]),n=x([q("Line height",s.bind((e=>e.lineHeight),((e,t)=>e.set("lineHeight",t))),{step:.05,decimals:2})]),a=x([Z("Color",s.bind((e=>e.fill),((e,t)=>e.set("fill",t))))]),o=x([T("Text align",{Left:"left",Center:"center",Right:"right",Justify:"justify"},s.bind((e=>e.textAlign),((e,t)=>e.set("textAlign",t))))]),r=x([T("Vertical align",{Top:e.top,Middle:e.middle,Bottom:e.bottom},s.bind((e=>e.verticalAlign),((e,t)=>e.set("verticalAlign",t))))]),c=x([T("Font",{Arial:"arial",Verdana:"verdana",Tahoma:"tahoma",Georgia:"georgia","Courier New":"courier new",Serif:"serif"},s.bind((e=>e.fontFamily),((e,t)=>e.set("fontFamily",t))))]),h=x([T("Weight",{Bold:"bold",Normal:"normal"},s.bind((e=>e.fontWeight),((e,t)=>e.set("fontWeight",t))))]),l=x([T("Bg",{Off:t.none,Behind:t.behind},s.bind((e=>e.textBackground),((e,t)=>e.set("textBackground",t)))),Z("Color",s.bind((e=>e.textBackgroundFill),((e,t)=>e.set("textBackgroundFill",t))))]),d=x([q("SW",s.bind((e=>e.strokeWidth),((e,t)=>e.set("strokeWidth",t))),{min:0}),Z("SC",s.bind((e=>e.stroke),((e,t)=>e.set("stroke",t))))]);return M(s,[i,n,a,o,r,c,h,l,d])}(i);case"image":return function(e){const t=x([q("W",e.bind((e=>e.getScaledWidth()),((e,t)=>{const s=t/e.getOriginalSize().width;e.set("scaleX",s)}))),q("H",e.bind((e=>e.getScaledHeight()),((e,t)=>{const s=t/e.getOriginalSize().height;e.set("scaleY",s)})))]);return M(e,[t])}(i)}}}class O{static create(e,t){const s=v.div({class:"mce-properties-editor"}),i=k.create(e,["modified","scaling"],t);i.onChanged.subscribe((()=>e.onPropertiesChanged.forward(t)));const n=L.create(t.type,i);return s.appendChild(n.view),new O(s,i,n)}constructor(e,t,s){this.view=e,this.manager=t,this.editor=s}destroy(){this.manager.destroy(),this.editor.destroy()}}class E{static create(e){const t=k.create(e,[],e.canvas);t.onChanged.subscribe((()=>e.onPropertiesChanged.forward(e.canvas)));const s=v.div({class:"mce-properties-editor"}),i=S([x([q("Width",t.bind((e=>e.workspaceWidth),((e,t)=>{e.workspaceBackground.set("width",t),e.workspaceWidth=t})),{decimals:0})]),x([q("Height",t.bind((e=>e.workspaceHeight),((e,t)=>{e.workspaceBackground.set("height",t),e.workspaceHeight=t})),{decimals:0})])]);return s.appendChild(i.view),new E(s)}constructor(e){this.view=e}destroy(){}}class A{static create(e){const t=document.createElement("div"),s=C("Properties",t),i=new A(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=O.create(this.state,t)}else this.component=E.create(this.state);this.container.appendChild(this.component.view)}}class B{static create(e,t){const s=v.div({class:"mce-sidebar"}),i=v.div({class:"mce-sidebar-switch"});i.appendChild(b.createSvg(b.menu,"mce-sidebar-switch-icon"));const n=v.div({class:"mce-sidebar-body"});if(!1!==t.properties){const t=A.create(e);n.appendChild(t.view)}if(!1!==t.layers){const t=y.create(e);n.appendChild(t.view)}s.appendChild(i),s.appendChild(n);const a=new B(s);return i.addEventListener("click",a.onSwitchClicked,!1),a}constructor(e){this.view=e,this.onSwitchClicked=()=>{this.view.classList.toggle("mce-visible")}}}class W{constructor(e,t,s,i){this.canvas=e,this.mode=t,this.configuration=s,this.container=i,this.onModeChanged=new m,this.onZoomChanged=new m,this.onLayerOrderChanged=new m,this.onPropertiesChanged=new m,this.onBrushConfigurationChanged=new m,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),t=this.canvas.workspaceWidth*e,i=this.canvas.workspaceHeight*e,n=this.container.clientWidth/2-t/2,a=this.container.clientHeight/2-i/2;this.canvas.setZoom(e),this.canvas.absolutePan(new s(-n,-a)),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 H(e)}setMode(e){this.mode=e,this.onModeChanged.forward(e)}}class H{constructor(e){this.map=e}revert(){this.map.forEach(((e,t)=>t.set("selectable",e)))}}class F{constructor(e){this.state=e}init(){this.state.canvas.setCursor("move"),this.state.canvas.selection=!0}destroy(){}}class D{static create(e,t){const s=e.disableSelection(),i=new D(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 m,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),a=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:a}),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=D.create(this.state,(()=>new i({fill:this.state.rect.fillColor,stroke:this.state.rect.fillColor,strokeWidth:0}))),this.painter.onFinished.subscribe((e=>{this.state.canvas.setActiveObject(e),this.state.setMode(d.select)}))}destroy(){this.painter&&(this.painter.destroy(),this.painter=void 0)}}class I{constructor(e){this.state=e}init(){this.painter=D.create(this.state,(()=>new n({fill:"transparent",stroke:"#26aa5a",strokeWidth:1}))),this.painter.onFinished.subscribe((e=>{const t=Math.max(e.getScaledHeight(),10),s=Math.min(t,20),i=new a("Text",{left:e.left,top:e.top,width:e.getScaledWidth(),maxHeight:t,fontSize:s,fill:"#000000"});this.state.canvas.remove(e),this.state.add(i),this.state.canvas.setActiveObject(i),this.state.setMode(d.select)}))}destroy(){this.painter&&(this.painter.destroy(),this.painter=void 0)}}class P{constructor(e){this.state=e,this.brush=new o(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 t=e.path;this.state.canvas.remove(t);const s=new r(t.path,t);this.state.canvas.add(s)})),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 N{static get(e,t){switch(e){case d.select:return new F(t);case d.rect:return new z(t);case d.brush:return new P(t);case d.textbox:return new I(t)}}}function V(){const e=v.div({class:"mce-workspace"}),t=document.createElement("canvas");return t.width=1,t.height=1,e.appendChild(t),{view:e,nativeCanvas:t}}const U={imageSmoothingEnabled:!0,preserveObjectStacking:!0,controlsAboveOverlay:!0,enableRetinaScaling:!0,skipOffscreen:!0};class X{static createBlank(e,t,s){const{view:i,nativeCanvas:n}=V(),a=c.createBlank(e,t,n,U);return X.create(i,a,s)}static createFromJSON(e,t){return u(this,void 0,void 0,(function*(){const{view:s,nativeCanvas:i}=V(),n=yield c.createFromJSON(e,i,U);return X.create(s,n,t)}))}static create(e,t,s){const i=s.initialMode||d.select,n=new W(t,i,s,e),a=new X(e,t,n);return t.on("mouse:wheel",a.onWheel),n.onModeChanged.subscribe(a.reloadMode),a.reloadMode(),a}constructor(e,t,i){this.view=e,this.canvas=t,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 t=e.e.deltaY;let i=this.canvas.getZoom();i*=Math.pow(.999,t),i>20&&(i=20),i<.01&&(i=.01),this.canvas.zoomToPoint(new s(e.e.offsetX,e.e.offsetY),i),this.state.onZoomChanged.forward()},this.reloadMode=()=>{this.currentMode&&this.currentMode.destroy(),this.currentMode=N.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 u(this,void 0,void 0,(function*(){this.currentMode&&this.currentMode.destroy(),window.removeEventListener("resize",this.reloadLayout,!1),yield this.canvas.dispose()}))}}class Y{static create(e,t,s){const i=v.div({class:"mce-toolbox-item",title:t});i.appendChild(b.createSvg(e,"mce-toolbox-item-icon"));const n=new Y(i,s);return i.addEventListener("click",(e=>{e.preventDefault(),n.onClicked.forward(n)}),!1),n}constructor(e,t){this.view=e,this.mode=t,this.onClicked=new m}setIsSelected(e){this.view.classList.toggle("mce-selected",e)}}class R{static create(e){const t=v.div({class:"mce-toolbox-item",title:"Zoom / Center"}),s=v.div({class:"mce-toolbox-item-zoom"});t.appendChild(s);const i=new R(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 J(e){return u(this,void 0,void 0,(function*(){const t=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(t){const s=Math.max(t.width/e.canvas.workspaceWidth,t.height/e.canvas.workspaceHeight),i=new h(t,{left:0,top:0,width:t.width,height:t.height,scaleX:1/s,scaleY:1/s});e.add(i)}}))}class ${static create(e,t){const s=v.div({class:"mce-toolbox"}),i=v.div({class:"mce-toolbox-top"}),n=v.div({class:"mce-toolbox-bottom"});s.appendChild(i),s.appendChild(n);let a=null;const o=[Y.create(b.cursor,"Select",d.select),!1!==t.rect&&Y.create(b.rect,"Rect",d.rect),!1!==t.textbox&&Y.create(b.text,"Textbox",d.textbox),!1!==t.brush&&Y.create(b.brush,"Brush",d.brush),!1!==t.image&&(a=Y.create(b.image,"Image",null))].filter(Boolean),r=new $(s,e,o);for(const e of o)i.appendChild(e.view),e.mode&&e.onClicked.subscribe(r.onItemClicked);a&&a.onClicked.subscribe(r.onOpenImageClicked);const c=R.create(e);return n.appendChild(c.view),r.reloadSelection(),e.onModeChanged.subscribe(r.reloadSelection),r}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=()=>u(this,void 0,void 0,(function*(){J(this.state)})),this.reloadSelection=()=>{this.items.forEach((e=>{e.setIsSelected(e.mode===this.state.mode)}))}}}class G{static create(e){const t=new G(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 K(e,t){const s=new m,i=v.element("span",{class:"mce-toolbar-label"});i.textContent=e;const n=v.element("input",{class:"mce-toolbar-color-input",type:"color",value:t});n.addEventListener("change",(function(){s.forward(n.value)}),!1);const a=v.div({class:"mce-toolbar-item"});return a.appendChild(i),a.appendChild(n),{view:a,onChanged:s}}class Q{static create(e){const t=v.div({class:"mce-toolbar-brush"}),s=K("Fill",e.rect.fillColor);t.appendChild(s.view);const i=new Q(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 _{static create(e){const t=v.div({class:"mce-toolbar-brush"}),s=function(e,t){const s=new m,i=v.element("span",{class:"mce-toolbar-label"});i.textContent=e;const n=v.element("input",{class:"mce-toolbar-number-input",type:"number",min:"0.5",step:"0.5",value:String(t)});n.addEventListener("change",(function(){const e=Number(n.value);s.forward(e)}),!1);const a=v.div({class:"mce-toolbar-item"});return a.appendChild(i),a.appendChild(n),{view:a,onChanged:s}}("Size",e.brush.brushSize),i=K("Color",e.brush.brushColor);t.appendChild(s.view),t.appendChild(i.view);const n=new _(t,e);return s.onChanged.subscribe(n.onBrushSizeChanged),i.onChanged.subscribe(n.onBrushColorChanged),n}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 ee{static create(e,t){switch(e){case d.rect:return Q.create(t);case d.brush:return _.create(t)}return null}}class te{static create(e){const t=v.div({class:"mce-toolbar"}),s=new te(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=ee.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 se{static createBlank(e,t,s,i){const n=X.createBlank(t,s,i);return se.create(e,n,i)}static createFromImage(e,t,s,i){var n,a,o;const r=null!==(n=s.workspaceWidth)&&void 0!==n?n:t.width,c=null!==(a=s.workspaceHeight)&&void 0!==a?a:t.height,l=se.createBlank(e,r,c,i),d={width:t.width,height:t.height,selectable:null===(o=s.selectable)||void 0===o||o};if(s.fitToWorkspace){const e=Math.max(r/t.width,c/t.height);d.left=(r-t.width*e)/2,d.top=(c-t.height*e)/2,d.scaleX=e,d.scaleY=e}const u=new h(t,d);if(l.add(u),!1===s.selectable&&s.select)throw new Error("Cannot select an image that is not selectable");return!1!==s.selectable&&s.select&&l.state.canvas.setActiveObject(u),l}static createFromJSON(e,t,s){return u(this,void 0,void 0,(function*(){const i=yield X.createFromJSON(e,s);return se.create(t,i,s)}))}static create(e,t,s){const i=v.div({class:"mce-editor"}),n=t.state,a=$.create(n,s),o=te.create(n);if(i.appendChild(a.view),i.appendChild(o.view),i.appendChild(t.view),!1!==s.sidebar){const e=B.create(n,"object"==typeof s.sidebar?s.sidebar:{});i.appendChild(e.view)}e.appendChild(i),t.startAutoLayout(!0);const r=G.create(i),c=new se(i,t,n,r);return n.canvas.on("object:added",c.onAnyChange),n.canvas.on("object:modified",c.onAnyChange),n.canvas.on("object:moving",c.onAnyChange),n.canvas.on("object:removed",c.onAnyChange),n.canvas.on("object:resizing",c.onAnyChange),n.canvas.on("object:rotating",c.onAnyChange),n.canvas.on("object:scaling",c.onAnyChange),n.canvas.on("object:skewing",c.onAnyChange),n.canvas.on("text:changed",c.onAnyChange),n.canvas.on("text:editing:exited",c.onAnyChange),n.canvas.on("selection:cleared",c.onAnyChange),n.canvas.on("selection:created",c.onAnyChange),n.canvas.on("selection:updated",c.onAnyChange),n.onLayerOrderChanged.subscribe(c.onAnyChange),n.onPropertiesChanged.subscribe(c.onAnyChange),c}constructor(e,t,s,i){this.view=e,this.workspace=t,this.state=s,this.layoutController=i,this.onChanged=new m,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 l.createFromJSON(this.toJSON())}render(){const e=this.state.canvas.getZoom(),t=this.state.canvas.width,i=this.state.canvas.height,n=this.state.canvas.viewportTransform,a=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 s(0,0)),this.state.canvas.workspaceBackground.visible=!1;const o=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(t),this.state.canvas.setHeight(i),this.state.canvas.setViewportTransform(n),this.state.canvas.workspaceBackground.visible=!0,a.forEach((({object:e,controls:t,hasBorders:s})=>{e.controls=t,e.hasBorders=s})),o}destroy(){var e;return u(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)}))}}export{se as Editor,d as EditorMode};