diff --git a/dist/index.html b/dist/index.html index 77c8680..a473b13 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1 +1 @@ -PPTist
\ No newline at end of file +PPTist
\ No newline at end of file diff --git a/dist/js/app.999ec9de.js b/dist/js/app.999ec9de.js deleted file mode 100644 index 9bb2090..0000000 --- a/dist/js/app.999ec9de.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(e){function t(t){for(var o,r,l=t[0],i=t[1],u=t[2],s=0,f=[];s一段测试文字,字号固定为28px

"},{id:"xxx3",type:"image",left:80,top:250,width:180,height:180,rotate:0,outline:{width:4,style:"solid",color:"#333"},clip:{range:[[30,0],[100,70]],shape:"ellipse"},fixedRatio:!1,lock:!1,src:"https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/1573622467064v2-7aa3ce420052983d91c6d01b47a7441d_hd.jpg"},{id:"xxx2",type:"image",left:750,top:320,width:150,height:150,rotate:0,fixedRatio:!0,lock:!1,src:"https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/62d9adb3-e7a6-4dc4-a352-095cffb49f08/b1be1a2f-f893-47d3-a8a3-eac7d04d395f/1596159381259v2-b2c69096d25ae16bf6ca09e30add3e65_hd.jpg"}],animations:[{elId:"xxx1",type:"rotateIn",duration:1e3},{elId:"xxx2",type:"zoomIn",duration:1e3}]},{id:"sajd172",elements:[{id:"yyx1",type:"text",left:590,top:90,width:220,height:188,rotate:0,opacity:1,lock:!1,content:"
😀 😐 😶 😜 🔔 ⭐ ⚡ 🔥 👍 💡 🔰 🎀 🎁 🥇 🏅 🏆 🎈 🎉 💎 🚧 ⛔ 📢 ⌛ ⏰ 🕒 🧩 🎵 📎 🔒 🔑 ⛳ 📌 📍 💬 📅 📈 📋 📜 📁 📱 💻 💾 🌏 🚚 🚡 🚢💧 🌐 🧭 💰 💳 🛒
"},{id:"xsfdas",type:"line",width:2,left:100,top:400,end:[0,0],start:[300,120],style:"solid",color:"#888",points:["","arrow"]},{id:"xxx7",type:"shape",left:130,top:50,width:150,height:150,rotate:0,fill:"#eebc29",opacity:.9,fixedRatio:!1,lock:!1,viewBox:1024,path:"M721.35111111 475.59111111H302.64888889c-5.00622222 0-9.10222222 4.096-9.10222222 9.10222222v54.61333334c0 5.00622222 4.096 9.10222222 9.10222222 9.10222222h418.70222222c5.00622222 0 9.10222222-4.096 9.10222222-9.10222222v-54.61333334c0-5.00622222-4.096-9.10222222-9.10222222-9.10222222z M512 2.27555555C230.51377778 2.27555555 2.27555555 230.51377778 2.27555555 512s228.23822222 509.72444445 509.72444445 509.72444445 509.72444445-228.23822222 509.72444445-509.72444445S793.48622222 2.27555555 512 2.27555555z m0 932.97777778c-233.69955555 0-423.25333333-189.55377778-423.25333333-423.25333333s189.55377778-423.25333333 423.25333333-423.25333333 423.25333333 189.55377778 423.25333333 423.25333333-189.55377778 423.25333333-423.25333333 423.25333333z"}],animations:[{elId:"yyx1",type:"flipInX",duration:1e3}]}],I={activeElementIdList:[],handleElementId:"",canvasPercentage:90,canvasScale:1,thumbnailsFocus:!1,editorAreaFocus:!1,disableHotkeys:!1,showGridLines:!1,creatingElement:null,availableFonts:[],toolbarState:"slideStyle",theme:{themeColor:"#d14424",fontColor:"#333",fontName:"微软雅黑",backgroundColor:"#fff"},slides:E,slideIndex:0,snapshotCursor:-1,snapshotLength:0,ctrlKeyState:!1,shiftKeyState:!1,screening:!1,clipingImageElementId:""},S=(n("4de4"),n("7db0"),n("caad"),n("d81d"),n("2532"),{currentSlide:function(e){return e.slides[e.slideIndex]||null},currentSlideAnimations:function(e){var t=e.slides[e.slideIndex];if(!t)return null;var n=t.animations;if(!n)return null;var o=t.elements,c=o.map((function(e){return e.id}));return n.filter((function(e){return c.includes(e.elId)}))},activeElementList:function(e){var t=e.slides[e.slideIndex];return t&&t.elements?t.elements.filter((function(t){return e.activeElementIdList.includes(t.id)})):[]},handleElement:function(e){var t=e.slides[e.slideIndex];return t&&t.elements&&t.elements.find((function(t){return e.handleElementId===t.id}))||null},canUndo:function(e){return e.snapshotCursor>0},canRedo:function(e){return e.snapshotCursor=0&&n.snapshotCursor20&&(a.push(c[0]),l--),l>=2&&M.snapshots.update(c[l-2],{index:n.slideIndex}),t.next=14,M.snapshots.bulkDelete(a);case 14:o(g.SET_SNAPSHOT_CURSOR,l-1),o(g.SET_SNAPSHOT_LENGTH,l);case 16:case"end":return t.stop()}}),t)})))()})),Object(C["a"])(N,y.UN_DO,(function(e){return Object(x["a"])(regeneratorRuntime.mark((function t(){var n,o,c,a,r,l,i;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(n=e.state,o=e.commit,!(n.snapshotCursor<=0)){t.next=3;break}return t.abrupt("return");case 3:return c=n.snapshotCursor-1,t.next=6,M.snapshots.orderBy("id").toArray();case 6:a=t.sent,r=a[c],l=r.index,i=r.slides,o(g.SET_SLIDES,i),o(g.UPDATE_SLIDE_INDEX,l),o(g.SET_SNAPSHOT_CURSOR,c),o(g.SET_ACTIVE_ELEMENT_ID_LIST,[]);case 13:case"end":return t.stop()}}),t)})))()})),Object(C["a"])(N,y.RE_DO,(function(e){return Object(x["a"])(regeneratorRuntime.mark((function t(){var n,o,c,a,r,l,i;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(n=e.state,o=e.commit,!(n.snapshotCursor>=n.snapshotLength-1)){t.next=3;break}return t.abrupt("return");case 3:return c=n.snapshotCursor+1,t.next=6,M.snapshots.orderBy("id").toArray();case 6:a=t.sent,r=a[c],l=r.index,i=r.slides,o(g.SET_SLIDES,i),o(g.UPDATE_SLIDE_INDEX,l),o(g.SET_SNAPSHOT_CURSOR,c),o(g.SET_ACTIVE_ELEMENT_ID_LIST,[]);case 13:case"end":return t.stop()}}),t)})))()})),N),A=(n("99af"),n("c740"),n("a434"),n("2909")),P=n("5530"),R=n("3eea"),F=n.n(R),z=[{zh:"微软雅黑",en:"Microsoft Yahei"},{zh:"宋体",en:"SimSun"},{zh:"黑体",en:"SimHei"},{zh:"楷体",en:"KaiTi"},{zh:"新宋体",en:"NSimSun"},{zh:"仿宋",en:"FangSong"},{zh:"苹方",en:"PingFang SC"},{zh:"华文黑体",en:"STHeiti"},{zh:"华文楷体",en:"STKaiti"},{zh:"华文宋体",en:"STSong"},{zh:"华文仿宋",en:"STFangSong"},{zh:"华文中宋",en:"STZhongSong"},{zh:"华文琥珀",en:"STHupo"},{zh:"华文新魏",en:"STXinwei"},{zh:"华文隶书",en:"STLiti"},{zh:"华文行楷",en:"STXingkai"},{zh:"冬青黑体简",en:"Hiragino Sans GB"},{zh:"兰亭黑-简",en:"Lantinghei SC"},{zh:"偏偏体-简",en:"Hanzipen SC"},{zh:"手札体-简",en:"Hannotate SC"},{zh:"宋体-简",en:"Songti SC"},{zh:"娃娃体-简",en:"Wawati SC"},{zh:"行楷-简",en:"Xingkai SC"},{zh:"圆体-简",en:"Yuanti SC"},{zh:"华文细黑",en:"STXihei"},{zh:"幼圆",en:"YouYuan"},{zh:"隶书",en:"LiSu"},{zh:"Arial",en:"Arial"}],H=[{name:"仓耳小丸子"},{name:"优设标题黑"},{name:"峰广明锐体"},{name:"摄图摩登小方体"},{name:"站酷快乐体"},{name:"站酷酷黑体"},{name:"素材集市康康体"},{name:"联盟起艺卢帅正锐黑体"},{name:"谦度手写楷体"},{name:"途牛类圆体"},{name:"锐字真言体"},{name:"问藏书房"}],U=(n("a15b"),function(e){if("string"!==typeof e)return!1;var t="Arial";if(e.toLowerCase()===t.toLowerCase())return!0;var n="a",o=100,c=100,a=100,r=document.createElement("canvas"),l=r.getContext("2d");if(!l)return!1;r.width=c,r.height=a,l.textAlign="center",l.fillStyle="black",l.textBaseline="middle";var i=function(e){l.clearRect(0,0,c,a),l.font="".concat(o,"px ").concat(e,", ").concat(t),l.fillText(n,c/2,a/2);var r=l.getImageData(0,0,c,a).data;return[].slice.call(r).filter((function(e){return 0!==e}))};return i(t).join("")!==i(e).join("")}),G=(T={},Object(C["a"])(T,g.SET_ACTIVE_ELEMENT_ID_LIST,(function(e,t){1===t.length?e.handleElementId=t[0]:e.handleElementId="",e.activeElementIdList=t})),Object(C["a"])(T,g.SET_HANDLE_ELEMENT_ID,(function(e,t){e.handleElementId=t})),Object(C["a"])(T,g.SET_CANVAS_PERCENTAGE,(function(e,t){e.canvasPercentage=t})),Object(C["a"])(T,g.SET_CANVAS_SCALE,(function(e,t){e.canvasScale=t})),Object(C["a"])(T,g.SET_THUMBNAILS_FOCUS,(function(e,t){e.thumbnailsFocus=t})),Object(C["a"])(T,g.SET_EDITORAREA_FOCUS,(function(e,t){e.editorAreaFocus=t})),Object(C["a"])(T,g.SET_DISABLE_HOTKEYS_STATE,(function(e,t){e.disableHotkeys=t})),Object(C["a"])(T,g.SET_GRID_LINES_STATE,(function(e,t){e.showGridLines=t})),Object(C["a"])(T,g.SET_CREATING_ELEMENT,(function(e,t){e.creatingElement=t})),Object(C["a"])(T,g.SET_AVAILABLE_FONTS,(function(e){e.availableFonts=z.filter((function(e){return U(e.en)}))})),Object(C["a"])(T,g.SET_TOOLBAR_STATE,(function(e,t){e.toolbarState=t})),Object(C["a"])(T,g.SET_CLIPING_IMAGE_ELEMENT_ID,(function(e,t){e.clipingImageElementId=t})),Object(C["a"])(T,g.SET_THEME,(function(e,t){e.theme=Object(P["a"])(Object(P["a"])({},e.theme),t)})),Object(C["a"])(T,g.SET_SLIDES,(function(e,t){e.slides=t})),Object(C["a"])(T,g.ADD_SLIDE,(function(e,t){var n=e.slideIndex+1;e.slides.splice(n,0,t),e.slideIndex=n})),Object(C["a"])(T,g.UPDATE_SLIDE,(function(e,t){var n=e.slideIndex;e.slides[n]=Object(P["a"])(Object(P["a"])({},e.slides[n]),t)})),Object(C["a"])(T,g.DELETE_SLIDE,(function(e,t){var n=e.slides.findIndex((function(e){return e.id===t}));n===e.slides.length-1&&(e.slideIndex=n-1),e.slides.splice(n,1)})),Object(C["a"])(T,g.UPDATE_SLIDE_INDEX,(function(e,t){e.slideIndex=t})),Object(C["a"])(T,g.ADD_ELEMENT,(function(e,t){var n=Array.isArray(t)?t:[t],o=e.slides[e.slideIndex].elements,c=[].concat(Object(A["a"])(o),Object(A["a"])(n));e.slides[e.slideIndex].elements=c})),Object(C["a"])(T,g.UPDATE_ELEMENT,(function(e,t){var n=t.id,o=t.props,c="string"===typeof n?[n]:n,a=e.slideIndex,r=e.slides[a],l=r.elements.map((function(e){return c.includes(e.id)?Object(P["a"])(Object(P["a"])({},e),o):e}));e.slides[a].elements=l})),Object(C["a"])(T,g.REMOVE_ELEMENT_PROPS,(function(e,t){var n=t.id,o=t.propName,c="string"===typeof o?[o]:o,a=e.slideIndex,r=e.slides[a],l=r.elements.map((function(e){return e.id===n?F()(e,c):e}));e.slides[a].elements=l})),Object(C["a"])(T,g.SET_SNAPSHOT_CURSOR,(function(e,t){e.snapshotCursor=t})),Object(C["a"])(T,g.SET_SNAPSHOT_LENGTH,(function(e,t){e.snapshotLength=t})),Object(C["a"])(T,g.SET_CTRL_KEY_STATE,(function(e,t){e.ctrlKeyState=t})),Object(C["a"])(T,g.SET_SHIFT_KEY_STATE,(function(e,t){e.shiftKeyState=t})),Object(C["a"])(T,g.SET_SCREENING,(function(e,t){e.screening=t})),T),q=Symbol(),W=Object(k["a"])({state:I,getters:S,mutations:G,actions:D}),X=function(){return Object(k["b"])(q)},Y=Object(h["withScopeId"])("data-v-d5c6b448");Object(h["pushScopeId"])("data-v-d5c6b448");var Z={class:"hamster-ppt-editor"},J={class:"layout-content"},K={class:"layout-content-center"};Object(h["popScopeId"])();var $,Q=Y((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("EditorHeader"),l=Object(h["resolveComponent"])("Thumbnails"),i=Object(h["resolveComponent"])("CanvasTool"),u=Object(h["resolveComponent"])("Canvas"),d=Object(h["resolveComponent"])("Toolbar");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Z,[Object(h["createVNode"])(r,{class:"layout-header"}),Object(h["createVNode"])("div",J,[Object(h["createVNode"])(l,{class:"layout-content-left"}),Object(h["createVNode"])("div",K,[Object(h["createVNode"])(i,{class:"center-top"}),Object(h["createVNode"])(u,{class:"center-body"})]),Object(h["createVNode"])(d,{class:"layout-content-right"})])])}));(function(e){e["C"]="C",e["X"]="X",e["Z"]="Z",e["Y"]="Y",e["A"]="A",e["G"]="G",e["L"]="L",e["F"]="F",e["D"]="D",e["MINUS"]="-",e["EQUAL"]="=",e["DIGIT_0"]="0",e["DELETE"]="DELETE",e["UP"]="ARROWUP",e["DOWN"]="ARROWDOWN",e["LEFT"]="ARROWLEFT",e["RIGHT"]="ARROWRIGHT",e["ENTER"]="ENTER",e["SPACE"]=" ",e["TAB"]="TAB"})($||($={}));n("3b18");var ee=n("f64c"),te=n("4106"),ne=n.n(te),oe=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:6,t="_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",n=t.length,o="",c=0;cEe?(n=Ee,o=n*c):o>Ee*Ie&&(o=Ee*Ie,n=o/c),a({type:"image",id:oe(),src:e,width:n,height:o,left:(Ee-n)/2,top:(Ee*Ie-o)/2,fixedRatio:!0})}))},l=function(e){a({type:"chart",id:oe(),chartType:e,left:300,top:81.25,width:400,height:400,themeColor:t.value,gridColor:n.value,data:{labels:["类别1","类别2","类别3","类别4","类别5"],series:[[12,19,5,2,18]]}})},i=function(e,n){var o=new Array(n).fill({id:oe(),colspan:1,rowspan:1,text:""}),c=new Array(e).fill(o),r=100,l=36,i=new Array(n).fill(1/n),u=n*r,d=e*l;a({type:"table",id:oe(),width:u,height:d,colWidths:i,data:c,left:(Ee-u)/2,top:(Ee*Ie-d)/2,outline:{width:2,style:"solid",color:"#eeece1"},theme:{color:t.value,rowHeader:!0,rowFooter:!1,colHeader:!1,colFooter:!1}})},u=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"请输入内容",n=e.left,o=e.top,c=e.width,r=e.height;a({type:"text",id:oe(),left:n,top:o,width:c,height:r,content:t})},d=function(e,n){var o=e.left,c=e.top,r=e.width,l=e.height;a({type:"shape",id:oe(),left:o,top:c,width:r,height:l,viewBox:n.viewBox,path:n.path,fill:t.value,fixedRatio:!1})},s=function(e,n){var o=e.left,c=e.top,r=e.start,l=e.end;a({type:"line",id:oe(),left:o,top:c,start:r,end:l,points:n.points,color:t.value,style:"solid",width:2})};return{createImageElement:r,createChartElement:l,createTableElement:i,createTextElement:u,createShapeElement:d,createLineElement:s}},Ce=function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.currentSlide})),n=ge(),o=n.addHistorySnapshot,c=Se(),a=c.createTextElement,r=function(n){var c,a={},r={},l=Object(me["a"])(n);try{for(l.s();!(c=l.n()).done;){var i=c.value,u=i.groupId;u&&!a[u]&&(a[u]=oe()),r[i.id]=oe()}}catch(m){l.e(m)}finally{l.f()}var d,s=t.value.elements.map((function(e){return e.id})),f=Object(me["a"])(n);try{for(f.s();!(d=f.n()).done;){var p=d.value,b=s.includes(p.id);p.id=r[p.id],b&&(p.left=p.left+10,p.top=p.top+10),p.groupId&&(p.groupId=a[p.groupId])}}catch(m){f.e(m)}finally{f.f()}e.commit(g.ADD_ELEMENT,n),e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,Object.values(r)),o()},l=function(t){e.commit(g.ADD_SLIDE,t),o()},i=function(e){a({left:0,top:0,width:600,height:50},e)},u=function(e,t){var n,o=(null===t||void 0===t?void 0:t.onlySlide)||!1,c=(null===t||void 0===t?void 0:t.onlyElements)||!1;try{n=JSON.parse(pe(e))}catch(s){n=e}if("object"===Object(be["a"])(n)){var a=n,u=a.type,d=a.data;"elements"!==u||o?"slide"!==u||c||l(d):r(d)}else c||o||i(n)};return{pasteTextClipboardData:u}},xe=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slideIndex})),n=Object(h["computed"])((function(){return e.state.theme})),o=Object(h["computed"])((function(){return e.state.slides.length})),c=Object(h["computed"])((function(){return e.getters.currentSlide})),a=Ce(),r=a.pasteTextClipboardData,l=ge(),i=l.addHistorySnapshot,u=function(n){var c=0;n===$.UP&&t.value>0?c=t.value-1:n===$.DOWN&&t.value=r&&(o-=c),e.commit(g.SET_CANVAS_PERCENTAGE,o)},o=function(t){e.commit(g.SET_CANVAS_PERCENTAGE,t)};return{scaleCanvas:n,setCanvasPercentage:o}},Re=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.ctrlKeyState})),n=Object(h["computed"])((function(){return e.state.shiftKeyState})),o=Object(h["computed"])((function(){return e.state.disableHotkeys})),c=Object(h["computed"])((function(){return e.state.activeElementIdList})),a=Object(h["computed"])((function(){return e.state.editorAreaFocus})),r=Object(h["computed"])((function(){return e.state.thumbnailsFocus})),l=xe(),i=l.updateSlideIndex,u=l.copySlide,d=l.createSlide,s=l.deleteSlide,f=l.cutSlide,p=l.copyAndPasteSlide,b=we(),m=b.combineElements,v=b.uncombineElements,O=Te(),j=O.deleteElement,y=Ne(),k=y.lockElement,E=Le(),I=E.copyElement,S=E.cutElement,C=E.quickCopyElement,x=Ve(),N=x.selectAllElement,T=_e(),w=T.moveElement,L=ge(),V=L.redo,_=L.undo,B=Ae(),M=B.enterScreening,D=Pe(),A=D.scaleCanvas,P=D.setCanvasPercentage,R=function(){c.value.length?I():r.value&&u()},F=function(){c.value.length?S():r.value&&f()},z=function(){c.value.length?C():r.value&&p()},H=function(){a.value&&N()},U=function(){a.value&&k()},G=function(){a.value&&m()},q=function(){a.value&&v()},W=function(){c.value.length?j():r.value&&s()},Y=function(e){c.value.length?w(e):e!==$.UP&&e!==$.DOWN||i(e)},Z=function(){r.value&&d()},J=function(c){var l=c.ctrlKey,i=c.shiftKey,u=c.metaKey,d=c.key.toUpperCase();if(l&&!t.value&&e.commit(g.SET_CTRL_KEY_STATE,!0),i&&!n.value&&e.commit(g.SET_SHIFT_KEY_STATE,!0),l&&d===$.F&&(c.preventDefault(),M(),e.commit(g.SET_CTRL_KEY_STATE,!1)),a.value||r.value){if((l||u)&&d===$.C){if(o.value)return;c.preventDefault(),R()}if(l&&d===$.X){if(o.value)return;c.preventDefault(),F()}if(l&&d===$.D){if(o.value)return;c.preventDefault(),z()}if(l&&d===$.Z){if(o.value)return;c.preventDefault(),_()}if(l&&d===$.Y){if(o.value)return;c.preventDefault(),V()}if(l&&d===$.A){if(o.value)return;c.preventDefault(),H()}if(l&&d===$.L){if(o.value)return;c.preventDefault(),U()}if(!i&&l&&d===$.G){if(o.value)return;c.preventDefault(),G()}if(i&&l&&d===$.G){if(o.value)return;c.preventDefault(),q()}if(d===$.DELETE){if(o.value)return;c.preventDefault(),W()}if(d===$.UP){if(o.value)return;c.preventDefault(),Y($.UP)}if(d===$.DOWN){if(o.value)return;c.preventDefault(),Y($.DOWN)}if(d===$.LEFT){if(o.value)return;c.preventDefault(),Y($.LEFT)}if(d===$.RIGHT){if(o.value)return;c.preventDefault(),Y($.RIGHT)}if(d===$.ENTER){if(o.value)return;c.preventDefault(),Z()}if(d===$.MINUS){if(o.value)return;c.preventDefault(),A("-")}if(d===$.EQUAL){if(o.value)return;c.preventDefault(),A("+")}if(d===$.DIGIT_0){if(o.value)return;c.preventDefault(),P(90)}}},K=function(){t.value&&e.commit(g.SET_CTRL_KEY_STATE,!1),n.value&&e.commit(g.SET_SHIFT_KEY_STATE,!1)};Object(h["onMounted"])((function(){document.addEventListener("keydown",J),document.addEventListener("keyup",K),window.addEventListener("blur",K)})),Object(h["onUnmounted"])((function(){document.removeEventListener("keydown",J),document.removeEventListener("keyup",K),window.removeEventListener("blur",K)}))},Fe=(n("c975"),function(){var e=X(),t=Object(h["computed"])((function(){return e.state.editorAreaFocus})),n=Object(h["computed"])((function(){return e.state.thumbnailsFocus})),o=Object(h["computed"])((function(){return e.state.disableHotkeys})),c=Ce(),a=c.pasteTextClipboardData,r=Se(),l=r.createImageElement,i=function(e){ke(e).then((function(e){return l(e)}))},u=function(e){if((t.value||n.value)&&!o.value&&e.clipboardData){var c=e.clipboardData.items,r=c[0];if(r){var l,u=Object(me["a"])(c);try{for(u.s();!(l=u.n()).done;){var d=l.value;if("file"===d.kind&&-1!==d.type.indexOf("image")){var s=d.getAsFile();return void(s&&i(s))}}}catch(f){u.e(f)}finally{u.f()}"string"===r.kind&&"text/plain"===r.type&&r.getAsString((function(e){return a(e)}))}}};Object(h["onMounted"])((function(){document.addEventListener("paste",u)})),Object(h["onUnmounted"])((function(){document.removeEventListener("paste",u)}))}),ze=Object(h["withScopeId"])("data-v-2accc3e9");Object(h["pushScopeId"])("data-v-2accc3e9");var He={class:"editor-header"},Ue={class:"left"},Ge={class:"menu-item"},qe=Object(h["createTextVNode"])(" 编辑"),We=Object(h["createTextVNode"])("撤销"),Xe=Object(h["createTextVNode"])("重做"),Ye=Object(h["createTextVNode"])("添加页面"),Ze=Object(h["createTextVNode"])("删除页面"),Je=Object(h["createTextVNode"])("重置幻灯片"),Ke={class:"menu-item"},$e=Object(h["createTextVNode"])(" 演示"),Qe=Object(h["createTextVNode"])("从头开始"),et=Object(h["createTextVNode"])("从当前页开始"),tt={class:"menu-item"},nt=Object(h["createTextVNode"])(" 帮助"),ot=Object(h["createTextVNode"])("开发文档"),ct=Object(h["createTextVNode"])("快捷键"),at={class:"right"},rt={class:"menu-item"},lt={class:"hotkeys"},it={class:"title"},ut={class:"label"},dt={class:"value"};Object(h["popScopeId"])();var st=ze((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEdit"),l=Object(h["resolveComponent"])("MenuItem"),i=Object(h["resolveComponent"])("Menu"),u=Object(h["resolveComponent"])("Dropdown"),d=Object(h["resolveComponent"])("IconPpt"),s=Object(h["resolveComponent"])("IconHelpcenter"),f=Object(h["resolveComponent"])("Tooltip"),p=Object(h["resolveComponent"])("IconGithub"),b=Object(h["resolveComponent"])("Drawer");return Object(h["openBlock"])(),Object(h["createBlock"])("div",He,[Object(h["createVNode"])("div",Ue,[Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[1]||(t[1]=function(t){return e.undo()})},{default:ze((function(){return[We]})),_:1}),Object(h["createVNode"])(l,{onClick:t[2]||(t[2]=function(t){return e.redo()})},{default:ze((function(){return[Xe]})),_:1}),Object(h["createVNode"])(l,{onClick:t[3]||(t[3]=function(t){return e.createSlide()})},{default:ze((function(){return[Ye]})),_:1}),Object(h["createVNode"])(l,{onClick:t[4]||(t[4]=function(t){return e.deleteSlide()})},{default:ze((function(){return[Ze]})),_:1}),Object(h["createVNode"])(l,{onClick:t[5]||(t[5]=function(t){return e.toggleGridLines()})},{default:ze((function(){return[Object(h["createTextVNode"])(Object(h["toDisplayString"])(e.showGridLines?"关闭网格线":"打开网格线"),1)]})),_:1}),Object(h["createVNode"])(l,{onClick:t[6]||(t[6]=function(t){return e.resetSlides()})},{default:ze((function(){return[Je]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",Ge,[Object(h["createVNode"])(r),qe])]})),_:1}),Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[7]||(t[7]=function(t){return e.enterScreeningFromStart()})},{default:ze((function(){return[Qe]})),_:1}),Object(h["createVNode"])(l,{onClick:t[8]||(t[8]=function(t){return e.enterScreening()})},{default:ze((function(){return[et]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",Ke,[Object(h["createVNode"])(d),$e])]})),_:1}),Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[9]||(t[9]=function(t){return e.openDoc()})},{default:ze((function(){return[ot]})),_:1}),Object(h["createVNode"])(l,{onClick:t[10]||(t[10]=function(t){return e.hotkeyDrawerVisible=!0})},{default:ze((function(){return[ct]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",tt,[Object(h["createVNode"])(s),nt])]})),_:1})]),Object(h["createVNode"])("div",at,[Object(h["createVNode"])(f,{mouseLeaveDelay:0,title:"幻灯片放映"},{default:ze((function(){return[Object(h["createVNode"])("div",{class:"menu-item",onClick:t[11]||(t[11]=function(t){return e.enterScreening()})},[Object(h["createVNode"])(d,{size:"18",fill:"#666",style:{"margin-top":"2px"}})])]})),_:1}),Object(h["createVNode"])(f,{mouseLeaveDelay:0,title:"Github 仓库"},{default:ze((function(){return[Object(h["createVNode"])("div",rt,[Object(h["createVNode"])(p,{size:"18",fill:"#666"})])]})),_:1})]),Object(h["createVNode"])(b,{width:"320",placement:"right",visible:e.hotkeyDrawerVisible,onClose:t[12]||(t[12]=function(t){return e.hotkeyDrawerVisible=!1})},{default:ze((function(){return[Object(h["createVNode"])("div",lt,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.hotkeys,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:e.type},[Object(h["createVNode"])("div",it,Object(h["toDisplayString"])(e.type),1),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.children,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"hotkey-item",key:e.label},[Object(h["createVNode"])("div",ut,Object(h["toDisplayString"])(e.label),1),Object(h["createVNode"])("div",dt,Object(h["toDisplayString"])(e.value),1)])})),128))],64)})),128))])]})),_:1},8,["visible"])])})),ft=[{type:"通用",children:[{label:"剪切",value:"Ctrl + X"},{label:"复制",value:"Ctrl + C"},{label:"粘贴",value:"Ctrl + V"},{label:"快速复制粘贴",value:"Ctrl + D"},{label:"全选",value:"Ctrl + A"},{label:"撤销",value:"Ctrl + Z"},{label:"恢复",value:"Ctrl + Y"},{label:"删除",value:"Delete"}]},{type:"幻灯片放映",children:[{label:"开始放映幻灯片",value:"Ctrl + F"},{label:"切换上一页",value:"↑ / ←"},{label:"切换下一页",value:"↓ / → / Enter / Space"},{label:"退出放映",value:"ESC"}]},{type:"幻灯片编辑",children:[{label:"新建幻灯片",value:"Enter"},{label:"缩放画布",value:"Ctrl + 鼠标滚动"},{label:"放大画布",value:"Ctrl + ="},{label:"缩小画布",value:"Ctrl + -"},{label:"缩放画布到合适大小",value:"Ctrl + 0"},{label:"编辑上一页",value:"↑ / ←"},{label:"编辑下一页",value:"↓ / →"}]},{type:"元素操作",children:[{label:"移动",value:"↑ / ← / ↓ / →"},{label:"锁定",value:"Ctrl + L"},{label:"组合",value:"Ctrl + G"},{label:"取消组合",value:"Ctrl + Shift + G"},{label:"多选",value:"按住 Ctrl 或 Shift"},{label:"锁定宽高比例",value:"按住 Ctrl 或 Shift"},{label:"创建水平 / 垂直线条",value:"按住 Ctrl 或 Shift"},{label:"确认图片裁剪",value:"Enter"}]},{type:"表格编辑",children:[{label:"聚焦到下一个单元格",value:"Tab"}]},{type:"文本编辑",children:[{label:"加粗",value:"Ctrl + B"},{label:"斜体",value:"Ctrl + I"},{label:"下划线",value:"Ctrl + U"},{label:"删除线",value:"Ctrl + D"}]}],pt=Object(h["defineComponent"])({name:"editor-header",setup:function(){var e=X(),t=Ae(),n=t.enterScreening,o=t.enterScreeningFromStart,c=xe(),a=c.createSlide,r=c.deleteSlide,l=ge(),i=l.redo,u=l.undo,d=Object(h["computed"])((function(){return e.state.showGridLines})),s=function(){e.commit(g.SET_GRID_LINES_STATE,!d.value)},f=function(){e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,[]),e.commit(g.SET_SLIDES,[{id:oe(),elements:[]}])},p=function(){ee["a"].warning("作者努力编写中...")},b=Object(h["ref"])(!1);return{enterScreening:n,enterScreeningFromStart:o,createSlide:a,deleteSlide:r,redo:i,undo:u,toggleGridLines:s,showGridLines:d,resetSlides:f,openDoc:p,hotkeyDrawerVisible:b,hotkeys:ft}}});n("5c0a");pt.render=st,pt.__scopeId="data-v-2accc3e9";var bt=pt,mt=Object(h["withScopeId"])("data-v-75c486b2");Object(h["pushScopeId"])("data-v-75c486b2");var vt={class:"operates"};Object(h["popScopeId"])();var Ot,ht,jt,gt,yt,kt=mt((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementCreateSelection"),l=Object(h["resolveComponent"])("AlignmentLine"),i=Object(h["resolveComponent"])("MultiSelectOperate"),u=Object(h["resolveComponent"])("Operate"),d=Object(h["resolveComponent"])("SlideBackground"),s=Object(h["resolveComponent"])("MouseSelection"),f=Object(h["resolveComponent"])("EditableElement"),p=Object(h["resolveDirective"])("contextmenu"),b=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"canvas",ref:"canvasRef",onMousewheel:t[2]||(t[2]=function(t){return e.mousewheelScaleCanvas(t)}),onMousedown:t[3]||(t[3]=function(t){return e.handleClickBlankArea(t)})},[e.creatingElement?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,onCreated:t[1]||(t[1]=function(t){return e.insertElementFromCreateSelection(t)})})):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"viewport-wrapper",style:{width:e.viewportStyles.width*e.canvasScale+"px",height:e.viewportStyles.height*e.canvasScale+"px",left:e.viewportStyles.left+"px",top:e.viewportStyles.top+"px"}},[Object(h["createVNode"])("div",vt,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.alignmentLines,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:t,type:e.type,axis:e.axis,length:e.length},null,8,["type","axis","length"])})),128)),e.activeElementIdList.length>1?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:0,elementList:e.elementList,scaleMultiElement:e.scaleMultiElement},null,8,["elementList","scaleMultiElement"])):Object(h["createCommentVNode"])("",!0),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.elementList,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(u,{key:t.id,elementInfo:t,isSelected:e.activeElementIdList.includes(t.id),isActive:e.handleElementId===t.id,isActiveGroupElement:e.activeGroupElementId===t.id,isMultiSelect:e.activeElementIdList.length>1,rotateElement:e.rotateElement,scaleElement:e.scaleElement,dragLineElement:e.dragLineElement},null,8,["elementInfo","isSelected","isActive","isActiveGroupElement","isMultiSelect","rotateElement","scaleElement","dragLineElement"])})),128)),Object(h["createVNode"])(d)]),Object(h["createVNode"])("div",{class:"viewport",ref:"viewportRef",style:{transform:"scale(".concat(e.canvasScale,")")}},[e.mouseSelectionState.isShow?(Object(h["openBlock"])(),Object(h["createBlock"])(s,{key:0,top:e.mouseSelectionState.top,left:e.mouseSelectionState.left,width:e.mouseSelectionState.width,height:e.mouseSelectionState.height,quadrant:e.mouseSelectionState.quadrant},null,8,["top","left","width","height","quadrant"])):Object(h["createCommentVNode"])("",!0),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.elementList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(f,{key:t.id,elementInfo:t,elementIndex:n+1,isMultiSelect:e.activeElementIdList.length>1,selectElement:e.selectElement},null,8,["elementInfo","elementIndex","isMultiSelect","selectElement"])})),128))],4)],4)],544)),[[p,e.contextmenus],[b,e.removeEditorAreaFocus]])})),Et=function(){var e=window.getSelection();e&&e.removeAllRanges()},It=function(e){var t=Object(h["ref"])(0),n=Object(h["ref"])(0),o=X(),c=Object(h["computed"])((function(){return o.state.canvasPercentage})),a=function(){if(e.value){var a=e.value.clientWidth,r=e.value.clientHeight;if(r/a>Ie){var l=a*(c.value/100);o.commit(g.SET_CANVAS_SCALE,l/Ee),t.value=(a-l)/2,n.value=(r-l*Ie)/2}else{var i=r*(c.value/100);o.commit(g.SET_CANVAS_SCALE,i/(Ee*Ie)),t.value=(a-i/Ie)/2,n.value=(r-i)/2}}};Object(h["watch"])(c,a);var r=Object(h["computed"])((function(){return{width:Ee,height:Ee*Ie,left:t.value,top:n.value}})),l=new ResizeObserver(a);return Object(h["onMounted"])((function(){e.value&&l.observe(e.value)})),Object(h["onUnmounted"])((function(){e.value&&l.unobserve(e.value)})),{viewportStyles:r}},St=(n("a623"),n("4160"),n("159b"),function(e){var t=e.left,n=e.top,o=e.width,c=e.height,a=e.rotate,r=void 0===a?0:a,l=Math.sqrt(Math.pow(o,2)+Math.pow(c,2))/2,i=180*Math.atan(c/o)/Math.PI,u=(180-r-i)*Math.PI/180,d=(i-r)*Math.PI/180,s=o/2,f=c/2,p=t+s,b=n+f,m=[p+l*Math.cos(u),p+l*Math.cos(d),p-l*Math.cos(u),p-l*Math.cos(d)],v=[b-l*Math.sin(u),b-l*Math.sin(d),b+l*Math.sin(u),b+l*Math.sin(d)];return{xRange:[Math.min.apply(Math,m),Math.max.apply(Math,m)],yRange:[Math.min.apply(Math,v),Math.max.apply(Math,v)]}}),Ct=function(e){var t,n,o,c;if("line"===e.type)t=e.left,n=e.left+Math.max(e.start[0],e.end[0]),o=e.top,c=e.top+Math.max(e.start[1],e.end[1]);else if("rotate"in e&&e.rotate){var a=e.left,r=e.top,l=e.width,i=e.height,u=e.rotate,d=St({left:a,top:r,width:l,height:i,rotate:u}),s=d.xRange,f=d.yRange;t=s[0],n=s[1],o=f[0],c=f[1]}else t=e.left,n=e.left+e.width,o=e.top,c=e.top+e.height;return{minX:t,maxX:n,minY:o,maxY:c}},xt=function(e){var t=[],n=[],o=[],c=[];e.forEach((function(e){var a=Ct(e),r=a.minX,l=a.maxX,i=a.minY,u=a.maxY;t.push(r),n.push(i),o.push(l),c.push(u)}));var a=Math.min.apply(Math,t),r=Math.max.apply(Math,o),l=Math.min.apply(Math,n),i=Math.max.apply(Math,c);return{minX:a,maxX:r,minY:l,maxY:i}},Nt=function(e){var t=[];return e.forEach((function(e){var n=t.findIndex((function(t){return t.value===e.value}));if(-1===n)t.push(e);else{var o=t[n],c=Math.min(o.range[0],e.range[0]),a=Math.max(o.range[1],e.range[1]),r=[c,a],l={value:e.value,range:r};t[n]=l}})),t},Tt=function(e,t){var n=X(),o=Object(h["computed"])((function(){return n.state.canvasScale})),c=Object(h["reactive"])({isShow:!1,top:0,left:0,width:0,height:0,quadrant:1}),a=function(a){if(t.value){var r=!0,l=t.value.getBoundingClientRect(),i=5,u=a.pageX,d=a.pageY,s=(u-l.x)/o.value,f=(d-l.y)/o.value;c.isShow=!1,c.quadrant=4,c.top=f,c.left=s,c.width=0,c.height=0,document.onmousemove=function(e){if(r){var t=e.pageX,n=e.pageY,a=(t-u)/o.value,l=(n-d)/o.value,s=Math.abs(a),f=Math.abs(l);if(!(s0&&l>0?p=4:a<0&&l<0?p=1:a>0&&l<0?p=2:a<0&&l>0&&(p=3),c.isShow=!0,c.quadrant=p,c.width=s,c.height=f}}},document.onmouseup=function(){document.onmousemove=null,document.onmouseup=null,r=!1;for(var t=[],o=0;ol&&bi&&vl-u&&bi-d&&vl&&bi-d&&vl-u&&bi&&v0&&Math.abs(l-45)<=d?l-=l-45:l<0&&Math.abs(l+45)<=d?l-=l+45:l>0&&Math.abs(l-90)<=d?l-=l-90:l<0&&Math.abs(l+90)<=d?l-=l+90:l>0&&Math.abs(l-135)<=d?l-=l-135:l<0&&Math.abs(l+135)<=d?l-=l+135:l>0&&Math.abs(l-180)<=d?l-=l-180:l<0&&Math.abs(l+180)<=d&&(l-=l+180),e.value=e.value.map((function(e){return c.id===e.id?Object(P["a"])(Object(P["a"])({},e),{},{rotate:l}):e}))}},document.onmouseup=function(){r=!1,document.onmousemove=null,document.onmouseup=null,i!==l&&(n.commit(g.UPDATE_SLIDE,{elements:e.value}),a())}}};return{rotateElement:r}};(function(e){e["UP"]="up",e["DOWN"]="down",e["TOP"]="top",e["BOTTOM"]="bottom"})(Ot||(Ot={})),function(e){e["TOP"]="top",e["BOTTOM"]="bottom",e["LEFT"]="left",e["RIGHT"]="right",e["VERTICAL"]="vertical",e["HORIZONTAL"]="horizontal"}(ht||(ht={})),function(e){e["T"]="top",e["B"]="bottom",e["L"]="left",e["R"]="right"}(jt||(jt={})),function(e){e["LEFT_TOP"]="left-top",e["TOP"]="top",e["RIGHT_TOP"]="right-top",e["LEFT"]="left",e["RIGHT"]="right",e["LEFT_BOTTOM"]="left-bottom",e["BOTTOM"]="bottom",e["RIGHT_BOTTOM"]="right-bottom"}(gt||(gt={})),function(e){e["START"]="start",e["END"]="end,"}(yt||(yt={}));var _t,Bt=n("14b7");(function(e){e["UPDATE_TEXT_STATE"]="UPDATE_TEXT_STATE",e["EXEC_TEXT_COMMAND"]="EXEC_TEXT_COMMAND",e["UPDATE_TABLE_SELECTED_CELL"]="UPDATE_TABLE_SELECTED_CELL",e["SCALE_ELEMENT_STATE"]="SCALE_ELEMENT_STATE"})(_t||(_t={}));var Mt=Object(Bt["a"])(),Dt=Mt,At={text:"文本",image:"图片",shape:"形状",line:"线条",chart:"图表",table:"表格"},Pt={text:20,image:20,shape:15,chart:200,table:20},Rt=function(e,t){var n=e.left,o=e.top,c=e.width,a=e.height,r=Math.sqrt(Math.pow(c,2)+Math.pow(a,2))/2,l=180*Math.atan(a/c)/Math.PI,i=(180-t-l)*Math.PI/180,u=(l-t)*Math.PI/180,d=(90-t)*Math.PI/180,s=t*Math.PI/180,f=c/2,p=a/2,b=n+f,m=o+p,v={left:b+r*Math.cos(i),top:m-r*Math.sin(i)},O={left:b+p*Math.cos(d),top:m-p*Math.sin(d)},h={left:b+r*Math.cos(u),top:m-r*Math.sin(u)},j={left:b+f*Math.cos(s),top:m+f*Math.sin(s)},g={left:b-r*Math.cos(i),top:m+r*Math.sin(i)},y={left:b-p*Math.sin(s),top:m+p*Math.cos(s)},k={left:b-r*Math.cos(u),top:m+r*Math.sin(u)},E={left:b-f*Math.cos(s),top:m-f*Math.sin(s)};return{leftTopPoint:v,topPoint:O,rightTopPoint:h,rightPoint:j,rightBottomPoint:g,bottomPoint:y,leftBottomPoint:k,leftPoint:E}},Ft=function(e,t){var n,o=(n={},Object(C["a"])(n,gt.RIGHT_BOTTOM,t.leftTopPoint),Object(C["a"])(n,gt.LEFT_BOTTOM,t.rightTopPoint),Object(C["a"])(n,gt.LEFT_TOP,t.rightBottomPoint),Object(C["a"])(n,gt.RIGHT_TOP,t.leftBottomPoint),Object(C["a"])(n,gt.TOP,t.bottomPoint),Object(C["a"])(n,gt.BOTTOM,t.topPoint),Object(C["a"])(n,gt.LEFT,t.rightPoint),Object(C["a"])(n,gt.RIGHT,t.leftPoint),n);return o[e]},zt=function(e,t,n){var o=X(),c=Object(h["computed"])((function(){return o.state.activeElementIdList})),a=Object(h["computed"])((function(){return o.getters.ctrlOrShiftKeyActive})),r=Object(h["computed"])((function(){return o.state.canvasScale})),l=ge(),i=l.addHistorySnapshot,u=function(l,u,d){var s=!0;Dt.emit(_t.SCALE_ELEMENT_STATE,!0);var f,p=u.left,b=u.top,m=u.width,v=u.height,O=a.value||"fixedRatio"in u&&u.fixedRatio,h=m/v,j="rotate"in u&&u.rotate?u.rotate:0,y=Math.PI*j/180,k=l.pageX,E=l.pageY,I=Pt[u.type]||20,S=function(e){return e2&&void 0!==arguments[2])||arguments[2];if(r.value||o.commit(g.SET_EDITORAREA_FOCUS,!0),c.value.includes(u.id)){if(l.value){var s=[];if(u.groupId){var f=[];e.value.forEach((function(e){e.groupId===u.groupId&&f.push(e.id)})),s=c.value.filter((function(e){return!f.includes(e)}))}else s=c.value.filter((function(e){return e!==u.id}));s.length>0&&o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,s)}else if(a.value!==u.id)o.commit(g.SET_HANDLE_ELEMENT_ID,u.id);else if(t.value!==u.id){var p=i.pageX,b=i.pageY;i.target.onmouseup=function(e){var n=e.pageX,o=e.pageY;p===n&&b===o&&(t.value=u.id,e.target.onmouseup=null)}}}else{var m=[];if(m=l.value?[].concat(Object(A["a"])(c.value),[u.id]):[u.id],u.groupId){var v=[];e.value.forEach((function(e){e.groupId===u.groupId&&v.push(e.id)})),m=[].concat(Object(A["a"])(m),v)}o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,Ut()(m)),o.commit(g.SET_HANDLE_ELEMENT_ID,u.id)}d&&n(i,u)},u=function(){var t=e.value.filter((function(e){return!e.lock})),n=t.map((function(e){return e.id}));o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,n)};return{selectElement:i,selectAllElement:u}},qt=function(e,t,n){var o=X(),c=Object(h["computed"])((function(){return o.state.activeElementIdList})),a=Object(h["computed"])((function(){return o.state.canvasScale})),r=ge(),l=r.addHistorySnapshot,i=function(r,i){if(c.value.includes(i.id)){var u,d=!0,s=Ee,f=Ee*Ie,p=JSON.parse(JSON.stringify(e.value)),b=p.filter((function(e){return c.value.includes(e.id)})),m=5,v=i.left,O=i.top,h=i.width,j="height"in i&&i.height?i.height:0,y="rotate"in i&&i.rotate?i.rotate:0,k=r.pageX,E=r.pageY,I=null,S=i.id===t.value,C=[],x=[],N=Object(me["a"])(e.value);try{for(N.s();!(u=N.n()).done;){var T=u.value;if("line"!==T.type&&((!S||T.id!==i.id)&&(S||!c.value.includes(T.id)))){var w=void 0,L=void 0,V=void 0,_=void 0;if("rotate"in T&&T.rotate){var B=St({left:T.left,top:T.top,width:T.width,height:T.height,rotate:T.rotate}),M=B.xRange,D=B.yRange;w=M[0],L=D[0],V=M[1]-M[0],_=D[1]-D[0]}else w=T.left,L=T.top,V=T.width,_=T.height;var R=w+V,F=L+_,z=L+_/2,H=w+V/2,U={value:L,range:[w,R]},G={value:F,range:[w,R]},q={value:z,range:[w,R]},W={value:w,range:[L,F]},X={value:R,range:[L,F]},Y={value:H,range:[L,F]};C.push(U,G,q),x.push(W,X,Y)}}}catch(te){N.e(te)}finally{N.f()}var Z={value:0,range:[0,s]},J={value:f,range:[0,s]},K={value:f/2,range:[0,s]},$={value:0,range:[0,f]},Q={value:s,range:[0,f]},ee={value:s/2,range:[0,f]};C.push(Z,J,K),x.push($,Q,ee),C=Nt(C),x=Nt(x),document.onmousemove=function(t){var o=t.pageX,r=t.pageY;if(!1!==I&&(I=Math.abs(k-o)v&&(V[0]=w-N,_[0]=0),m>O&&(V[1]=L-T,_[1]=0),e.value=e.value.map((function(e){return e.id===a.id?Object(P["a"])(Object(P["a"])({},e),{},{left:N,top:T,start:V,end:_}):e}))}},document.onmouseup=function(n){l=!1,document.onmousemove=null,document.onmouseup=null;var o=n.pageX,a=n.pageY;u===o&&d===a||(t.commit(g.UPDATE_SLIDE,{elements:e.value}),c())}};return{dragLineElement:a}},Xt=n("3835"),Yt=function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.creatingElement})),c=function(t){var o=t.start,c=t.end;if(e.value){var a=e.value.getBoundingClientRect(),r=Object(Xt["a"])(o,2),l=r[0],i=r[1],u=Object(Xt["a"])(c,2),d=u[0],s=u[1],f=Math.min(l,d),p=Math.max(l,d),b=Math.min(i,s),m=Math.max(i,s),v=(f-a.x)/n.value,O=(b-a.y)/n.value,h=(p-f)/n.value,j=(m-b)/n.value;return{left:v,top:O,width:h,height:j}}},a=function(t){var o=t.start,c=t.end;if(e.value){var a=e.value.getBoundingClientRect(),r=Object(Xt["a"])(o,2),l=r[0],i=r[1],u=Object(Xt["a"])(c,2),d=u[0],s=u[1],f=Math.min(l,d),p=Math.max(l,d),b=Math.min(i,s),m=Math.max(i,s),v=(f-a.x)/n.value,O=(b-a.y)/n.value,h=(p-f)/n.value,j=(m-b)/n.value,g=[l===f?0:h,i===b?0:j],y=[d===f?0:h,s===b?0:j];return{left:v,top:O,start:g,end:y}}},r=Se(),l=r.createTextElement,i=r.createShapeElement,u=r.createLineElement,d=function(e){if(o.value){var n=o.value.type;if("text"===n){var r=c(e);r&&l(r)}else if("shape"===n){var d=c(e);d&&i(d,o.value.data)}else if("line"===n){var s=a(e);s&&u(s,o.value.data)}t.commit(g.SET_CREATING_ELEMENT,null)}};return{insertElementFromCreateSelection:d}};function Zt(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"editable-element",ref:"elementRef",id:"editable-element-"+e.elementInfo.id,style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo,selectElement:e.selectElement,contextmenus:e.contextmenus},null,8,["elementInfo","selectElement","contextmenus"]))],12,["id"])}var Jt;n("a9e3");(function(e){e["TEXT"]="text",e["IMAGE"]="image",e["SHAPE"]="shape",e["LINE"]="line",e["CHART"]="chart",e["TABLE"]="table"})(Jt||(Jt={}));var Kt,$t,Qt=function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.currentSlide})),n=ge(),o=n.addHistorySnapshot,c=function(e,t){var n=e.findIndex((function(e){return e.id===t[0].id})),o=e.findIndex((function(e){return e.id===t[t.length-1].id}));return{minIndex:n,maxIndex:o}},a=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex,l=a.maxIndex;if(l===e.length-1)return null;var i=n[l+1],u=n.splice(r,o.length);if(i.groupId){var d=n.filter((function(e){return e.groupId===i.groupId}));n.splice.apply(n,[r+d.length,0].concat(Object(A["a"])(u)))}else n.splice.apply(n,[r+1,0].concat(Object(A["a"])(u)))}else{var s=e.findIndex((function(e){return e.id===t.id}));if(s===e.length-1)return null;var f=n[s+1],p=n.splice(s,1)[0];if(f.groupId){var b=n.filter((function(e){return e.groupId===f.groupId}));n.splice(s+b.length,0,p)}else n.splice(s+1,0,p)}return n},r=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex;if(0===r)return null;var l=n[r-1],i=n.splice(r,o.length);if(l.groupId){var u=n.filter((function(e){return e.groupId===l.groupId}));n.splice.apply(n,[r-u.length,0].concat(Object(A["a"])(i)))}else n.splice.apply(n,[r-1,0].concat(Object(A["a"])(i)))}else{var d=e.findIndex((function(e){return e.id===t.id}));if(0===d)return null;var s=n[d-1],f=n.splice(d,1)[0];if(s.groupId){var p=n.filter((function(e){return e.groupId===s.groupId}));n.splice(d-p.length,0,f)}else n.splice(d-1,0,f)}return n},l=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex,l=a.maxIndex;if(l===e.length-1)return null;var i=n.splice(r,o.length);n.push.apply(n,Object(A["a"])(i))}else{var u=e.findIndex((function(e){return e.id===t.id}));if(u===e.length-1)return null;n.splice(u,1),n.push(t)}return n},i=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex;if(0===r)return null;var l=n.splice(r,o.length);n.unshift.apply(n,Object(A["a"])(l))}else{var i=e.findIndex((function(e){return e.id===t.id}));if(0===i)return null;n.splice(i,1),n.unshift(t)}return n},u=function(n,c){var u=null;c===Ot.UP?u=a(t.value.elements,n):c===Ot.DOWN?u=r(t.value.elements,n):c===Ot.TOP?u=l(t.value.elements,n):c===Ot.BOTTOM&&(u=i(t.value.elements,n)),u&&(e.commit(g.UPDATE_SLIDE,{elements:u}),o())};return{orderElement:u}},en=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.getters.activeElementList})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=function(c){var a,r=Ee,l=Ee*Ie,i=xt(n.value),u=i.minX,d=i.maxX,s=i.minY,f=i.maxY,p=JSON.parse(JSON.stringify(o.value.elements)),b=Object(me["a"])(p);try{for(b.s();!(a=b.n()).done;){var m=a.value;if(t.value.includes(m.id))if(c===ht.TOP){var v=s-0;m.top=m.top-v}else if(c===ht.VERTICAL){var O=s+(f-s)/2-l/2;m.top=m.top-O}else if(c===ht.BOTTOM){var h=f-l;m.top=m.top-h}else if(c===ht.LEFT){var j=u-0;m.left=m.left-j}else if(c===ht.HORIZONTAL){var y=u+(d-u)/2-r/2;m.left=m.left-y}else if(c===ht.RIGHT){var k=d-r;m.left=m.left-k}}}catch(E){b.e(E)}finally{b.f()}e.commit(g.UPDATE_SLIDE,{elements:p})};return{alignElementToCanvas:c}},tn=Object(h["withScopeId"])("data-v-c9d8ae3c"),nn=tn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ImageClipHandler"),l=Object(h["resolveComponent"])("ImageRectOutline"),i=Object(h["resolveComponent"])("ImageEllipseOutline"),u=Object(h["resolveComponent"])("ImagePolygonOutline"),d=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-image",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")},onMousedown:t[2]||(t[2]=function(t){return e.handleSelectElement(t)})},[e.isCliping?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,src:e.elementInfo.src,clipData:e.elementInfo.clip,width:e.elementInfo.width,height:e.elementInfo.height,top:e.elementInfo.top,left:e.elementInfo.left,clipPath:e.clipShape.style,onClip:t[1]||(t[1]=function(t){return e.clip(t)})},null,8,["src","clipData","width","height","top","left","clipPath"])):Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:1,class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):"",transform:e.flip}},["rect"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:0,width:e.elementInfo.width,height:e.elementInfo.height,radius:e.clipShape.radius,outline:e.elementInfo.outline},null,8,["width","height","radius","outline"])):"ellipse"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:1,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"])):"polygon"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(u,{key:2,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline,createPath:e.clipShape.createPath},null,8,["width","height","outline","createPath"])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"image-content",style:{clipPath:e.clipShape.style}},[Object(h["createVNode"])("img",{src:e.elementInfo.src,draggable:!1,style:{top:e.imgPosition.top,left:e.imgPosition.left,width:e.imgPosition.width,height:e.imgPosition.height,filter:e.filter},alt:""},null,12,["src"])],4)],4)),[[d,e.contextmenus]])],38)}));n("b64b");(function(e){e["RECT"]="rect",e["ELLIPSE"]="ellipse",e["POLYGON"]="polygon"})(Kt||(Kt={})),function(e){e["RECT"]="rect",e["ROUNDRECT"]="roundRect",e["ELLIPSE"]="ellipse",e["TRIANGLE"]="triangle",e["PENTAGON"]="pentagon",e["RHOMBUS"]="rhombus",e["STAR"]="star"}($t||($t={}));var on={rect:{name:"矩形",type:Kt.RECT,radius:"0",style:""},rect2:{name:"矩形2",type:Kt.POLYGON,style:"polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 0 100%)",createPath:function(e,t){return"M 0 0 L ".concat(.8*e," 0 L ").concat(e," ").concat(.2*t," L ").concat(e," ").concat(t," L 0 ").concat(t," Z")}},rect3:{name:"矩形3",type:Kt.POLYGON,style:"polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 20% 100%, 0% 80%)",createPath:function(e,t){return"M 0 0 L ".concat(.8*e," 0 L ").concat(e," ").concat(.2*t," L ").concat(e," ").concat(t," L ").concat(.2*e," ").concat(t," L 0 ").concat(.8*t," Z")}},roundRect:{name:"圆角矩形",type:Kt.RECT,radius:"10%",style:"inset(0 0 0 0 round 10% 10% 10% 10%)"},ellipse:{name:"圆形",type:Kt.ELLIPSE,style:"ellipse(50% 50% at 50% 50%)"},triangle:{name:"三角形",type:Kt.POLYGON,style:"polygon(50% 0%, 0% 100%, 100% 100%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L 0 ").concat(t," L ").concat(e," ").concat(t," Z")}},triangle2:{name:"三角形2",type:Kt.POLYGON,style:"polygon(50% 100%, 0% 0%, 100% 0%)",createPath:function(e,t){return"M ".concat(.5*e," ").concat(t," L 0 0 L ").concat(e," 0 Z")}},triangle3:{name:"三角形3",type:Kt.POLYGON,style:"polygon(0% 0%, 0% 100%, 100% 100%)",createPath:function(e,t){return"M 0 0 L 0 ".concat(t," L ").concat(e," ").concat(t," Z")}},rhombus:{name:"菱形",type:Kt.POLYGON,style:"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L ").concat(e," ").concat(.5*t," L ").concat(.5*e," ").concat(t," L 0 ").concat(.5*t," Z")}},hexagon:{name:"六边形",type:Kt.POLYGON,style:"polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)",createPath:function(e,t){return"M ".concat(.2*e," 0 L ").concat(.8*e," 0 L ").concat(e," ").concat(.5*t," L ").concat(.8*e," ").concat(t," L ").concat(.2*e," ").concat(t," L 0 ").concat(.5*t," Z")}},pentagon:{name:"五边形",type:Kt.POLYGON,style:"polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L ").concat(e," ").concat(.38*t," L ").concat(.82*e," ").concat(t," L ").concat(.18*e," ").concat(t," L 0 ").concat(.38*t," Z")}},parallelogram:{name:"平行四边形",type:Kt.POLYGON,style:"polygon(30% 0%, 100% 0%, 70% 100%, 0% 100%)",createPath:function(e,t){return"M ".concat(.3*e," 0 L ").concat(e," 0 L ").concat(.7*e," ").concat(t," L 0 ").concat(t," Z")}},parallelogram2:{name:"平行四边形2",type:Kt.POLYGON,style:"polygon(30% 100%, 100% 100%, 70% 0%, 0% 0%)",createPath:function(e,t){return"M ".concat(.3*e," ").concat(t," L ").concat(e," ").concat(t," L ").concat(.7*e," 0 L 0 0 Z")}},trapezoid:{name:"梯形",type:Kt.POLYGON,style:"polygon(25% 0%, 75% 0%, 100% 100%, 0% 100%)",createPath:function(e,t){return"M ".concat(.25*e," 0 L ").concat(.75*e," 0 L ").concat(e," ").concat(t," L 0 ").concat(t," Z")}},trapezoid2:{name:"梯形2",type:Kt.POLYGON,style:"polygon(0% 0%, 100% 0%, 75% 100%, 25% 100%)",createPath:function(e,t){return"M 0 0 L ".concat(e," 0 L ").concat(.75*e," ").concat(t," L ").concat(.25*e," ").concat(t," Z")}}},cn=function(e){var t=Object(h["ref"])("");return Object(h["watchEffect"])((function(){if(e.value){var n=e.value,o=n.h,c=n.v,a=n.blur,r=n.color;t.value="".concat(o,"px ").concat(c,"px ").concat(a,"px ").concat(r)}else t.value=""})),{shadowStyle:t}},an=Object(h["withScopeId"])("data-v-4efc595a"),rn=an((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-rect-outline",overflow:"visible",width:e.width,height:e.height},{default:an((function(){return[Object(h["createVNode"])("rect",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",rx:e.radius,ry:e.radius,width:e.width,height:e.height,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["rx","ry","width","height","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),ln=function(e){var t=Object(h["computed"])((function(){return e.value&&void 0!==e.value.width?e.value.width:0})),n=Object(h["computed"])((function(){return e.value&&void 0!==e.value.style?e.value.style:"solid"})),o=Object(h["computed"])((function(){return e.value&&void 0!==e.value.color?e.value.color:"#d14424"}));return{outlineWidth:t,outlineStyle:n,outlineColor:o}},un=Object(h["defineComponent"])({name:"image-rect-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object},radius:{type:String,default:"0"}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("b640");un.render=rn,un.__scopeId="data-v-4efc595a";var dn=un,sn=Object(h["withScopeId"])("data-v-4a286c0d"),fn=sn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-ellipse-outline",overflow:"visible",width:e.width,height:e.height},{default:sn((function(){return[Object(h["createVNode"])("ellipse",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",cx:e.width/2,cy:e.height/2,rx:e.width/2,ry:e.height/2,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["cx","cy","rx","ry","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),pn=Object(h["defineComponent"])({name:"image-ellipse-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("0741");pn.render=fn,pn.__scopeId="data-v-4a286c0d";var bn=pn,mn=Object(h["withScopeId"])("data-v-0a37b709"),vn=mn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-polygon-outline",overflow:"visible",width:e.width,height:e.height},{default:mn((function(){return[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",d:e.createPath(e.width,e.height),stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["d","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),On=Object(h["defineComponent"])({name:"image-polygon-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object},createPath:{type:Function,required:!0}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("b19e");On.render=vn,On.__scopeId="data-v-0a37b709";var hn=On,jn=Object(h["withScopeId"])("data-v-1e41275c");Object(h["pushScopeId"])("data-v-1e41275c");var gn=Object(h["createVNode"])("path",{"stroke-width":"0.3","shape-rendering":"crispEdges",d:"M 16 0 L 0 0 L 0 16 L 4 16 L 4 4 L 16 4 L 16 0 Z"},null,-1);Object(h["popScopeId"])();var yn=jn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper"),l=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"image-clip-handler",style:e.clipWrapperPositionStyle},[Object(h["createVNode"])("img",{class:"bottom-img",src:e.src,draggable:!1,alt:"",style:e.bottomImgPositionStyle},null,12,["src"]),Object(h["createVNode"])("div",{class:"top-image-content",style:Object(P["a"])(Object(P["a"])({},e.topImgWrapperPositionStyle),{},{clipPath:e.clipPath})},[Object(h["createVNode"])("img",{class:"top-img",src:e.src,draggable:!1,alt:"",style:e.topImgPositionStyle},null,12,["src"])],4),Object(h["createVNode"])("div",{class:"operate",style:e.topImgWrapperPositionStyle,onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.moveClipRange(t)}),["stop"]))},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(["t-l","t-r","b-l","b-r"],(function(t){return Object(h["createVNode"])("div",{class:["clip-point",t],key:t,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleClipRange(n,t)}),["stop"])},[Object(h["createVNode"])(r,{width:"12",height:"12",fill:"#fff",stroke:"#333"},{default:jn((function(){return[gn]})),_:1})],42,["onMousedown"])})),64))],36)],4)),[[l,e.handleClip]])})),kn=Object(h["defineComponent"])({name:"image-clip-handler",props:{src:{type:String,required:!0},clipData:{type:Object},clipPath:{type:String,required:!0},width:{type:Number,required:!0},height:{type:Number,required:!0},top:{type:Number,required:!0},left:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.state.canvasScale})),a=Object(h["reactive"])({top:0,left:0,width:0,height:0}),r=Object(h["reactive"])({top:"0",left:"0"}),l=Object(h["ref"])(!1),i=Object(h["ref"])(null),u=function(){var t=e.clipData?e.clipData.range:[[0,0],[100,100]],n=Object(Xt["a"])(t,2),o=n[0],c=n[1],a=(c[0]-o[0])/100,r=(c[1]-o[1])/100,l=o[0]/a,i=o[1]/r;return{widthScale:a,heightScale:r,left:l,top:i}},d=Object(h["computed"])((function(){var e=u(),t=e.widthScale,n=e.heightScale,o=e.left,c=e.top;return{left:-o,top:-c,width:100/t,height:100/n}})),s=Object(h["computed"])((function(){return{top:d.value.top+"%",left:d.value.left+"%",width:d.value.width+"%",height:d.value.height+"%"}})),f=Object(h["computed"])((function(){return{top:a.top+"%",left:a.left+"%",width:a.width+"%",height:a.height+"%"}})),p=Object(h["computed"])((function(){var e=d.value.width,t=d.value.height,n=a.left,o=a.top,c=a.width,r=a.height;return{left:100/c*-n+"%",top:100/r*-o+"%",width:e/c*100+"%",height:t/r*100+"%"}})),b=function(){var e=u(),t=e.left,n=e.top;a.left=t,a.top=n,a.width=100,a.height=100,r.top=-n+"%",r.left=-t+"%"},m=function(){if(!l.value)if(i.value){var t=u(),o=t.left,c=t.top,r={left:(a.left-o)/100*e.width,top:(a.top-c)/100*e.height,width:(a.width-100)/100*e.width,height:(a.height-100)/100*e.height},d={range:i.value,position:r};n("clip",d)}else n("clip",null)},v=function(e){var t=e.key.toUpperCase();t===$.ENTER&&m()};Object(h["onMounted"])((function(){b(),document.addEventListener("keydown",v)})),Object(h["onUnmounted"])((function(){document.removeEventListener("keydown",v)}));var O=function(){var e={left:parseInt(p.value.left),top:parseInt(p.value.top),width:parseInt(p.value.width),height:parseInt(p.value.height)},t=100/e.width,n=100/e.height,o=[-e.left*t,-e.top*n],c=[100*t+o[0],100*n+o[1]];i.value=[o,c]},j=function(t){l.value=!0;var n=!0,o=t.pageX,r=t.pageY,i=d.value,u={left:a.left,top:a.top,width:a.width,height:a.height};document.onmousemove=function(t){if(n){var l=t.pageX,d=t.pageY,s=(l-o)/c.value/e.width*100,f=(d-r)/c.value/e.height*100,p=u.left+s,b=u.top+f;p<0?p=0:p+u.width>i.width&&(p=i.width-u.width),b<0?b=0:b+u.height>i.height&&(b=i.height-u.height),a.left=p,a.top=b}},document.onmouseup=function(){n=!1,document.onmousemove=null,document.onmouseup=null,O(),setTimeout((function(){l.value=!1}),0)}},g=function(t,n){l.value=!0;var o=!0,r=50/e.width*100,i=50/e.height*100,u=t.pageX,s=t.pageY,f=d.value,p={left:a.left,top:a.top,width:a.width,height:a.height};document.onmousemove=function(t){if(o){var l,d,b,m,v=t.pageX,O=t.pageY,h=(v-u)/c.value/e.width*100,j=(O-s)/c.value/e.height*100;"t-l"===n?(p.left+h<0&&(h=-p.left),p.top+j<0&&(j=-p.top),p.width-hf.width&&(h=f.width-(p.left+p.width)),p.top+j<0&&(j=-p.top),p.width+hf.height&&(j=f.height-(p.top+p.height)),p.width-hf.width&&(h=f.width-(p.left+p.width)),p.top+p.height+j>f.height&&(j=f.height-(p.top+p.height)),p.width+h\s$/,e)},Fn=function(e){return Object(An["g"])(/^(\d+)\.\s$/,e,(function(e){return{order:+e[1]}}),(function(e,t){return t.childCount+t.attrs.order===+e[1]}))},zn=function(e){return Object(An["g"])(/^\s*([-+*])\s$/,e)},Hn=function(e){return Object(An["e"])(/^```$/,e)},Un=function(e){var t=[].concat(Object(A["a"])(An["d"]),[An["a"],An["b"]]);return t.push(Rn(e.nodes.blockquote)),t.push(Fn(e.nodes.ordered_list)),t.push(zn(e.nodes.bullet_list)),t.push(Hn(e.nodes.code_block)),Object(An["c"])({rules:t})},Gn=function(e){return[Un(e),Object(Vn["b"])(Pn(e)),Object(Vn["b"])(Nn["a"]),Object(Bn["a"])(),Object(Mn["a"])(),Object(_n["a"])()]},qn=n("2210"),Wn=Object(P["a"])(Object(P["a"])({},Dn["d"]),{},{content:"list_item+",group:"block"}),Xn=Object(P["a"])(Object(P["a"])({},Dn["a"]),{},{content:"list_item+",group:"block"}),Yn=Object(P["a"])(Object(P["a"])({},Dn["c"]),{},{content:"paragraph block*",group:"block"}),Zn={attrs:{align:{default:""}},content:"inline*",group:"block",parseDOM:[{tag:"p",getAttrs:function(e){var t=e.style.textAlign,n=e.getAttribute("align")||t||"";return n=/(left|right|center|justify)/.test(n)?n:"",{align:n}}}],toDOM:function(e){var t=e.attrs.align,n="";return t&&"left"!==t&&(n+="text-align: ".concat(t,";")),["p",{style:n},0]}},Jn=Object(P["a"])(Object(P["a"])({},qn["b"]),{},{ordered_list:Wn,bullet_list:Xn,list_item:Yn,paragraph:Zn}),Kn=(n("ac1f"),n("5319"),{excludes:"subscript",parseDOM:[{tag:"sub"},{style:"vertical-align",getAttrs:function(e){return"sub"===e&&null}}],toDOM:function(){return["sub",0]}}),$n={excludes:"superscript",parseDOM:[{tag:"sup"},{style:"vertical-align",getAttrs:function(e){return"super"===e&&null}}],toDOM:function(){return["sup",0]}},Qn={parseDOM:[{tag:"strike"},{style:"text-decoration",getAttrs:function(e){return"line-through"===e&&null}},{style:"text-decoration-line",getAttrs:function(e){return"line-through"===e&&null}}],toDOM:function(){return["span",{style:"text-decoration-line: line-through"},0]}},eo={parseDOM:[{tag:"u"},{style:"text-decoration",getAttrs:function(e){return"underline"===e&&null}},{style:"text-decoration-line",getAttrs:function(e){return"underline"===e&&null}}],toDOM:function(){return["span",{style:"text-decoration: underline"},0]}},to={attrs:{color:{}},parseDOM:[{style:"color",getAttrs:function(e){return e?{color:e}:{}}}],toDOM:function(e){var t=e.attrs.color,n="";return t&&(n+="color: ".concat(t,";")),["span",{style:n},0]}},no={attrs:{backcolor:{}},inline:!0,group:"inline",parseDOM:[{tag:"span[style*=background-color]",getAttrs:function(e){return e?{backcolor:e}:{}}}],toDOM:function(e){var t=e.attrs.backcolor,n="";return t&&(n+="background-color: ".concat(t,";")),["span",{style:n},0]}},oo={attrs:{fontsize:{}},inline:!0,group:"inline",parseDOM:[{style:"font-size",getAttrs:function(e){return e?{fontsize:e}:{}}}],toDOM:function(e){var t=e.attrs.fontsize,n="";return t&&(n+="font-size: ".concat(t)),["span",{style:n},0]}},co={attrs:{fontname:{}},inline:!0,group:"inline",parseDOM:[{style:"font-family",getAttrs:function(e){return{fontname:e&&"string"===typeof e?e.replace(/[\"\']/g,""):""}}}],toDOM:function(e){var t=e.attrs.fontname,n="";return t&&(n+="font-family: ".concat(t)),["span",{style:n},0]}},ao=Object(P["a"])(Object(P["a"])({},qn["a"]),{},{subscript:Kn,superscript:$n,strikethrough:Qn,underline:eo,forecolor:to,backcolor:no,fontsize:oo,fontname:co}),ro=Jn,lo=ao,io=new Ln["i"]({nodes:ro,marks:lo}),uo=function(e){var t="
".concat(e,"
"),n=new window.DOMParser,o=n.parseFromString(t,"text/html").body.firstElementChild;return Ln["a"].fromSchema(io).parse(o)},so=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return new wn["c"](e,Object(P["a"])({state:Tn["b"].create({doc:uo(t),plugins:Gn(io)})},n))},fo=(n("b0c0"),function(e,t){return Array.isArray(e)&&e.indexOf(t.type)>-1||t.type===e}),po=function(e,t){for(var n=e.depth;n>0;n--){var o=e.node(n);if(t(o))return{pos:n>0?e.before(n):0,start:e.start(n),depth:n,node:o}}},bo=function(e){return function(t){return po(t.$from,e)}},mo=function(e){return function(t){return bo((function(t){return fo(e,t)}))(t)}},vo=function(e,t){var n=t.schema.nodes[e];return!!mo(n)(t.selection)},Oo=function(e){var t=e.state,n=t.selection,o=t.doc,c=n.from,a=o.nodeAt(c);return(null===a||void 0===a?void 0:a.marks)||[]},ho=function(e,t,n){var o,c=Oo(e),a=Object(me["a"])(c);try{for(a.s();!(o=a.n()).done;){var r=o.value;if(r.type.name===t&&r.attrs[n])return r.attrs[n]}}catch(l){a.e(l)}finally{a.f()}return null},jo=function(e,t){var n,o=Oo(e),c=Object(me["a"])(o);try{for(c.s();!(n=c.n()).done;){var a=n.value;if(a.type.name===t)return!0}}catch(r){c.e(r)}finally{c.f()}return!1},go=function(e,t){var n=e.state,o=n.selection,c=n.doc,a=o.from,r=o.to,l=!0,i="";return c.nodesBetween(a,r,(function(e){return l&&e.attrs[t]&&(l=!1,i=e.attrs[t]),l})),i},yo=function(e){var t=jo(e,"strong"),n=jo(e,"em"),o=jo(e,"underline"),c=jo(e,"strikethrough"),a=jo(e,"superscript"),r=jo(e,"subscript"),l=jo(e,"code"),i=ho(e,"forecolor","color")||"#000",u=ho(e,"backcolor","backcolor")||"#000",d=ho(e,"fontsize","fontsize")||"12px",s=ho(e,"fontname","fontname")||"微软雅黑",f=go(e,"align")||"left",p=vo("bullet_list",e.state),b=vo("ordered_list",e.state),m=vo("blockquote",e.state);return{bold:t,em:n,underline:o,strikethrough:c,superscript:a,subscript:r,code:l,color:i,backcolor:u,fontsize:d,fontname:s,align:f,bulletList:p,orderedList:b,blockquote:m}},ko=(n("6062"),n("3ca3"),function(e,t,n){var o=e,c=o.selection,a=o.doc;if(!c||!a)return e;var r=c.from,l=c.to,i=t.nodes,u=i.blockquote,d=i.list_item,s=i.paragraph,f=[];n=n||"";var p=new Set([u,d,s]);return a.nodesBetween(r,l,(function(e,t){var o=e.type,c=e.attrs.align||"";return c!==n&&p.has(o)&&f.push({node:e,pos:t,nodeType:o}),!0})),f.length?(f.forEach((function(t){var o=t.node,c=t.pos,a=t.nodeType,r=o.attrs;r=n?Object(P["a"])(Object(P["a"])({},r),{},{align:n}):Object(P["a"])(Object(P["a"])({},r),{},{align:null}),e=e.setNodeMarkup(c,a,r,o.marks)})),e):e}),Eo=function(e,t){var n=e.state,o=n.schema,c=n.selection,a=ko(n.tr.setSelection(c),o,t);e.dispatch(a)},Io=function(e,t){return e.type===t.nodes.bullet_list||e.type===t.nodes.ordered_list},So=function(e,t){return function(n,o){var c=n.schema,a=n.selection,r=a.$from,l=a.$to,i=r.blockRange(l);if(!i)return!1;var u=bo((function(e){return Io(e,c)}))(a);if(i.depth>=1&&u&&i.depth-u.depth<=1){if(u.node.type===e)return Object(Dn["b"])(t)(n,o);if(Io(u.node,c)&&e.validContent(u.node.content)){var d=n.tr;return d.setNodeMarkup(u.pos,e),o&&o(d),!1}}return Object(Dn["g"])(e)(n,o)}},Co=Object(h["withScopeId"])("data-v-59365834"),xo=Co((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"element-outline",overflow:"visible",width:e.width,height:e.height},{default:Co((function(){return[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",d:"M0,0 L".concat(e.width,",0 L").concat(e.width,",").concat(e.height," L0,").concat(e.height," Z"),stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["d","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),No=Object(h["defineComponent"])({name:"element-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("606f");No.render=xo,No.__scopeId="data-v-59365834";var To=No,wo=Object(h["defineComponent"])({name:"editable-element-text",components:{ElementOutline:To},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=X(),n=ge(),o=n.addHistorySnapshot,c=Object(h["ref"])(),a=Object(h["ref"])(!1),r=Object(h["ref"])(-1),l=function(n){a.value=n,n||-1===r.value||(t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:r.value}}),r.value=-1)};Dt.on(_t.SCALE_ELEMENT_STATE,(function(e){return l(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.SCALE_ELEMENT_STATE,(function(e){return l(e)}))}));var i=function(n){var o=n[0].contentRect;if(c.value){var l=o.height;e.elementInfo.height!==l&&(a.value?r.value=l:t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:l}}))}},u=new ResizeObserver(i);Object(h["onMounted"])((function(){c.value&&u.observe(c.value)})),Object(h["onUnmounted"])((function(){c.value&&u.unobserve(c.value)}));var d,s=Object(h["ref"])(),f=function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,!0)},p=function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,!1)},b=Oe()((function(){t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{content:d.dom.innerHTML}}),o()}),300,{trailing:!0}),m=Oe()((function(){var e=yo(d);Dt.emit(_t.UPDATE_TEXT_STATE,e)}),30,{trailing:!0}),v=function(){b(),m()},O=Object(h["computed"])((function(){return e.elementInfo.content}));Object(h["watch"])(O,(function(){d&&(d.hasFocus()||(d.dom.innerHTML=O.value))}));var j=Object(h["computed"])((function(){return!e.elementInfo.lock}));Object(h["watch"])(j,(function(){d.setProps({editable:function(){return j.value}})})),Object(h["onMounted"])((function(){d=so(s.value,O.value,{handleDOMEvents:{focus:f,blur:p,keydown:v,click:m},editable:function(){return j.value}})})),Object(h["onUnmounted"])((function(){d&&d.destroy()}));var y=function(t){var n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo,n))},k=Object(h["computed"])((function(){return e.elementInfo.shadow})),E=cn(k),I=E.shadowStyle,S=Object(h["computed"])((function(){return t.state.handleElementId})),C=function(t){if(S.value===e.elementInfo.id){var n,o="command"in t?[t]:t,c=Object(me["a"])(o);try{for(c.s();!(n=c.n()).done;){var a=n.value;if("fontname"===a.command&&a.value){var r=d.state.schema.marks.fontname.create({fontname:a.value}),l=d.state.selection.empty;l&&Object(Nn["d"])(d.state,d.dispatch);var i=d.state.selection,u=i.$from,s=i.$to;d.dispatch(d.state.tr.addMark(u.pos,s.pos,r))}else if("fontsize"===a.command&&a.value){var f=d.state.schema.marks.fontsize.create({fontsize:a.value}),p=d.state.selection.empty;p&&Object(Nn["d"])(d.state,d.dispatch);var v=d.state.selection,O=v.$from,h=v.$to;d.dispatch(d.state.tr.addMark(O.pos,h.pos,f))}else if("color"===a.command&&a.value){var j=d.state.schema.marks.forecolor.create({color:a.value}),g=d.state.selection.empty;g&&Object(Nn["d"])(d.state,d.dispatch);var y=d.state.selection,k=y.$from,E=y.$to;d.dispatch(d.state.tr.addMark(k.pos,E.pos,j))}else if("backcolor"===a.command&&a.value){var I=d.state.schema.marks.backcolor.create({backcolor:a.value}),C=d.state.selection.empty;C&&Object(Nn["d"])(d.state,d.dispatch);var x=d.state.selection,N=x.$from,T=x.$to;d.dispatch(d.state.tr.addMark(N.pos,T.pos,I))}else if("bold"===a.command){var w=d.state.selection.empty;w&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.strong)(d.state,d.dispatch)}else if("em"===a.command){var L=d.state.selection.empty;L&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.em)(d.state,d.dispatch)}else if("underline"===a.command){var V=d.state.selection.empty;V&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.underline)(d.state,d.dispatch)}else if("strikethrough"===a.command){var _=d.state.selection.empty;_&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.strikethrough)(d.state,d.dispatch)}else if("subscript"===a.command)Object(Nn["f"])(d.state.schema.marks.subscript)(d.state,d.dispatch);else if("superscript"===a.command)Object(Nn["f"])(d.state.schema.marks.superscript)(d.state,d.dispatch);else if("blockquote"===a.command)Object(Nn["g"])(d.state.schema.nodes.blockquote)(d.state,d.dispatch);else if("code"===a.command)Object(Nn["f"])(d.state.schema.marks.code)(d.state,d.dispatch);else if("align"===a.command&&a.value)Eo(d,a.value);else if("bulletList"===a.command){var B=d.state.schema.nodes,M=B.bullet_list,D=B.list_item;So(M,D)(d.state,d.dispatch)}else if("orderedList"===a.command){var A=d.state.schema.nodes,P=A.ordered_list,R=A.list_item;So(P,R)(d.state,d.dispatch)}else if("clear"===a.command){var F=d.state.selection.empty;F&&Object(Nn["d"])(d.state,d.dispatch);var z=d.state.selection,H=z.$from,U=z.$to;d.dispatch(d.state.tr.removeMark(H.pos,U.pos))}}}catch(G){c.e(G)}finally{c.f()}d.focus(),b(),m()}};return Dt.on(_t.EXEC_TEXT_COMMAND,(function(e){return C(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.EXEC_TEXT_COMMAND,(function(e){return C(e)}))})),{elementRef:c,editorViewRef:s,handleSelectElement:y,shadowStyle:I}}});n("01f7");wo.render=xn,wo.__scopeId="data-v-092f3d4e";var Lo=wo,Vo=Object(h["withScopeId"])("data-v-6a9228f2");Object(h["pushScopeId"])("data-v-6a9228f2");var _o={key:0};Object(h["popScopeId"])();var Bo=Vo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("GradientDefs"),l=Object(h["resolveComponent"])("SvgWrapper"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-shape",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")},onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"element-content",style:{opacity:e.elementInfo.opacity,filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):""}},[Object(h["createVNode"])(l,{overflow:"visible",width:e.elementInfo.width,height:e.elementInfo.height},{default:Vo((function(){return[e.elementInfo.gradient?(Object(h["openBlock"])(),Object(h["createBlock"])("defs",_o,[Object(h["createVNode"])(r,{id:"editabel-gradient-".concat(e.elementInfo.id),type:e.elementInfo.gradient.type,color1:e.elementInfo.gradient.color[0],color2:e.elementInfo.gradient.color[1],rotate:e.elementInfo.gradient.rotate},null,8,["id","type","color1","color2","rotate"])])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("g",{transform:"scale(".concat(e.elementInfo.width/e.elementInfo.viewBox,", ").concat(e.elementInfo.height/e.elementInfo.viewBox,") translate(0,0) matrix(1,0,0,1,0,0)")},[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",d:e.elementInfo.path,fill:e.elementInfo.gradient?"url(#editabel-gradient-".concat(e.elementInfo.id,")"):e.elementInfo.fill,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"10 5":"0 0"},null,8,["d","fill","stroke","stroke-width","stroke-dasharray"])],8,["transform"])]})),_:1},8,["width","height"])],4),[[i,e.contextmenus]])],38)}));function Mo(e,t,n,o,c,a){return"linear"===e.type?(Object(h["openBlock"])(),Object(h["createBlock"])("linearGradient",{key:0,id:e.id,x1:"0%",y1:"0%",x2:"100%",y2:"0%",gradientTransform:"rotate(".concat(e.rotate,",0.5,0.5)")},[Object(h["createVNode"])("stop",{offset:"0%","stop-color":e.color1},null,8,["stop-color"]),Object(h["createVNode"])("stop",{offset:"100%","stop-color":e.color2},null,8,["stop-color"])],8,["id","gradientTransform"])):(Object(h["openBlock"])(),Object(h["createBlock"])("radialGradient",{key:1,id:e.id},[Object(h["createVNode"])("stop",{offset:"0%","stop-color":e.color1},null,8,["stop-color"]),Object(h["createVNode"])("stop",{offset:"100%","stop-color":e.color2},null,8,["stop-color"])],8,["id"]))}var Do=Object(h["defineComponent"])({name:"gradient-defs",props:{id:{type:String,required:!0},type:{type:String},color1:{type:String,required:!0},color2:{type:String,required:!0},rotate:{type:Number,default:0}}});Do.render=Mo;var Ao=Do,Po=Object(h["defineComponent"])({name:"editable-element-shape",components:{GradientDefs:Ao},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},n=Object(h["computed"])((function(){return e.elementInfo.outline})),o=ln(n),c=o.outlineWidth,a=o.outlineStyle,r=o.outlineColor,l=Object(h["computed"])((function(){return e.elementInfo.shadow})),i=cn(l),u=i.shadowStyle;return{handleSelectElement:t,shadowStyle:u,outlineWidth:c,outlineStyle:a,outlineColor:r}}});n("2a31");Po.render=Bo,Po.__scopeId="data-v-6a9228f2";var Ro=Po,Fo=Object(h["withScopeId"])("data-v-d93ab0c4"),zo=Fo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("LinePointMarker"),l=Object(h["resolveComponent"])("SvgWrapper"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-shape",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px"}},[Object(h["createVNode"])("div",{class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):""}},[Object(h["createVNode"])(l,{overflow:"visible",width:e.svgWidth,height:e.svgHeight},{default:Fo((function(){return[Object(h["createVNode"])("defs",null,[e.elementInfo.points[0]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,id:e.elementInfo.id,position:"start",type:e.elementInfo.points[0],color:e.elementInfo.color,baseSize:e.elementInfo.width},null,8,["id","type","color","baseSize"])):Object(h["createCommentVNode"])("",!0),e.elementInfo.points[1]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,id:e.elementInfo.id,position:"end",type:e.elementInfo.points[1],color:e.elementInfo.color,baseSize:e.elementInfo.width},null,8,["id","type","color","baseSize"])):Object(h["createCommentVNode"])("",!0)]),Object(h["createVNode"])("path",{d:e.path,stroke:e.elementInfo.color,"stroke-width":e.elementInfo.width,"stroke-dasharray":e.lineDashArray,fill:"none","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":"","marker-start":e.elementInfo.points[0]?"url(#".concat(e.elementInfo.id,"-").concat(e.elementInfo.points[0],"-start)"):"","marker-end":e.elementInfo.points[1]?"url(#".concat(e.elementInfo.id,"-").concat(e.elementInfo.points[1],"-end)"):""},null,8,["d","stroke","stroke-width","stroke-dasharray","marker-start","marker-end"]),Object(h["withDirectives"])(Object(h["createVNode"])("path",{class:"line-path",d:e.path,stroke:"transparent","stroke-width":"20",fill:"none",onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},null,40,["d"]),[[i,e.contextmenus]])]})),_:1},8,["width","height"])],4)],6)}));function Ho(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("marker",{id:"".concat(e.id,"-").concat(e.type,"-").concat(e.position),markerUnits:"userSpaceOnUse",orient:"auto",markerWidth:3*e.size,markerHeight:3*e.size,refX:1.5*e.size,refY:1.5*e.size},[Object(h["createVNode"])("path",{d:e.path,fill:e.color,transform:"scale(".concat(.3*e.size,", ").concat(.3*e.size,") rotate(").concat(e.rotate,", 5, 5)")},null,8,["d","fill","transform"])],8,["id","markerWidth","markerHeight","refX","refY"])}var Uo={dot:"m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",arrow:"M0,0 L10,5 0,10 Z"},Go={"arrow-start":180,"arrow-end":0},qo=Object(h["defineComponent"])({name:"line-point-marker",props:{id:{type:String,required:!0},position:{type:String,required:!0},type:{type:String,required:!0},color:{type:String},baseSize:{type:Number,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){return Uo[e.type]})),n=Object(h["computed"])((function(){return Go["".concat(e.type,"-").concat(e.position)]||0})),o=Object(h["computed"])((function(){return e.baseSize<2?2:e.baseSize}));return{path:t,rotate:n,size:o}}});qo.render=Ho;var Wo=qo,Xo=Object(h["defineComponent"])({name:"editable-element-shape",components:{LinePointMarker:Wo},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},n=Object(h["computed"])((function(){return e.elementInfo.shadow})),o=cn(n),c=o.shadowStyle,a=Object(h["computed"])((function(){var t=Math.abs(e.elementInfo.start[0]-e.elementInfo.end[0]);return t<24?24:t})),r=Object(h["computed"])((function(){var t=Math.abs(e.elementInfo.start[1]-e.elementInfo.end[1]);return t<24?24:t})),l=Object(h["computed"])((function(){return"dashed"===e.elementInfo.style?"10, 5":"0, 0"})),i=Object(h["computed"])((function(){var t=e.elementInfo.start.join(","),n=e.elementInfo.end.join(",");return"M".concat(t," L").concat(n)}));return{handleSelectElement:t,shadowStyle:c,svgWidth:a,svgHeight:r,lineDashArray:l,path:i}}});n("1c60");Xo.render=zo,Xo.__scopeId="data-v-d93ab0c4";var Yo=Xo,Zo=Object(h["withScopeId"])("data-v-7550799e"),Jo=Zo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementOutline"),l=Object(h["resolveComponent"])("Chart"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-chart",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px"},onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"element-content",style:{backgroundColor:e.elementInfo.fill}},[Object(h["createVNode"])(r,{width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"]),Object(h["createVNode"])(l,{width:e.elementInfo.width,height:e.elementInfo.height,type:e.elementInfo.chartType,data:e.elementInfo.data,options:e.elementInfo.options,themeColor:e.elementInfo.themeColor,gridColor:e.elementInfo.gridColor},null,8,["width","height","type","data","options","themeColor","gridColor"])],4),[[i,e.contextmenus]])],38)})),Ko=Object(h["withScopeId"])("data-v-5f401eca");Object(h["pushScopeId"])("data-v-5f401eca");var $o={class:"chart"};Object(h["popScopeId"])();var Qo=Ko((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",$o,[Object(h["createVNode"])("div",{class:"chart-content",ref:"chartRef",style:{width:e.width+"px",height:e.height+"px",transform:"scale(".concat(1/e.slideScale,")")}},null,4)])})),ec=n("8103"),tc=n.n(ec),nc=n("66cb"),oc=n.n(nc),cc=n("ba48"),ac=n.n(cc),rc=(n("aa97"),Object(h["defineComponent"])({name:"chart",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},type:{type:String,required:!0},data:{type:Object,required:!0},options:{type:Object},themeColor:{type:String,required:!0},gridColor:{type:String}},setup:function(e){var t,n=Object(h["ref"])(),o=Object(h["inject"])("slideScale")||Object(h["ref"])(1),c=function(){var t=e.options||{},n=Object(P["a"])(Object(P["a"])({},t),{},{width:e.width*o.value,height:e.height*o.value}),c="pie"===e.type?Object(P["a"])(Object(P["a"])({},e.data),{},{series:e.data.series[0]}):e.data;return{data:c,options:n}},a=function(){if(n.value){var o=tc()(e.type),a=c(),r=a.data,l=a.options;t=new ac.a[o](n.value,r,l)}},r=function(){if(t){var e=c(),n=e.data,o=e.options;t.update(n,o)}else a()};Object(h["watch"])([function(){return e.width},function(){return e.height},function(){return e.data},o],r),Object(h["onMounted"])(a);var l=function(){if(n.value){for(var t=oc()(e.themeColor).toHsl(),o=0;o<10;o++){var c=t.h+36*o;c>360&&(c-=360);var a=Object(P["a"])(Object(P["a"])({},t),{},{h:c});n.value.style.setProperty("--theme-color-".concat(o+1),oc()(a).toRgbString())}e.gridColor&&n.value.style.setProperty("--grid-color",e.gridColor)}};return Object(h["watch"])([function(){return e.themeColor},function(){return e.gridColor}],l),Object(h["onMounted"])(l),{slideScale:o,chartRef:n}}}));n("380f8"),n("d85b");rc.render=Qo,rc.__scopeId="data-v-5f401eca";var lc=rc,ic=Object(h["defineComponent"])({name:"editable-element-chart",components:{ElementOutline:To,Chart:lc},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))};return{handleSelectElement:t}}});n("fba1");ic.render=Jo,ic.__scopeId="data-v-7550799e";var uc=ic,dc=Object(h["withScopeId"])("data-v-045f7664");Object(h["pushScopeId"])("data-v-045f7664");var sc={class:"element-content"};Object(h["popScopeId"])();var fc=dc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("EditableTable"),l=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-table",{lock:e.elementInfo.lock}],ref:"elementRef",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px"}},[Object(h["withDirectives"])(Object(h["createVNode"])("div",sc,[Object(h["createVNode"])(r,{onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(){}),["stop"])),data:e.elementInfo.data,width:e.elementInfo.width,colWidths:e.elementInfo.colWidths,outline:e.elementInfo.outline,theme:e.elementInfo.theme,editable:e.editable,onChange:t[2]||(t[2]=function(t){return e.updateTableCells(t)}),onChangeColWidths:t[3]||(t[3]=function(t){return e.updateColWidths(t)}),onChangeSelectedCells:t[4]||(t[4]=function(t){return e.updateSelectedCells(t)})},null,8,["data","width","colWidths","outline","theme","editable"]),!e.editable||e.elementInfo.lock?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["table-mask",{lock:e.elementInfo.lock}],onDblclick:t[5]||(t[5]=function(t){return e.startEdit()}),onMousedown:t[6]||(t[6]=function(t){return e.handleSelectElement(t)})},[Object(h["createVNode"])("div",{class:"mask-tip",style:{transform:"scale(".concat(1/e.canvasScale,")")}},"双击编辑",4)],34)):Object(h["createCommentVNode"])("",!0)],512),[[l,e.contextmenus]])],6)})),pc=(n("13d5"),Object(h["withScopeId"])("data-v-7859e10e"));Object(h["pushScopeId"])("data-v-7859e10e");var bc={key:0,class:"handler"};Object(h["popScopeId"])();var mc=pc((function(e,t,n,o,c,a){var r,l,i,u,d,s=Object(h["resolveComponent"])("CustomTextarea"),f=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"editable-table",style:{width:e.totalWidth+"px"}},[e.editable?(Object(h["openBlock"])(),Object(h["createBlock"])("div",bc,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.dragLinePosition,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"drag-line",key:n,style:{left:t+"px"},onMousedown:function(t){return e.handleMousedownColHandler(t,n)}},null,44,["onMousedown"])})),128))])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("table",{class:{theme:e.theme,"row-header":null===(r=e.theme)||void 0===r?void 0:r.rowHeader,"row-footer":null===(l=e.theme)||void 0===l?void 0:l.rowFooter,"col-header":null===(i=e.theme)||void 0===i?void 0:i.colHeader,"col-footer":null===(u=e.theme)||void 0===u?void 0:u.colFooter},style:"--themeColor: ".concat(null===(d=e.theme)||void 0===d?void 0:d.color,"; --subThemeColor1: ").concat(e.subThemeColor[0],"; --subThemeColor2: ").concat(e.subThemeColor[1])},[Object(h["createVNode"])("colgroup",null,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.colSizeList,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])("col",{span:"1",key:t,width:e},null,8,["width"])})),128))]),Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.tableCells,(function(n,o){return Object(h["openBlock"])(),Object(h["createBlock"])("tr",{key:o},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(n,(function(n,c){return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("td",{class:["cell",{selected:e.selectedCells.includes("".concat(o,"_").concat(c))&&e.selectedCells.length>1,active:e.activedCell==="".concat(o,"_").concat(c)}],style:Object(P["a"])({borderStyle:e.outline.style,borderColor:e.outline.color,borderWidth:e.outline.width+"px"},e.getTextStyle(n.style)),key:n.id,rowspan:n.rowspan,colspan:n.colspan,"data-cell-index":"".concat(o,"_").concat(c),onMousedown:function(t){return e.handleCellMousedown(t,o,c)},onMouseenter:function(t){return e.handleCellMouseenter(o,c)}},[Object(h["createVNode"])(s,{class:["cell-text",{active:e.activedCell==="".concat(o,"_").concat(c)}],contenteditable:e.activedCell==="".concat(o,"_").concat(c)&&"plaintext-only",modelValue:n.text,"onUpdate:modelValue":[function(e){return n.text=e},t[1]||(t[1]=function(t){return e.handleInput()})]},null,8,["class","contenteditable","modelValue","onUpdate:modelValue"])],46,["rowspan","colspan","data-cell-index","onMousedown","onMouseenter"])),[[h["vShow"],!e.hideCells.includes("".concat(o,"_").concat(c))],[f,function(t){return e.contextmenus(t)}]])})),128))])})),128))])],6)],4)}));n("1276"),n("cc71");function vc(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"custom-textarea",ref:"textareaRef",contenteditable:e.contenteditable,onFocus:t[1]||(t[1]=function(){return e.handleFocus&&e.handleFocus.apply(e,arguments)}),onBlur:t[2]||(t[2]=function(){return e.handleBlur&&e.handleBlur.apply(e,arguments)}),onInput:t[3]||(t[3]=function(t){return e.handleInput(t)}),innerHTML:e.text},null,40,["contenteditable","innerHTML"])}var Oc=Object(h["defineComponent"])({name:"custom-textarea",props:{modelValue:{type:String,default:""},contenteditable:{type:[Boolean,String],default:!1}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=Object(h["ref"])(""),a=Object(h["ref"])(!1);Object(h["watch"])((function(){return e.modelValue}),(function(){a.value||(c.value=e.modelValue,o.value&&(o.value.innerHTML=e.modelValue))}),{immediate:!0});var r=function(){if(o.value){var e=o.value.innerHTML;n("update:modelValue",e)}},l=function(){a.value=!0,o.value&&(o.value.onpaste=function(e){if(e.preventDefault(),e.clipboardData){var t=e.clipboardData.items[0];t&&"string"===t.kind&&"text/plain"===t.type&&t.getAsString((function(e){return n("update:modelValue",e)}))}})},i=function(){a.value=!1,o.value&&(o.value.onpaste=null)};return Object(h["onUnmounted"])((function(){o.value&&(o.value.onpaste=null)})),{textareaRef:o,handleFocus:l,handleInput:r,handleBlur:i,text:c}}});Oc.render=vc;var hc=Oc,jc=Object(h["defineComponent"])({name:"editable-table",components:{CustomTextarea:hc},props:{data:{type:Array,required:!0},width:{type:Number,required:!0},colWidths:{type:Array,required:!0},outline:{type:Object,required:!0},theme:{type:Object},editable:{type:Boolean,default:!0}},setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.state.canvasScale})),a=Object(h["ref"])(["",""]);Object(h["watch"])((function(){return e.theme}),(function(){if(e.theme){var t=oc()(e.theme.color).toRgb(),n={r:t.r,g:t.g,b:t.b,a:.3*t.a},o={r:t.r,g:t.g,b:t.b,a:.1*t.a};a.value=["rgba(".concat([n.r,n.g,n.b,n.a].join(","),")"),"rgba(".concat([o.r,o.g,o.b,o.a].join(","),")")]}}),{immediate:!0});var r=Object(h["computed"])({get:function(){return e.data},set:function(e){n("change",e)}}),l=Object(h["ref"])([]),i=Object(h["computed"])((function(){return l.value.reduce((function(e,t){return e+t}))}));Object(h["watch"])([function(){return e.colWidths},function(){return e.width}],(function(){l.value=e.colWidths.map((function(t){return t*e.width}))}),{immediate:!0});var u=Object(h["ref"])(!1),d=Object(h["ref"])([]),s=Object(h["ref"])([]),f=function(){d.value=[],s.value=[]};Object(h["watch"])((function(){return e.editable}),(function(){e.editable||f()}));var p=Object(h["computed"])((function(){for(var e=[],t=1;t1||c.rowspan>1)for(var a=t;a=i&&b<=f&&v>=u&&v<=p&&l.push("".concat(b,"_").concat(v));return l}));Object(h["watch"])(m,(function(){n("changeSelectedCells",m.value)}));var v=Object(h["computed"])((function(){return m.value.length>1?null:m.value[0]})),O=Object(h["computed"])((function(){if(!d.value.length)return null;var e=Object(Xt["a"])(d.value,2),t=e[0],n=e[1];if(!s.value.length)return{row:[t,t],col:[n,n]};var o=Object(Xt["a"])(s.value,2),c=o[0],a=o[1];if(t===c&&n===a)return{row:[t,t],col:[n,n]};var r=Math.min(t,c),l=Math.min(n,a),i=Math.max(t,c),u=Math.max(n,a);return{row:[r,i],col:[l,u]}})),j=function(){return u.value=!1},g=function(e,t,n){0===e.button&&(s.value=[],u.value=!0,d.value=[t,n])},y=function(e,t){u.value&&(s.value=[e,t])};Object(h["onMounted"])((function(){document.addEventListener("mouseup",j)})),Object(h["onUnmounted"])((function(){document.removeEventListener("mouseup",j)}));var k=function(e,t){return b.value.includes("".concat(e,"_").concat(t))},E=function(e){var t=r.value.length-1;d.value=[0,e],s.value=[t,e]},I=function(e){var t=r.value[e].length-1;d.value=[e,0],s.value=[e,t]},S=function(){var e=r.value.length-1,t=r.value[e].length-1;d.value=[0,0],s.value=[e,t]},C=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),n=r.value[e],o=[],c=0;c=0;u--)if(!k(u,i)){t[u][i].rowspan=t[u][i].rowspan-1;break}t.splice(e,1),r.value=t},x=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),o=[],c=0;c=0;d--)if(!k(u,d)){t[u][d].colspan=t[u][d].colspan-1;break}r.value=t.map((function(t){return t.splice(e,1),t})),l.value.splice(e,1),n("changeColWidths",l.value)},N=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),n=[],o=0;o1,n=e[0].length>1;return{canDeleteRow:t,canDeleteCol:n}},F=function(e,t){var n=m.value.length>1,o=r.value[e][t],c=n,a=!n&&(o.rowspan>1||o.colspan>1);return{canMerge:c,canSplit:a}},z=function(e){var t=e.dataset.cellIndex,n=+t.split("_")[0],o=+t.split("_")[1];m.value.includes("".concat(n,"_").concat(o))||(d.value=[n,o],s.value=[]);var c=F(n,o),a=c.canMerge,r=c.canSplit,l=R(),i=l.canDeleteRow,u=l.canDeleteCol;return[{text:"插入列",children:[{text:"到左侧",handler:function(){return T(o)}},{text:"到右侧",handler:function(){return T(o+1)}}]},{text:"插入行",children:[{text:"到上方",handler:function(){return N(n)}},{text:"到下方",handler:function(){return N(n+1)}}]},{text:"删除列",disable:!u,handler:function(){return x(o)}},{text:"删除行",disable:!i,handler:function(){return C(n)}},{divider:!0},{text:"合并单元格",disable:!a,handler:w},{text:"取消合并单元格",disable:!r,handler:function(){return L(n,o)}},{divider:!0},{text:"选中当前列",handler:function(){return E(o)}},{text:"选中当前行",handler:function(){return I(n)}},{text:"选中全部单元格",handler:S}]};return{getTextStyle:D,dragLinePosition:p,tableCells:r,colSizeList:l,totalWidth:i,hideCells:b,selectedCells:m,activedCell:v,selectedRange:O,handleCellMousedown:g,handleCellMouseenter:y,selectCol:E,selectRow:I,handleMousedownColHandler:V,contextmenus:z,handleInput:A,subThemeColor:a}}});n("14ac");jc.render=mc,jc.__scopeId="data-v-7859e10e";var gc=jc,yc=Object(h["defineComponent"])({name:"editable-element-table",components:{EditableTable:gc},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=ge(),c=o.addHistorySnapshot,a=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},r=Object(h["ref"])(!1),l=Object(h["computed"])((function(){return t.state.handleElementId}));Object(h["watch"])(l,(function(){l.value!==e.elementInfo.id&&(r.value=!1)})),Object(h["watch"])(r,(function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,r.value)}));var i=Object(h["ref"])(),u=Object(h["ref"])(!1),d=Object(h["ref"])(-1),s=function(n){u.value=n,n&&(r.value=!1),n||-1===d.value||(t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:d.value}}),d.value=-1)};Dt.on(_t.SCALE_ELEMENT_STATE,(function(e){return s(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.SCALE_ELEMENT_STATE,(function(e){return s(e)}))}));var f=function(n){var o=n[0].contentRect;if(i.value){var c=o.height;e.elementInfo.height!==c&&(u.value?d.value=c:t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:c}}))}},p=new ResizeObserver(f);Object(h["onMounted"])((function(){i.value&&p.observe(i.value)})),Object(h["onUnmounted"])((function(){i.value&&p.unobserve(i.value)}));var b=function(n){t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{data:n}}),c()},m=function(n){var o=n.reduce((function(e,t){return e+t})),a=n.map((function(e){return e/o}));t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{width:o,colWidths:a}}),c()},v=function(e){Object(h["nextTick"])((function(){return Dt.emit(_t.UPDATE_TABLE_SELECTED_CELL,e)}))},O=function(){e.elementInfo.lock||(r.value=!0)};return{elementRef:i,canvasScale:n,handleSelectElement:a,updateTableCells:b,updateColWidths:m,editable:r,startEdit:O,updateSelectedCells:v}}});n("7e16");yc.render=fc,yc.__scopeId="data-v-045f7664";var kc=yc,Ec=Object(h["defineComponent"])({name:"editable-element",props:{elementInfo:{type:Object,required:!0},elementIndex:{type:Number,required:!0},isMultiSelect:{type:Boolean,required:!0},selectElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.theme})),o=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,Sn),Object(C["a"])(t,Jt.TEXT,Lo),Object(C["a"])(t,Jt.SHAPE,Ro),Object(C["a"])(t,Jt.LINE,Yo),Object(C["a"])(t,Jt.CHART,uc),Object(C["a"])(t,Jt.TABLE,kc),t);return n[e.elementInfo.type]||null})),c=Qt(),a=c.orderElement,r=en(),l=r.alignElementToCanvas,i=we(),u=i.combineElements,d=i.uncombineElements,s=Te(),f=s.deleteElement,p=Ne(),b=p.lockElement,m=p.unlockElement,v=Le(),O=v.copyElement,j=v.cutElement,g=function(){return e.elementInfo.lock?[{text:"解锁",handler:function(){return m(e.elementInfo)}}]:[{text:"剪切",subText:"Ctrl + X",handler:j},{text:"复制",subText:"Ctrl + C",handler:O},{divider:!0},{text:"层级排序",disable:e.isMultiSelect&&!e.elementInfo.groupId,children:[{text:"置顶层",handler:function(){return a(e.elementInfo,Ot.TOP)}},{text:"置底层",handler:function(){return a(e.elementInfo,Ot.BOTTOM)}},{divider:!0},{text:"上移一层",handler:function(){return a(e.elementInfo,Ot.UP)}},{text:"下移一层",handler:function(){return a(e.elementInfo,Ot.DOWN)}}]},{text:"水平对齐",children:[{text:"水平居中",handler:function(){return l(ht.HORIZONTAL)}},{text:"左对齐",handler:function(){return l(ht.LEFT)}},{text:"右对齐",handler:function(){return l(ht.RIGHT)}}]},{text:"垂直对齐",children:[{text:"垂直居中",handler:function(){return l(ht.VERTICAL)}},{text:"上对齐",handler:function(){return l(ht.TOP)}},{text:"下对齐",handler:function(){return l(ht.BOTTOM)}}]},{divider:!0},{text:e.elementInfo.groupId?"取消组合":"组合",subText:"Ctrl + G",handler:e.elementInfo.groupId?d:u,hide:!e.isMultiSelect},{text:"锁定",subText:"Ctrl + L",handler:b},{text:"删除",subText:"Delete",handler:f}]};return{currentElementComponent:o,contextmenus:g,theme:n}}});Ec.render=Zt;var Ic=Ec,Sc=Object(h["withScopeId"])("data-v-1619c258"),Cc=Sc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"mouse-selection quadrant-".concat(n.quadrant),style:{top:n.top+"px",left:n.left+"px",width:n.width+"px",height:n.height+"px"}},null,6)})),xc={name:"mouse-selection",props:{top:{type:Number,required:!0},left:{type:Number,required:!0},width:{type:Number,required:!0},height:{type:Number,required:!0},quadrant:{type:Number,required:!0,validator:function(e){return[1,2,3,4].includes(e)}}}};n("2007");xc.render=Cc,xc.__scopeId="data-v-1619c258";var Nc=xc,Tc=Object(h["withScopeId"])("data-v-774174ab"),wc=Tc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("GridLines");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"slide-background",style:e.backgroundStyle},[e.showGridLines?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0})):Object(h["createCommentVNode"])("",!0)],4)})),Lc=Object(h["withScopeId"])("data-v-6515bb1c"),Vc=Lc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"grid-lines"},{default:Lc((function(){return[Object(h["createVNode"])("path",{style:{transform:"scale(".concat(e.canvasScale,")")},d:e.path,fill:"none",stroke:e.gridColor,"stroke-width":"0.3","shape-rendering":"crispEdges","stroke-dasharray":"5"},null,12,["d","stroke"])]})),_:1})})),_c=Object(h["defineComponent"])({name:"grid-lines",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.canvasScale})),n=Object(h["computed"])((function(){return e.getters.currentSlide.background})),o=Object(h["computed"])((function(){if(!n.value||"image"===n.value.type)return"rgba(100, 100, 100, 0.5)";var e=n.value.color,t=oc()(e).toRgb(),o={r:t.r>128?t.r-128:t.r+127,g:t.g>128?t.g-128:t.g+127,b:t.b>128?t.b-128:t.b+127,a:.5};return"rgba(".concat([o.r,o.g,o.b,o.a].join(","),")")})),c=50,a=function(){for(var e=Ee,t=Ee*Ie,n="",o=0;o<=Math.floor(t/c);o++)n+="M0 ".concat(o*c,", L").concat(e," ").concat(o*c);for(var a=0;a<=Math.floor(e/c);a++)n+="M".concat(a*c," 0, L").concat(a*c," ").concat(t);return n};return{canvasScale:t,gridColor:o,width:Ee,height:Ee*Ie,path:a()}}});n("bd86");_c.render=Vc,_c.__scopeId="data-v-6515bb1c";var Bc=_c,Mc=function(e){var t=Object(h["computed"])((function(){if(!e.value)return{backgroundColor:"#fff"};var t=e.value,n=t.type,o=t.color,c=t.image,a=t.imageSize,r=t.gradientColor,l=t.gradientRotate,i=t.gradientType;if("solid"===n)return{backgroundColor:o};if("image"===n)return c?"repeat"===a?{backgroundImage:"url(".concat(c),backgroundRepeat:"repeat",backgroundSize:"initial"}:{backgroundImage:"url(".concat(c),backgroundRepeat:"no-repeat",backgroundSize:a||"cover"}:{backgroundColor:"#fff"};if("gradient"===n){var u=l||0,d=r?r[0]:"#fff",s=r?r[1]:"#fff";return"radial"===i?{backgroundImage:"radial-gradient(".concat(d,", ").concat(s)}:{backgroundImage:"linear-gradient(".concat(u,"deg, ").concat(d,", ").concat(s)}}return{backgroundColor:"#fff"}}));return{backgroundStyle:t}},Dc=Object(h["defineComponent"])({name:"slide-background",components:{GridLines:Bc},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.showGridLines})),n=Object(h["computed"])((function(){return e.getters.currentSlide.background})),o=Mc(n),c=o.backgroundStyle;return{showGridLines:t,backgroundStyle:c}}});n("7aa8");Dc.render=wc,Dc.__scopeId="data-v-774174ab";var Ac=Dc,Pc=Object(h["withScopeId"])("data-v-520a7023"),Rc=Pc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"alignment-line",style:{left:e.left,top:e.top}},[Object(h["createVNode"])("div",{class:["line",e.type],style:e.sizeStyle},null,6)],4)})),Fc=Object(h["defineComponent"])({name:"alignment-line",props:{type:{type:String,required:!0},axis:{type:Object,required:!0},length:{type:Number,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.axis.x*n.value+"px"})),c=Object(h["computed"])((function(){return e.axis.y*n.value+"px"})),a=Object(h["computed"])((function(){return"vertical"===e.type?{height:e.length*n.value+"px"}:{width:e.length*n.value+"px"}}));return{left:o,top:c,sizeStyle:a}}});n("032d");Fc.render=Rc,Fc.__scopeId="data-v-520a7023";var zc=Fc,Hc=Object(h["withScopeId"])("data-v-eea668f4"),Uc=Hc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"element-create-selection",ref:"selectionRef",onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.createSelection(t)}),["stop"]))},[e.start&&e.end?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["selection",e.creatingElement.type],style:e.position},["line"===e.creatingElement.type&&e.lineData?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,overflow:"visible",width:e.lineData.svgWidth,height:e.lineData.svgHeight},{default:Hc((function(){return[Object(h["createVNode"])("path",{d:e.lineData.path,stroke:"#888",fill:"none","stroke-width":"1","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":""},null,8,["d"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)],6)):Object(h["createCommentVNode"])("",!0)],544)})),Gc=Object(h["defineComponent"])({name:"element-create-selection",setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.getters.ctrlOrShiftKeyActive})),a=Object(h["computed"])((function(){return o.state.creatingElement})),r=Object(h["ref"])(null),l=Object(h["ref"])(null),i=Object(h["ref"])(),u=Object(h["reactive"])({x:0,y:0});Object(h["onMounted"])((function(){if(i.value){var e=i.value.getBoundingClientRect(),t=e.x,n=e.y;u.x=t,u.y=n}}));var d=function(e){var t=!0,i=e.pageX,u=e.pageY;r.value=[i,u],document.onmousemove=function(e){if(a.value&&t){var n=e.pageX,o=e.pageY;if(c.value){var r=n-i,d=o-u,s=Math.abs(r),f=Math.abs(d);if("shape"===a.value.type){var p=d>0&&r<0||d<0&&r>0;s>f?o=p?u-r:u+r:n=p?i-d:i+d}else"line"===a.value.type&&(s>f?o=u:n=i)}l.value=[n,o]}},document.onmouseup=function(e){document.onmousemove=null,document.onmouseup=null,t=!1;var c=e.pageX,a=e.pageY,d=30;Math.abs(c-i)>=d||Math.abs(a-u)>=d?n("created",{start:r.value,end:l.value}):o.commit(g.SET_CREATING_ELEMENT,null)}},s=Object(h["computed"])((function(){if(!r.value||!l.value)return null;if(!a.value||"line"!==a.value.type)return null;var e=Object(Xt["a"])(r.value,2),t=e[0],n=e[1],o=Object(Xt["a"])(l.value,2),c=o[0],i=o[1],u=Math.min(t,c),d=Math.max(t,c),s=Math.min(n,i),f=Math.max(n,i),p=d-u>=24?d-u:24,b=f-s>=24?f-s:24,m=t===u?0:d-u,v=n===s?0:f-s,O=c===u?0:d-u,h=i===s?0:f-s,j="M".concat(m,", ").concat(v," L").concat(O,", ").concat(h);return{svgWidth:p,svgHeight:b,startX:m,startY:v,endX:O,endY:h,path:j}})),f=Object(h["computed"])((function(){if(!r.value||!l.value)return{};var e=Object(Xt["a"])(r.value,2),t=e[0],n=e[1],o=Object(Xt["a"])(l.value,2),c=o[0],a=o[1],i=Math.min(t,c),d=Math.max(t,c),s=Math.min(n,a),f=Math.max(n,a),p=d-i,b=f-s;return{left:i-u.x+"px",top:s-u.y+"px",width:p+"px",height:b+"px"}}));return{selectionRef:i,start:r,end:l,creatingElement:a,createSelection:d,lineData:s,position:f}}});n("4e78");Gc.render=Uc,Gc.__scopeId="data-v-eea668f4";var qc=Gc,Wc=Object(h["withScopeId"])("data-v-66dfa39d"),Xc=Wc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"multi-select-operate",style:{left:e.minX*e.canvasScale+"px",top:e.minY*e.canvasScale+"px"}},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.disableResize?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleMultiElement(n,{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY},t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))],4)})),Yc=function(e,t){var n=Object(h["computed"])((function(){return[{direction:gt.LEFT_TOP,style:{}},{direction:gt.TOP,style:{left:e.value/2+"px"}},{direction:gt.RIGHT_TOP,style:{left:e.value+"px"}},{direction:gt.LEFT,style:{top:t.value/2+"px"}},{direction:gt.RIGHT,style:{left:e.value+"px",top:t.value/2+"px"}},{direction:gt.LEFT_BOTTOM,style:{top:t.value+"px"}},{direction:gt.BOTTOM,style:{left:e.value/2+"px",top:t.value+"px"}},{direction:gt.RIGHT_BOTTOM,style:{left:e.value+"px",top:t.value+"px"}}]})),o=Object(h["computed"])((function(){return[{direction:gt.LEFT,style:{top:t.value/2+"px"}},{direction:gt.RIGHT,style:{left:e.value+"px",top:t.value/2+"px"}}]})),c=Object(h["computed"])((function(){return[{type:jt.T,style:{width:e.value+"px"}},{type:jt.B,style:{top:t.value+"px",width:e.value+"px"}},{type:jt.L,style:{height:t.value+"px"}},{type:jt.R,style:{left:e.value+"px",height:t.value+"px"}}]}));return{resizeHandlers:n,textElementResizeHandlers:o,borderLines:c}},Zc=Object(h["withScopeId"])("data-v-1c2a68d0"),Jc=Zc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["resize-handler",n.type]},null,2)})),Kc={name:"resize-handler",props:{type:{type:String,default:""}}};n("a933");Kc.render=Jc,Kc.__scopeId="data-v-1c2a68d0";var $c=Kc,Qc=Object(h["withScopeId"])("data-v-630e246b"),ea=Qc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["border-line",n.type,{wide:n.isWide}]},null,2)})),ta={name:"border-line",props:{type:{type:String,required:!0},isWide:{type:Boolean,default:!1}}};n("fb1d");ta.render=ea,ta.__scopeId="data-v-630e246b";var na=ta,oa=Object(h["defineComponent"])({name:"multi-select-operate",components:{ResizeHandler:$c,BorderLine:na},props:{elementList:{type:Array,required:!0},scaleMultiElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.activeElementIdList})),o=Object(h["computed"])((function(){return t.state.canvasScale})),c=Object(h["computed"])((function(){return e.elementList.filter((function(e){return n.value.includes(e.id)}))})),a=Object(h["reactive"])({minX:0,maxX:0,minY:0,maxY:0}),r=Object(h["computed"])((function(){return(a.maxX-a.minX)*o.value})),l=Object(h["computed"])((function(){return(a.maxY-a.minY)*o.value})),i=Yc(r,l),u=i.resizeHandlers,d=i.borderLines,s=Object(h["computed"])((function(){return c.value.some((function(e){return!!("image"!==e.type&&"shape"!==e.type||e.rotate)}))})),f=function(){var e=xt(c.value),t=e.minX,n=e.maxX,o=e.minY,r=e.maxY;a.minX=t,a.maxX=n,a.minY=o,a.maxY=r};return Object(h["watchEffect"])(f),Object(P["a"])(Object(P["a"])({},Object(h["toRefs"])(a)),{},{canvasScale:o,borderLines:d,disableResize:s,resizeHandlers:u})}});n("6aa3");oa.render=Xc,oa.__scopeId="data-v-66dfa39d";var ca=oa,aa=Object(h["withScopeId"])("data-v-558a94fe");Object(h["pushScopeId"])("data-v-558a94fe");var ra={key:1,class:"animation-index"};Object(h["popScopeId"])();var la=aa((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["operate",{"multi-select":e.isMultiSelect&&!e.isActive}],style:{top:e.elementInfo.top*e.canvasScale+"px",left:e.elementInfo.left*e.canvasScale+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)"),transformOrigin:"".concat(e.elementInfo.width*e.canvasScale/2,"px ").concat(e.elementInfo.height*e.canvasScale/2,"px")}},[e.isSelected?(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentOperateComponent),{key:0,elementInfo:e.elementInfo,isActiveGroupElement:e.isActiveGroupElement,isMultiSelect:e.isMultiSelect,rotateElement:e.rotateElement,scaleElement:e.scaleElement,dragLineElement:e.dragLineElement},null,8,["elementInfo","isActiveGroupElement","isMultiSelect","rotateElement","scaleElement","dragLineElement"])):Object(h["createCommentVNode"])("",!0),"elAnimation"===e.toolbarState&&-1!==e.elementIndexInAnimation?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ra,Object(h["toDisplayString"])(e.elementIndexInAnimation+1),1)):Object(h["createCommentVNode"])("",!0)],6)})),ia=Object(h["withScopeId"])("data-v-5b0628aa"),ua=ia((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["image-element-operate",{cliping:e.isCliping}]},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))],2)})),da=Object(h["withScopeId"])("data-v-9a549510");Object(h["pushScopeId"])("data-v-9a549510");var sa={class:"rotate-handler"};Object(h["popScopeId"])();var fa=da((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",sa)})),pa={name:"rotate-handler"};n("8754");pa.render=fa,pa.__scopeId="data-v-9a549510";var ba=pa,ma=Object(h["defineComponent"])({name:"image-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.clipingImageElementId})),c=Object(h["computed"])((function(){return o.value===e.elementInfo.id})),a=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),r=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),l=Yc(a,r),i=l.resizeHandlers,u=l.borderLines;return{isCliping:c,scaleWidth:a,resizeHandlers:i,borderLines:u}}});n("5c02");ma.render=ua,ma.__scopeId="data-v-5b0628aa";var va=ma,Oa={class:"text-element-operate"};function ha(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Oa,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.textElementResizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))])}var ja=Object(h["defineComponent"])({name:"text-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.textElementResizeHandlers,l=a.borderLines;return{scaleWidth:o,textElementResizeHandlers:r,borderLines:l}}});ja.render=ha;var ga=ja,ya={class:"shape-element-operate"};function ka(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ya,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))])}var Ea=Object(h["defineComponent"])({name:"shape-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.resizeHandlers,l=a.borderLines;return{scaleWidth:o,resizeHandlers:r,borderLines:l}}});Ea.render=ka;var Ia=Ea,Sa={class:"text-element-operate"};function Ca(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Sa,[e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.dragLineElement(n,e.elementInfo,t.handler)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var xa=Object(h["defineComponent"])({name:"text-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},dragLineElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return[{handler:yt.START,style:{left:e.elementInfo.start[0]*n.value+"px",top:e.elementInfo.start[1]*n.value+"px"}},{handler:yt.END,style:{left:e.elementInfo.end[0]*n.value+"px",top:e.elementInfo.end[1]*n.value+"px"}}]}));return{resizeHandlers:o}}});xa.render=Ca;var Na=xa,Ta={class:"chart-element-operate"};function wa(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Ta,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var La=Object(h["defineComponent"])({name:"chart-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.resizeHandlers,l=a.borderLines;return{scaleWidth:o,resizeHandlers:r,borderLines:l}}});La.render=wa;var Va=La,_a={class:"table-element-operate"};function Ba(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",_a,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.textElementResizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var Ma=Object(h["defineComponent"])({name:"table-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.outline.width||1})),c=Object(h["computed"])((function(){return(e.elementInfo.width+o.value)*n.value})),a=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),r=Yc(c,a),l=r.textElementResizeHandlers,i=r.borderLines;return{scaleWidth:c,textElementResizeHandlers:l,borderLines:i}}});Ma.render=Ba;var Da=Ma,Aa=Object(h["defineComponent"])({name:"operate",props:{elementInfo:{type:Object,required:!0},isSelected:{type:Boolean,required:!0},isActive:{type:Boolean,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0},dragLineElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.toolbarState})),c=Object(h["computed"])((function(){return t.getters.currentSlide})),a=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,va),Object(C["a"])(t,Jt.TEXT,ga),Object(C["a"])(t,Jt.SHAPE,Ia),Object(C["a"])(t,Jt.LINE,Na),Object(C["a"])(t,Jt.CHART,Va),Object(C["a"])(t,Jt.TABLE,Da),t);return n[e.elementInfo.type]||null})),r=Object(h["computed"])((function(){var t=c.value.animations||[];return t.findIndex((function(t){return t.elId===e.elementInfo.id}))}));return{currentOperateComponent:a,canvasScale:n,toolbarState:o,elementIndexInAnimation:r}}});n("9884");Aa.render=la,Aa.__scopeId="data-v-558a94fe";var Pa=Aa,Ra=Object(h["defineComponent"])({name:"editor-canvas",components:{EditableElement:Ic,MouseSelection:Nc,SlideBackground:Ac,AlignmentLine:zc,ElementCreateSelection:qc,MultiSelectOperate:ca,Operate:Pa},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.state.handleElementId})),o=Object(h["computed"])((function(){return e.state.editorAreaFocus})),c=Object(h["computed"])((function(){return e.state.ctrlKeyState})),a=Object(h["computed"])((function(){return e.getters.ctrlOrShiftKeyActive})),r=Object(h["ref"])(),l=Object(h["ref"])([]),i=Object(h["ref"])("");Object(h["watch"])(n,(function(){return i.value=""}));var u=Object(h["computed"])((function(){return e.getters.currentSlide})),d=Object(h["ref"])([]),s=function(){d.value=u.value?JSON.parse(JSON.stringify(u.value.elements)):[]};Object(h["watchEffect"])(s);var f=Object(h["ref"])(),p=Object(h["computed"])((function(){return e.state.canvasScale})),b=It(f),m=b.viewportStyles;wt(f);var v=Tt(d,r),O=v.mouseSelectionState,j=v.updateMouseSelection,y=qt(d,i,l),k=y.dragElement,E=Wt(d),I=E.dragLineElement,S=Gt(d,i,k),C=S.selectElement,x=zt(d,i,l),N=x.scaleElement,T=x.scaleMultiElement,w=Vt(d,r),L=w.rotateElement,V=Ve(),_=V.selectAllElement,B=Te(),M=B.deleteAllElements,D=Le(),A=D.pasteElement,P=function(t){e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,[]),a.value||j(t),o.value||e.commit(g.SET_EDITORAREA_FOCUS,!0),Et()},R=function(){o.value&&e.commit(g.SET_EDITORAREA_FOCUS,!1)},F=Pe(),z=F.scaleCanvas,H=je()(z,100,{leading:!0,trailing:!1}),U=function(e){c.value&&(e.preventDefault(),e.deltaY>0?H("-"):e.deltaY<0&&H("+"))},G=Object(h["computed"])((function(){return e.state.showGridLines})),q=function(){e.commit(g.SET_GRID_LINES_STATE,!G.value)},W=Object(h["computed"])((function(){return e.state.creatingElement})),Y=Yt(r),Z=Y.insertElementFromCreateSelection,J=function(){return[{text:"全选",subText:"Ctrl + A",handler:_},{text:"粘贴",subText:"Ctrl + V",handler:A},{text:G.value?"关闭网格线":"打开网格线",handler:q},{text:"清空本页",handler:M}]};return Object(h["provide"])("slideScale",p),{elementList:d,activeElementIdList:t,handleElementId:n,activeGroupElementId:i,canvasRef:f,viewportRef:r,viewportStyles:m,canvasScale:p,mouseSelectionState:O,handleClickBlankArea:P,removeEditorAreaFocus:R,currentSlide:u,creatingElement:W,insertElementFromCreateSelection:Z,alignmentLines:l,selectElement:C,rotateElement:L,scaleElement:N,dragLineElement:I,scaleMultiElement:T,mousewheelScaleCanvas:U,contextmenus:J}}});n("923f");Ra.render=kt,Ra.__scopeId="data-v-75c486b2";var Fa=Ra,za=Object(h["withScopeId"])("data-v-1a2df855");Object(h["pushScopeId"])("data-v-1a2df855");var Ha={class:"canvas-tool"},Ua={class:"left-handler"},Ga={class:"add-element-handler"},qa={class:"right-handler"},Wa={class:"text"};Object(h["popScopeId"])();var Xa=za((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconBack"),l=Object(h["resolveComponent"])("Tooltip"),i=Object(h["resolveComponent"])("IconNext"),u=Object(h["resolveComponent"])("IconFontSize"),d=Object(h["resolveComponent"])("IconPicture"),s=Object(h["resolveComponent"])("FileInput"),f=Object(h["resolveComponent"])("ShapePool"),p=Object(h["resolveComponent"])("IconPentagonOne"),b=Object(h["resolveComponent"])("Popover"),m=Object(h["resolveComponent"])("LinePool"),v=Object(h["resolveComponent"])("IconConnection"),O=Object(h["resolveComponent"])("ChartPool"),j=Object(h["resolveComponent"])("IconChartProportion"),g=Object(h["resolveComponent"])("TableGenerator"),y=Object(h["resolveComponent"])("IconInsertTable"),k=Object(h["resolveComponent"])("IconMinus"),E=Object(h["resolveComponent"])("IconPlus"),I=Object(h["resolveComponent"])("IconFullScreen");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Ha,[Object(h["createVNode"])("div",Ua,[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"撤销"},{default:za((function(){return[Object(h["createVNode"])(r,{class:["handler-item",{disable:!e.canUndo}],onClick:t[1]||(t[1]=function(t){return e.undo()})},null,8,["class"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"重做"},{default:za((function(){return[Object(h["createVNode"])(i,{class:["handler-item",{disable:!e.canRedo}],onClick:t[2]||(t[2]=function(t){return e.redo()})},null,8,["class"])]})),_:1},8,["mouseEnterDelay"])]),Object(h["createVNode"])("div",Ga,[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入文字"},{default:za((function(){return[Object(h["createVNode"])(u,{class:"handler-item",onClick:t[3]||(t[3]=function(t){return e.drawText()})})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(s,{onChange:t[4]||(t[4]=function(t){return e.insertImageElement(t)})},{default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入图片"},{default:za((function(){return[Object(h["createVNode"])(d,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(b,{trigger:"click",visible:e.shapePoolVisible,"onUpdate:visible":t[6]||(t[6]=function(t){return e.shapePoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(f,{onSelect:t[5]||(t[5]=function(t){return e.drawShape(t)})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入形状"},{default:za((function(){return[Object(h["createVNode"])(p,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.linePoolVisible,"onUpdate:visible":t[8]||(t[8]=function(t){return e.linePoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(m,{onSelect:t[7]||(t[7]=function(t){return e.drawLine(t)})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入线条"},{default:za((function(){return[Object(h["createVNode"])(v,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.chartPoolVisible,"onUpdate:visible":t[10]||(t[10]=function(t){return e.chartPoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(O,{onSelect:t[9]||(t[9]=function(t){e.createChartElement(t),e.chartPoolVisible=!1})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入图表"},{default:za((function(){return[Object(h["createVNode"])(j,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.tableGeneratorVisible,"onUpdate:visible":t[13]||(t[13]=function(t){return e.tableGeneratorVisible=t})},{content:za((function(){return[Object(h["createVNode"])(g,{onClose:t[11]||(t[11]=function(t){return e.tableGeneratorVisible=!1}),onInsert:t[12]||(t[12]=function(t){var n=t.row,o=t.col;e.createTableElement(n,o),e.tableGeneratorVisible=!1})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入表格"},{default:za((function(){return[Object(h["createVNode"])(y,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"])]),Object(h["createVNode"])("div",qa,[Object(h["createVNode"])(k,{class:"handler-item viewport-size",onClick:t[14]||(t[14]=function(t){return e.scaleCanvas("-")})}),Object(h["createVNode"])("span",Wa,Object(h["toDisplayString"])(e.canvasScalePercentage),1),Object(h["createVNode"])(E,{class:"handler-item viewport-size",onClick:t[15]||(t[15]=function(t){return e.scaleCanvas("+")})}),Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"适配屏幕"},{default:za((function(){return[Object(h["createVNode"])(I,{class:"handler-item viewport-size-adaptation",onClick:t[16]||(t[16]=function(t){return e.setCanvasPercentage(90)})})]})),_:1},8,["mouseEnterDelay"])])])})),Ya=Object(h["withScopeId"])("data-v-e95c032e");Object(h["pushScopeId"])("data-v-e95c032e");var Za={class:"shape-pool"},Ja={class:"category-name"},Ka={class:"shape-list"};Object(h["popScopeId"])();var $a=Ya((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Za,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.shapeList,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"category",key:t.type},[Object(h["createVNode"])("div",Ja,Object(h["toDisplayString"])(t.type),1),Object(h["createVNode"])("div",Ka,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(t.children,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"shape-item",key:n},[Object(h["createVNode"])("div",{class:"shape-content",onClick:function(n){return e.selectShape(t)}},[Object(h["createVNode"])(r,{overflow:"visible",width:"20",height:"20"},{default:Ya((function(){return[Object(h["createVNode"])("g",{transform:"scale(".concat(20/t.viewBox,", ").concat(20/t.viewBox,") translate(0,0) matrix(1,0,0,1,0,0)")},[Object(h["createVNode"])("path",{class:"shape-path","vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",stroke:"#999","stroke-width":"2",d:t.path},null,8,["d"])],8,["transform"])]})),_:2},1024)],8,["onClick"])])})),128))])])})),128))])})),Qa=[{type:"矩形",children:[{viewBox:200,path:"M 0 0 L 200 0 L 200 200 L 0 200 Z"},{viewBox:200,path:"M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z"},{viewBox:200,path:"M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z"},{viewBox:200,path:"M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200"},{viewBox:200,path:"M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z"},{viewBox:200,path:"M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z"},{viewBox:200,path:"M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z"},{viewBox:200,path:"M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z"}]},{type:"常用形状",children:[{viewBox:200,path:"M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 100 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 200 0 L 100 0 Z"},{viewBox:200,path:"M 0 0 L 200 0 Q 200 200 0 200 L 0 0 Z"},{viewBox:200,path:"M 100 0 L 0 200 L 200 200 L 100 0 Z"},{viewBox:200,path:"M 0 0 L 0 200 L 200 200 Z"},{viewBox:200,path:"M 50 0 L 200 0 L 150 200 L 0 200 L 50 0 Z"},{viewBox:200,path:"M 50 0 L 150 0 L 200 200 L 0 200 L 50 0 Z"},{viewBox:200,path:"M 100 0 L 0 100 L 100 200 L 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 L 0 90 L 50 200 L 150 200 L 200 90 L 100 0 Z"},{viewBox:200,path:"M 100 0 L 0 60 L 0 140 L 100 200 L 200 140 L 200 60 L 100 0 Z"},{viewBox:200,path:"M 60 0 L 140 0 L 200 60 L 200 140 L 140 200 L 60 200 L 0 140 L 0 60 L 60 0 Z"},{viewBox:200,path:"M 100 0 L 0 50 L 0 200 L 200 200 L 200 50 L 100 0 Z"},{viewBox:200,path:"M 150 0 A 50 100 0 1 1 150 200 L 0 200 L 0 0 L 150 0 Z"},{viewBox:200,path:"M 150 0 A 50 100 0 1 1 150 200 L 0 200 A 50 100 0 0 0 0 0 L 150 0 Z"},{viewBox:200,path:"M 200 100 L 150 0 L 0 0 L 50 100 L 0 200 L 150 200 L 200 100 Z"},{viewBox:200,path:"M 200 0 L 200 200 L 0 200 L 0 100 L 200 0 Z"},{viewBox:200,path:"M 50 0 L 150 0 L 150 50 L 200 50 L 200 150 L 150 150 L 150 200 L 50 200 L 50 150 L 0 150 L 0 50 L 50 50 L 50 0 Z"},{viewBox:200,path:"M 0 0 L 0 200 L 200 200 L 200 140 L 60 140 L 60 0 L 0 0 Z"},{viewBox:200,path:"M0 0 L200 0 L200 200 L0 200 L0 0 Z M50 50 L50 150 L150 150 L150 50 Z"},{viewBox:200,path:"M0 100 A100 100 0 1 1 0 101 Z M150 100 A50 50 0 1 0 150 101 Z"},{viewBox:200,path:"M 70 0 L 70 70 L 0 70 L 0 130 L 70 130 L 70 200 L 130 200 L 130 130 L 200 130 L 200 70 L 130 70 L 130 0 L 70 0 Z"},{viewBox:200,path:"M 40 0 L 0 40 L 60 100 L 0 160 L 40 200 L 100 140 L 160 200 L 200 160 L 140 100 L 200 40 L 160 0 L 100 60 L 40 0 Z"},{viewBox:200,path:"M 0 0 L 200 0 L 200 160 L 100 160 L 60 200 L 60 160 L 0 160 L 0 0 Z"},{viewBox:200,path:"M 0 40 Q 0 0 40 0 L 160 0 Q 200 0 200 40 L 200 120 Q 200 160 160 160 L 100 160 L 60 200 L 60 160 L 40 160 Q 0 160 0 120 L 0 40 Z"}]},{type:"箭头",children:[{viewBox:200,path:"M 100 0 L 0 100 L 50 100 L 50 200 L 150 200 L 150 100 L 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 200 L 200 100 L 150 100 L 150 0 L 50 0 L 50 100 L 0 100 L 100 200 Z"},{viewBox:200,path:"M 0 100 L 100 0 L 100 50 L 200 50 L 200 150 L 100 150 L 100 200 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 100 0 L 100 50 L 0 50 L 0 150 L 100 150 L 100 200 L 200 100 Z"},{viewBox:200,path:"M 100 0 L 0 60 L 60 60 L 60 140 L 0 140 L 100 200 L 200 140 L 140 140 L 140 60 L 200 60 L 100 0 Z"},{viewBox:200,path:"M 0 100 L 60 0 L 60 60 L 140 60 L 140 0 L 200 100 L 140 200 L 140 140 L 60 140 L 60 200 L 0 100 Z"},{viewBox:200,path:"M 100 0 L 60 40 L 80 40 L 80 80 L 40 80 L 40 60 L 0 100 L 40 140 L 40 120 L 80 120 L 80 160 L 60 160 L 100 200 L 140 160 L 120 160 L 120 120 L 160 120 L 160 140 L 200 100 L 160 60 L 160 80 L 120 80 L 120 40 L 140 40 L 100 0 Z"},{viewBox:200,path:"M 0 100 L 100 0 L 100 50 L 200 50 L 150 100 L 200 150 L 100 150 L 100 200 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 100 0 L 100 50 L 0 50 L 50 100 L 0 150 L 100 150 L 100 200 L 200 100 Z"},{viewBox:200,path:"M 0 100 L 80 20 L 80 80 L 120 80 L 120 0 L 200 0 L 200 200 L 120 200 L 120 120 L 80 120 L 80 180 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 120 20 L 120 80 L 80 80 L 80 0 L 0 0 L 0 200 L 80 200 L 80 120 L 120 120 L 120 180 L 200 100 Z"},{viewBox:200,path:"M 0 0 L 120 0 L 200 100 L 120 200 L 0 200 L 80 100 L 0 0 Z"},{viewBox:200,path:"M 80 0 L 200 0 L 120 100 L 200 200 L 80 200 L 0 100 L 80 0 Z"},{viewBox:200,path:"M 0 0 L 140 0 L 200 100 L 140 200 L 0 200 L 0 100 L 0 0 Z"},{viewBox:200,path:"M 60 0 L 200 0 L 200 100 L 200 200 L 60 200 L 0 100 L 60 0 Z"}]},{type:"其他形状",children:[{viewBox:1024,path:"M995.336 243.4016c-15.7584-36.5736-38.3376-69.26639999-66.91440001-97.37280001-28.5768-27.98879999-61.73999999-49.8624-98.78399999-65.26799998-38.22-15.876-78.6744-23.8728-120.4224-23.87280001-57.97680001 0-114.5424 15.876-163.69919999 45.864-11.76 7.17360001-22.932 15.05279999-33.51600001 23.63760001-10.584-8.5848-21.75600001-16.46400001-33.51600001-23.63760001-49.1568-29.98799999-105.7224-45.86399999-163.69919999-45.864-41.74799999 0-82.2024 7.9968-120.4224 23.87280001-36.9264 15.28799999-70.2072 37.27919999-98.78399999 65.26799998-28.6944 28.10640001-51.156 60.79919999-66.91440001 97.37280001-16.34639999 37.9848-24.696 78.3216-24.696 119.83439999 0 39.1608 7.9968 79.96800001 23.8728 121.48080001 13.28880001 34.692 32.34000001 70.67760001 56.6832 107.016 38.57279999 57.5064 91.61040001 117.4824 157.4664 178.28160001 109.1328 100.78319999 217.2072 170.4024 221.79359999 173.22479998l27.87120001 17.8752c12.348 7.8792 28.224 7.8792 40.572 0l27.87119999-17.8752c4.58639999-2.94 112.54319999-72.44159999 221.79360001-173.22479998 65.85599999-60.79919999 118.89359999-120.7752 157.4664-178.28160001 24.3432-36.33839999 43.512-72.324 56.68319999-107.016 15.876-41.5128 23.8728-82.32 23.87280001-121.48080001 0.1176-41.5128-8.232-81.8496-24.5784-119.83439999z"},{viewBox:1024,path:"M985.20746667 343.50079998l-303.32586667-44.08319999L546.28693333 24.5248c-3.70346666-7.5264-9.79626667-13.6192-17.32266665-17.32266668-18.87573334-9.3184-41.81333333-1.55306667-51.25120001 17.32266668L342.1184 299.41759999l-303.32586667 44.08319999c-8.36266667 1.19466667-16.00853333 5.13706667-21.8624 11.11040001-14.69440001 15.17226667-14.45546667 39.30453334 0.71679999 54.1184l219.46026668 213.9648-51.84853333 302.1312c-1.43359999 8.24320001-0.11946667 16.8448 3.82293333 24.25173333 9.79626667 18.6368 32.9728 25.92426667 51.6096 16.00853334L512 822.44266665l271.3088 142.64320001c7.40693333 3.9424 16.00853333 5.25653333 24.25173333 3.82293333 20.78719999-3.584 34.7648-23.296 31.1808-44.0832l-51.84853333-302.1312 219.46026668-213.9648c5.97333334-5.85386666 9.91573333-13.49973334 11.11039999-21.8624 3.2256-20.90666667-11.34933333-40.26026667-32.256-43.36640001z"},{viewBox:1024,path:"M852.65066667 405.84533333C800.54044445 268.40177778 667.76177778 170.66666667 512.22755555 170.66666667S223.91466667 268.288 171.80444445 405.73155555C74.29688889 431.33155555 2.27555555 520.07822222 2.27555555 625.77777778c0 125.72444445 101.83111111 227.55555555 227.44177778 227.55555555h564.56533334C919.89333333 853.33333333 1021.72444445 751.50222222 1021.72444445 625.77777778c0-105.472-71.79377778-194.21866667-169.07377778-219.93244445z"},{viewBox:1024,path:"M926.25224691 323.7371485H654.6457886L898.88200917 15.14388241c5.05486373-6.53433603 0.49315743-16.02761669-7.76722963-16.02761668H418.30008701c-3.45210206 0-6.78091476 1.84934039-8.50696579 4.93157436L90.35039154 555.76772251c-3.82197013 6.53433603 0.86302552 14.7947231 8.50696578 14.79472311h215.01664245l-110.22068713 440.88274851c-2.34249783 9.61657002 9.24670194 16.39748478 16.39748477 9.49328065L933.03316167 340.62779071c6.41104668-6.0411786 2.09591911-16.8906422-6.78091476-16.89064221z"},{viewBox:1024,path:"M878.47822222 463.30311111c-22.18666667-49.83466667-53.93066667-93.98044445-94.32177777-131.072l-33.10933334-30.37866666c-4.89244445-4.32355555-12.62933333-2.38933333-14.79111111 3.75466666l-14.79111111 42.43911111c-9.216 26.624-26.16888889 53.81688889-50.176 80.55466667-1.59288889 1.70666667-3.41333333 2.16177778-4.66488889 2.27555556-1.25155555 0.11377778-3.18577778-0.11377778-4.89244445-1.70666667-1.59288889-1.36533333-2.38933333-3.41333333-2.27555555-5.46133333 4.20977778-68.49422222-16.27022222-145.74933333-61.09866667-229.83111112C561.26577778 124.01777778 509.72444445 69.51822222 445.32622222 31.51644445l-46.99022222-27.648c-6.144-3.64088889-13.99466667 1.13777778-13.65333333 8.30577777l2.50311111 54.61333333c1.70666667 37.31911111-2.61688889 70.31466667-12.85688889 97.73511112-12.51555555 33.56444445-30.49244445 64.73955555-53.47555556 92.72888888-16.15644445 19.56977778-34.24711111 37.20533333-54.04444444 52.45155556-47.90044445 36.75022222-87.38133333 84.65066667-114.11911111 138.24C125.72444445 502.10133333 111.50222222 562.74488889 111.50222222 623.50222222c0 53.70311111 10.58133333 105.69955555 31.51644445 154.73777778 20.25244445 47.21777778 49.152 89.77066667 85.90222222 126.17955555 36.864 36.40888889 79.64444445 65.08088889 127.31733333 84.992C405.61777778 1010.11911111 457.95555555 1020.58666667 512 1020.58666667s106.38222222-10.46755555 155.76177778-31.06133334c47.67288889-19.91111111 90.56711111-48.46933333 127.31733333-84.992 36.864-36.40888889 65.76355555-78.96177778 85.90222222-126.17955555 20.93511111-49.03822222 31.51644445-101.03466667 31.51644445-154.73777778 0-55.52355555-11.37777778-109.45422222-34.01955556-160.31288889z"},{viewBox:1024,path:"M968.20337778 20.11591112H705.44042667c-22.17301333 0-41.92483556 15.16430222-47.14951111 37.33731555C642.36202666 124.73685332 582.08711111 173.03324444 512 173.03324444s-130.36202666-48.29639112-146.29091556-115.58001777c-5.22467555-22.17301333-24.84906667-37.33731556-47.14951111-37.33731555H55.79662222c-30.96576 0-56.06968889 25.10392889-56.06968888 56.06968888v321.12639999c0 30.96576 25.10392889 56.06968889 56.06968888 56.06968889h95.57333334v494.43271112c0 30.96576 25.10392889 56.06968889 56.06968889 56.06968888h609.1207111c30.96576 0 56.06968889-25.10392889 56.06968889-56.06968888V453.38168888h95.57333334c30.96576 0 56.06968889-25.10392889 56.06968888-56.06968889V76.1856c0-30.96576-25.10392889-56.06968889-56.06968888-56.06968888z"},{viewBox:1024,path:"M980.94648889 239.80714666H523.46880001L373.99210666 96.82944c-1.91146667-1.78403556-4.46008889-2.80348444-7.00871111-2.80348445H43.05351111c-22.55530667 0-40.77795555 18.22264888-40.77795555 40.77795557v754.39217776c0 22.55530667 18.22264888 40.77795555 40.77795555 40.77795557h937.89297778c22.55530667 0 40.77795555-18.22264888 40.77795555-40.77795557V280.58510222c0-22.55530667-18.22264888-40.77795555-40.77795555-40.77795556z"},{viewBox:1024,path:"M972.60904597 164.57058577L841.30587843 33.39070759c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480282-29.3428675-26.75379095 0-51.90482023 10.47959553-70.76809219 29.3428675L558.60337778 174.68031322c-18.86327195 18.86327195-29.34286748 44.1375906-29.34286749 70.64480283 0 26.75379095 10.47959553 51.90482023 29.34286749 70.76809218l103.31648301 103.31648302c-24.28800376 53.50758189-57.69942011 101.59043198-99.24793416 143.13894603-41.42522469 41.67180341-89.63136414 75.08321976-143.13894603 99.61780223L316.21649759 558.84995649c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480283-29.34286747-26.75379095 0-51.90482023 10.47959553-70.76809217 29.34286747L33.39070759 700.01627278c-18.86327195 18.86327195-29.34286748 44.1375906-29.3428675 70.76809217 0 26.75379095 10.47959553 51.90482023 29.3428675 70.76809219l131.05658883 131.05658883c30.08260365 30.205893 71.63111769 47.34311394 114.28923598 47.34311394 9.00012323 0 17.63037836-0.73973616 26.13734414-2.21920846 166.19405621-27.37023774 331.03192945-115.76870829 464.06114804-248.67463751C901.84095379 636.27567408 990.11613498 471.56109018 1017.85624079 304.87387654c8.38367642-50.91850535-8.50696579-103.31648302-45.24719482-140.30329077z"},{viewBox:1024,path:"M910.60451556 640.96028445c-20.38897778-65.49959112-43.83630221-120.54983112-79.89930667-210.64362666C836.31217778 193.67708444 737.93535999 2.27555556 511.36284444 2.27555556 282.24170667 2.27555556 186.03121778 197.50001778 192.14791111 430.31665779c-36.19043555 90.22122667-59.51032888 144.88917333-79.89930667 210.64362666-43.32657778 139.53706668-29.30915556 197.26336001-18.60494222 198.53767111 22.9376 2.80348444 89.32920888-105.00323556 89.32920889-105.00323556 0 62.44124445 32.11264001 143.86972444 101.69002667 202.61546667-33.64181333 10.32192-109.20846222 38.10190221-91.24067556 68.55793777 14.52714667 24.59420444 250.01984 15.67402668 317.94062222 8.02816 67.92078222 7.64586667 303.41347556 16.56604444 317.94062223-8.02816 17.96778667-30.32860444-57.72629333-58.23601779-91.24067555-68.55793777 69.57738667-58.87317334 101.69002667-140.30165333 101.69002667-202.61546667 0 0 66.39160889 107.80672 89.32920888 105.00323556 10.83164445-1.40174222 24.84906667-59.12803556-18.47751111-198.53767111z"},{viewBox:1024,path:"M1016.86992592 199.24764445c-37.13706667 16.01991111-77.55093333 27.54939259-119.17842962 32.03982222 42.96248889-25.60758518 75.60912592-66.02145185 91.02222222-114.08118519-39.68568889 23.66577778-84.58998518 41.02068148-131.31472593 50.00154074C819.53374815 126.79395555 765.76995555 101.79318518 706.18074075 101.79318518c-114.688 0-206.92385185 92.96402963-206.92385186 207.04521482 0 16.01991111 1.94180741 32.03982222 5.09724444 47.45291852-171.72859259-8.98085925-324.88865185-91.02222222-426.71217778-216.63288889-17.96171852 30.82619259-28.15620741 66.02145185-28.1562074 104.49351112 0 71.84687408 36.53025185 135.19834075 92.23585185 172.45677036-33.98162963-1.33499259-66.02145185-10.92266667-93.57084445-26.33576296v2.54862222c0 100.6098963 71.1186963 183.98625185 165.90317037 203.1616-17.3549037 4.49042963-35.92343703 7.03905185-54.49197037 7.03905185-13.47128889 0-26.2144-1.33499259-39.07887407-3.15543704C146.69748148 681.90814815 223.03478518 741.49736297 313.93564445 743.43917037c-71.1186963 55.7056-160.19911111 88.4736-256.9253926 88.4736-17.3549037 0-33.37481482-0.60681482-50.00154074-2.54862222C98.75911111 888.22518518 207.62168889 922.20681482 324.85831111 922.20681482 705.45256297 922.20681482 913.71140741 606.90583703 913.71140741 333.23235555c0-8.98085925 0-17.96171852-0.60681482-26.94257777 40.2925037-29.4912 75.60912592-66.02145185 103.76533333-107.04213333z"}]}],er=Object(h["defineComponent"])({name:"shape-pool",setup:function(e,t){var n=t.emit,o=Qa,c=function(e){n("select",e)};return{shapeList:o,selectShape:c}}});n("a2a2");er.render=$a,er.__scopeId="data-v-e95c032e";var tr=er,nr=Object(h["withScopeId"])("data-v-a0f5af54");Object(h["pushScopeId"])("data-v-a0f5af54");var or={class:"line-pool"};Object(h["popScopeId"])();var cr=nr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("LinePointMarker"),l=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",or,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.lineList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"line-item",key:n},[Object(h["createVNode"])("div",{class:"line-content",onClick:function(n){return e.selectLine(t)}},[Object(h["createVNode"])(l,{overflow:"visible",width:"20",height:"20"},{default:nr((function(){return[Object(h["createVNode"])("defs",null,[t.points[0]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"line-marker",id:"preset-line-".concat(n),position:"start",type:t.points[0],color:"currentColor",baseSize:2},null,8,["id","type"])):Object(h["createCommentVNode"])("",!0),t.points[1]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,class:"line-marker",id:"preset-line-".concat(n),position:"end",type:t.points[1],color:"currentColor",baseSize:2},null,8,["id","type"])):Object(h["createCommentVNode"])("",!0)]),Object(h["createVNode"])("path",{class:"line-path",d:t.path,stroke:"currentColor",fill:"none","stroke-width":"2","stroke-dasharray":"solid"===t.style?"0, 0":"4, 1","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":"","marker-start":t.points[0]?"url(#".concat("preset-line-".concat(n),"-",t.points[0],"-start)"):"","marker-end":t.points[1]?"url(#".concat("preset-line-".concat(n),"-",t.points[1],"-end)"):""},null,8,["d","stroke-dasharray","marker-start","marker-end"])]})),_:2},1024)],8,["onClick"])])})),128))])})),ar=[{path:"M0,0 L20,20",style:"solid",points:["",""]},{path:"M0,0 L20,20",style:"dashed",points:["",""]},{path:"M0,0 L20,20",style:"solid",points:["","arrow"]},{path:"M0,0 L20,20",style:"dashed",points:["","arrow"]},{path:"M0,0 L20,20",style:"solid",points:["","dot"]}],rr=Object(h["defineComponent"])({name:"line-pool",components:{LinePointMarker:Wo},setup:function(e,t){var n=t.emit,o=ar,c=function(e){n("select",e)};return{lineList:o,selectLine:c}}});n("69b0");rr.render=cr,rr.__scopeId="data-v-a0f5af54";var lr=rr,ir=Object(h["withScopeId"])("data-v-28a1a821");Object(h["pushScopeId"])("data-v-28a1a821");var ur={class:"chart-pool"};Object(h["popScopeId"])();var dr=ir((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconChartLine"),l=Object(h["resolveComponent"])("IconChartHistogram"),i=Object(h["resolveComponent"])("IconChartProportion");return Object(h["openBlock"])(),Object(h["createBlock"])("ul",ur,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.chartList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("li",{class:"chart-item",key:n},[Object(h["createVNode"])("div",{class:"chart-content",onClick:function(n){return e.selectChart(t)}},["line"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,size:"24"})):"bar"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,size:"24"})):"pie"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:2,size:"24"})):Object(h["createCommentVNode"])("",!0)],8,["onClick"])])})),128))])})),sr=Object(h["defineComponent"])({name:"chart-pool",setup:function(e,t){var n=t.emit,o=["bar","line","pie"],c=function(e){n("select",e)};return{chartList:o,selectChart:c}}});n("4d85");sr.render=dr,sr.__scopeId="data-v-28a1a821";var fr=sr,pr=Object(h["withScopeId"])("data-v-0239b43b");Object(h["pushScopeId"])("data-v-0239b43b");var br={class:"table-generator"},mr={class:"title"},vr={class:"lef"},Or={key:1,class:"custom"},hr={class:"row"},jr=Object(h["createVNode"])("div",{class:"label",style:{flex:"1"}},"行数:",-1),gr={class:"row"},yr=Object(h["createVNode"])("div",{class:"label",style:{flex:"1"}},"列数:",-1),kr={class:"btns"},Er=Object(h["createTextVNode"])("取消"),Ir=Object(h["createTextVNode"])("确认");Object(h["popScopeId"])();var Sr=pr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("InputNumber"),l=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",br,[Object(h["createVNode"])("div",mr,[Object(h["createVNode"])("div",vr,"插入表格 "+Object(h["toDisplayString"])(e.endCell.length?"".concat(e.endCell[0]," x ").concat(e.endCell[1]):""),1),Object(h["createVNode"])("div",{class:"right",onClick:t[1]||(t[1]=function(t){return e.isCustom=!e.isCustom})},Object(h["toDisplayString"])(e.isCustom?"返回":"自定义"),1)]),e.isCustom?(Object(h["openBlock"])(),Object(h["createBlock"])("div",Or,[Object(h["createVNode"])("div",hr,[jr,Object(h["createVNode"])(r,{min:1,max:20,value:e.customRow,"onUpdate:value":t[4]||(t[4]=function(t){return e.customRow=t}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",gr,[yr,Object(h["createVNode"])(r,{min:1,max:20,value:e.customCol,"onUpdate:value":t[5]||(t[5]=function(t){return e.customCol=t}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",kr,[Object(h["createVNode"])(l,{class:"btn",onClick:t[6]||(t[6]=function(t){return e.close()})},{default:pr((function(){return[Er]})),_:1}),Object(h["createVNode"])(l,{class:"btn",type:"primary",onClick:t[7]||(t[7]=function(t){return e.insertCustomTable()})},{default:pr((function(){return[Ir]})),_:1})])])):(Object(h["openBlock"])(),Object(h["createBlock"])("table",{key:0,onMouseleave:t[2]||(t[2]=function(t){return e.endCell=[]}),onClick:t[3]||(t[3]=function(t){return e.handleClickTable()})},[Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(10,(function(t){return Object(h["createVNode"])("tr",{key:t},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(10,(function(n){return Object(h["createVNode"])("td",{onMouseenter:function(o){return e.endCell=[t,n]},key:n},[Object(h["createVNode"])("div",{class:["cell",{active:e.endCell.length&&t<=e.endCell[0]&&n<=e.endCell[1]}]},null,2)],40,["onMouseenter"])})),64))])})),64))])],32))])})),Cr=Object(h["defineComponent"])({name:"table-generator",setup:function(e,t){var n=t.emit,o=Object(h["ref"])([]),c=Object(h["ref"])(3),a=Object(h["ref"])(3),r=Object(h["ref"])(!1),l=function(){if(o.value.length){var e=Object(Xt["a"])(o.value,2),t=e[0],c=e[1];n("insert",{row:t,col:c})}},i=function(){return c.value<1||c.value>20||a.value<1||a.value>20?ee["a"].warning("行数/列数必须在0~20之间!"):(n("insert",{row:c.value,col:a.value}),void(r.value=!1))},u=function(){n("close"),r.value=!1};return{endCell:o,customRow:c,customCol:a,handleClickTable:l,insertCustomTable:i,isCustom:r,close:u}}});n("da1a");Cr.render=Sr,Cr.__scopeId="data-v-0239b43b";var xr=Cr,Nr=Object(h["defineComponent"])({name:"canvas-tool",components:{ShapePool:tr,LinePool:lr,ChartPool:fr,TableGenerator:xr},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.canvasScale})),n=Object(h["computed"])((function(){return e.getters.canUndo})),o=Object(h["computed"])((function(){return e.getters.canRedo})),c=Object(h["computed"])((function(){return parseInt(100*t.value+"")+"%"})),a=Pe(),r=a.scaleCanvas,l=a.setCanvasPercentage,i=ge(),u=i.redo,d=i.undo,s=Se(),f=s.createImageElement,p=s.createChartElement,b=s.createTableElement,m=function(e){var t=e[0];t&&ke(t).then((function(e){return f(e)}))},v=Object(h["ref"])(!1),O=Object(h["ref"])(!1),j=Object(h["ref"])(!1),y=Object(h["ref"])(!1),k=function(){e.commit(g.SET_CREATING_ELEMENT,{type:"text",data:null})},E=function(t){e.commit(g.SET_CREATING_ELEMENT,{type:"shape",data:t}),v.value=!1},I=function(t){e.commit(g.SET_CREATING_ELEMENT,{type:"line",data:t}),O.value=!1};return{scaleCanvas:r,setCanvasPercentage:l,canvasScalePercentage:c,canUndo:n,canRedo:o,redo:u,undo:d,insertImageElement:m,shapePoolVisible:v,linePoolVisible:O,chartPoolVisible:j,tableGeneratorVisible:y,drawText:k,drawShape:E,drawLine:I,createChartElement:p,createTableElement:b}}});n("ae3c");Nr.render=Xa,Nr.__scopeId="data-v-1a2df855";var Tr=Nr,wr=Object(h["withScopeId"])("data-v-6821a1b4");Object(h["pushScopeId"])("data-v-6821a1b4");var Lr=Object(h["createTextVNode"])(" 添加幻灯片"),Vr={class:"slide-index"},_r={class:"thumbnail"};Object(h["popScopeId"])();var Br=wr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconPlus"),l=Object(h["resolveComponent"])("ThumbnailSlide"),i=Object(h["resolveComponent"])("Draggable"),u=Object(h["resolveDirective"])("contextmenu"),d=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"thumbnails",onMousedown:t[2]||(t[2]=function(){return e.setThumbnailsFocus(!0)})},[Object(h["createVNode"])("div",{class:"add-slide",onClick:t[1]||(t[1]=function(t){return e.createSlide()})},[Object(h["createVNode"])(r),Lr]),Object(h["createVNode"])(i,{class:"thumbnail-list",modelValue:e.slides,animation:300,scroll:!0,scrollSensitivity:50,onEnd:e.handleDragEnd,itemKey:"id"},{item:wr((function(t){var n=t.element,o=t.index;return[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:["thumbnail-wrapper",{active:e.slideIndex===o}],onMousedown:function(t){return e.changSlideIndex(o)}},[Object(h["createVNode"])("div",Vr,Object(h["toDisplayString"])(e.fillDigit(o+1,2)),1),Object(h["createVNode"])("div",_r,[Object(h["createVNode"])(l,{slide:n,size:120},null,8,["slide"])])],42,["onMousedown"]),[[u,e.contextmenusThumbnailItem]])]})),_:1},8,["modelValue","onEnd"])],544)),[[d,function(){return e.setThumbnailsFocus(!1)}],[u,e.contextmenusThumbnails]])})),Mr=n("b76a"),Dr=n.n(Mr),Ar=Object(h["withScopeId"])("data-v-1debfb1c"),Pr=Ar((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ThumbnailElement");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"thumbnail-slide",style:{width:e.size+"px",height:e.size*e.VIEWPORT_ASPECT_RATIO+"px"}},[Object(h["createVNode"])("div",{class:"elements-wrapper",style:{width:e.VIEWPORT_SIZE+"px",height:e.VIEWPORT_SIZE*e.VIEWPORT_ASPECT_RATIO+"px",transform:"scale(".concat(e.scale,")")}},[Object(h["createVNode"])("div",{class:"background",style:Object(P["a"])({},e.backgroundStyle)},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slide.elements,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.id,elementInfo:e,elementIndex:t+1},null,8,["elementInfo","elementIndex"])})),128))],4)],4)}));function Rr(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"base-element",style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo,target:"thumbnail"},null,8,["elementInfo"]))],4)}var Fr=Object(h["withScopeId"])("data-v-008489be"),zr=Fr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ImageRectOutline"),l=Object(h["resolveComponent"])("ImageEllipseOutline"),i=Object(h["resolveComponent"])("ImagePolygonOutline");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"base-element-image",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")}},[Object(h["createVNode"])("div",{class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):"",transform:e.flip}},["rect"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,width:e.elementInfo.width,height:e.elementInfo.height,radius:e.clipShape.radius,outline:e.elementInfo.outline},null,8,["width","height","radius","outline"])):"ellipse"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"])):"polygon"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:2,width:e.elementInfo.width,height:e.elementInfo.height,createPath:e.clipShape.createPath,outline:e.elementInfo.outline},null,8,["width","height","createPath","outline"])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"image-content",style:{clipPath:e.clipShape.style}},[Object(h["createVNode"])("img",{src:e.elementInfo.src,draggable:!1,style:{top:e.imgPosition.top,left:e.imgPosition.left,width:e.imgPosition.width,height:e.imgPosition.height,filter:e.filter},alt:""},null,12,["src"])],4)],4)],4)})),Hr=Object(h["defineComponent"])({name:"base-element-image",components:{ImageRectOutline:dn,ImageEllipseOutline:bn,ImagePolygonOutline:hn},props:{elementInfo:{type:Object,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){if(!e.elementInfo||!e.elementInfo.clip)return{top:"0",left:"0",width:"100%",height:"100%"};var t=Object(Xt["a"])(e.elementInfo.clip.range,2),n=t[0],o=t[1],c=(o[0]-n[0])/100,a=(o[1]-n[1])/100,r=n[0]/c,l=n[1]/a;return{left:-r+"%",top:-l+"%",width:100/c+"%",height:100/a+"%"}})),n=Object(h["computed"])((function(){if(!e.elementInfo||!e.elementInfo.clip)return on.rect;var t=e.elementInfo.clip.shape||Kt.RECT;return on[t]})),o=Object(h["computed"])((function(){if(!e.elementInfo.filters)return"";for(var t="",n=0,o=Object.keys(e.elementInfo.filters);n1||a.rowspan>1)for(var r=n;r1&&void 0!==arguments[1]?arguments[1]:0,c=s(),a=c.originClipRange,r=c.originWidth,i=c.originHeight,u=c.originLeft,f=c.originTop;if(o){var p,b=i/r,m=0,v=100;if(b>o){var O=(1-o/b)/2*100;p=[[m,O],[v,v-O]]}else{var h=(1-b/o)/2*100;p=[[h,m],[v-h,v]]}e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{clip:Object(P["a"])(Object(P["a"])({},t.value.clip),{},{shape:n,range:p}),left:u+r*(p[0][0]/100),top:f+i*(p[0][1]/100),width:r*(p[1][0]-p[0][0])/100,height:i*(p[1][1]-p[0][1])/100}})}else e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{clip:Object(P["a"])(Object(P["a"])({},t.value.clip),{},{shape:n,range:a})}});d(),l()},p=function(n){var o=n[0];o&&(ke(o).then((function(n){var o={src:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o})})),l())},b=function(){if(t.value.clip){var n=s(),o=n.originWidth,c=n.originHeight,a=n.originLeft,r=n.originTop;e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{left:a,top:r,width:o,height:c}})}e.commit(g.REMOVE_ELEMENT_PROPS,{id:t.value.id,propName:["clip","outline","flip","shadow","filters"]}),l()},m=function(){var o=Object(P["a"])(Object(P["a"])({},n.value.background),{},{type:"image",image:t.value.src,imageSize:"cover"});e.commit(g.UPDATE_SLIDE,{background:o}),l()};return{clipPanelVisible:o,shapeClipPathOptions:eu,ratioClipOptions:tu,filterOptions:a,flip:c,handleElement:t,updateImage:i,updateFilter:u,clipImage:d,presetImageClip:f,replaceImage:p,resetImage:b,setBackgroundImage:m}}});n("a347");nu.render=$i,nu.__scopeId="data-v-af9fc43e";var ou=nu,cu=Object(h["withScopeId"])("data-v-d415c6bc");Object(h["pushScopeId"])("data-v-d415c6bc");var au={class:"shape-style-panel"},ru={class:"row"},lu=Object(h["createTextVNode"])("纯色填充"),iu=Object(h["createTextVNode"])("渐变填充"),uu=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1),du=Object(h["createTextVNode"])("线性渐变"),su=Object(h["createTextVNode"])("径向渐变"),fu={class:"row"},pu=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点颜色:",-1),bu={class:"row"},mu=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点颜色:",-1),vu={key:0,class:"row"},Ou=Object(h["createVNode"])("div",{style:{flex:"2"}},"渐变角度:",-1);Object(h["popScopeId"])();var hu=cu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("Slider"),f=Object(h["resolveComponent"])("Divider"),p=Object(h["resolveComponent"])("ElementOutline"),b=Object(h["resolveComponent"])("ElementShadow"),m=Object(h["resolveComponent"])("ElementOpacity");return Object(h["openBlock"])(),Object(h["createBlock"])("div",au,[Object(h["createVNode"])("div",ru,[Object(h["createVNode"])(l,{style:{flex:"10"},value:e.fillType,onChange:t[1]||(t[1]=function(t){return e.updateFillType(t)})},{default:cu((function(){return[Object(h["createVNode"])(r,{value:"fill"},{default:cu((function(){return[lu]})),_:1}),Object(h["createVNode"])(r,{value:"gradient"},{default:cu((function(){return[iu]})),_:1})]})),_:1},8,["value"]),uu,"fill"===e.fillType?(Object(h["openBlock"])(),Object(h["createBlock"])(d,{key:0,trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.fill,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateFill(t)})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.fill,style:{flex:"10"}},null,8,["color"])]})),_:1})):(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,style:{flex:"10"},value:e.gradient.type,onChange:t[3]||(t[3]=function(t){return e.updateGradient({type:t})})},{default:cu((function(){return[Object(h["createVNode"])(r,{value:"linear"},{default:cu((function(){return[du]})),_:1}),Object(h["createVNode"])(r,{value:"radial"},{default:cu((function(){return[su]})),_:1})]})),_:1},8,["value"]))]),"gradient"===e.fillType?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",fu,[pu,Object(h["createVNode"])(d,{trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.gradient.color[0],"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.updateGradient({color:[t,e.gradient.color[1]]})})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.gradient.color[0],style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",bu,[mu,Object(h["createVNode"])(d,{trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.gradient.color[1],"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.updateGradient({color:[e.gradient.color[0],t]})})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.gradient.color[1],style:{flex:"3"}},null,8,["color"])]})),_:1})]),"linear"===e.gradient.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",vu,[Ou,Object(h["createVNode"])(s,{min:0,max:360,step:15,value:e.gradient.rotate,style:{flex:"3"},onChange:t[6]||(t[6]=function(t){return e.updateGradient({rotate:t})})},null,8,["value"])])):Object(h["createCommentVNode"])("",!0)],64)):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])(f),Object(h["createVNode"])(p),Object(h["createVNode"])(f),Object(h["createVNode"])(b),Object(h["createVNode"])(f),Object(h["createVNode"])(m)])})),ju=Object(h["defineComponent"])({name:"shape-style-panel",components:{ElementOpacity:ql,ElementOutline:si,ElementShadow:xi,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(),o=Object(h["ref"])(),c=Object(h["ref"])("fill");Object(h["watch"])(t,(function(){t.value&&"shape"===t.value.type&&(n.value=t.value.fill||"#000",o.value=t.value.gradient||{type:"linear",rotate:0,color:[n.value,"#fff"]},c.value=t.value.gradient?"gradient":"fill")}),{deep:!0,immediate:!0});var a=ge(),r=a.addHistorySnapshot,l=function(n){if("fill"===n)e.commit(g.REMOVE_ELEMENT_PROPS,{id:t.value.id,propName:"gradient"});else{var c={gradient:o.value};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c})}r()},i=function(n){var c={gradient:Object(P["a"])(Object(P["a"])({},o.value),n)};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c}),r()},u=function(n){var o={fill:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),r()};return{fill:n,gradient:o,fillType:c,updateFillType:l,updateFill:u,updateGradient:i}}});n("ff3e");ju.render=hu,ju.__scopeId="data-v-d415c6bc";var gu=ju,yu=Object(h["withScopeId"])("data-v-65b24fb3");Object(h["pushScopeId"])("data-v-65b24fb3");var ku={class:"line-style-panel"},Eu={class:"row"},Iu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条样式:",-1),Su=Object(h["createTextVNode"])("实线"),Cu=Object(h["createTextVNode"])("虚线"),xu={class:"row"},Nu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条颜色:",-1),Tu={class:"row"},wu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条宽度:",-1),Lu={class:"row"},Vu=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点样式:",-1),_u=Object(h["createTextVNode"])("无"),Bu=Object(h["createTextVNode"])("箭头"),Mu=Object(h["createTextVNode"])("圆点"),Du={class:"row"},Au=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点样式:",-1),Pu=Object(h["createTextVNode"])("无"),Ru=Object(h["createTextVNode"])("箭头"),Fu=Object(h["createTextVNode"])("圆点");Object(h["popScopeId"])();var zu=yu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("InputNumber"),f=Object(h["resolveComponent"])("Divider"),p=Object(h["resolveComponent"])("ElementShadow");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ku,[Object(h["createVNode"])("div",Eu,[Iu,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.style,onChange:t[1]||(t[1]=function(t){return e.updateLine({style:t})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:"solid"},{default:yu((function(){return[Su]})),_:1}),Object(h["createVNode"])(r,{value:"dashed"},{default:yu((function(){return[Cu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",xu,[Nu,Object(h["createVNode"])(d,{trigger:"click"},{content:yu((function(){return[Object(h["createVNode"])(i,{modelValue:e.handleElement.color,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateLine({color:t})})},null,8,["modelValue"])]})),default:yu((function(){return[Object(h["createVNode"])(u,{color:e.handleElement.color,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",Tu,[wu,Object(h["createVNode"])(s,{value:e.handleElement.width,onChange:t[3]||(t[3]=function(t){return e.updateLine({width:t})}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",Lu,[Vu,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.points[0],onChange:t[4]||(t[4]=function(t){return e.updateLine({points:[t,e.handleElement.points[1]]})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:""},{default:yu((function(){return[_u]})),_:1}),Object(h["createVNode"])(r,{value:"arrow"},{default:yu((function(){return[Bu]})),_:1}),Object(h["createVNode"])(r,{value:"dot"},{default:yu((function(){return[Mu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",Du,[Au,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.points[1],onChange:t[5]||(t[5]=function(t){return e.updateLine({points:[e.handleElement.points[0],t]})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:""},{default:yu((function(){return[Pu]})),_:1}),Object(h["createVNode"])(r,{value:"arrow"},{default:yu((function(){return[Ru]})),_:1}),Object(h["createVNode"])(r,{value:"dot"},{default:yu((function(){return[Fu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])(f),Object(h["createVNode"])(p)])})),Hu=Object(h["defineComponent"])({name:"line-style-panel",components:{ElementShadow:xi,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=ge(),o=n.addHistorySnapshot,c=function(n){e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:n}),o()};return{handleElement:t,updateLine:c}}});n("8df8e");Hu.render=zu,Hu.__scopeId="data-v-65b24fb3";var Uu=Hu,Gu=Object(h["withScopeId"])("data-v-0bd1ca02");Object(h["pushScopeId"])("data-v-0bd1ca02");var qu={class:"chart-style-panel"},Wu=Object(h["createTextVNode"])(" 编辑图表数据 "),Xu={class:"row"},Yu=Object(h["createTextVNode"])("面积图样式"),Zu=Object(h["createTextVNode"])("散点图样式"),Ju={class:"row"},Ku=Object(h["createTextVNode"])("使用平滑曲线"),$u={key:1,class:"row"},Qu=Object(h["createTextVNode"])("条形图样式"),ed={key:2,class:"row"},td=Object(h["createTextVNode"])("环形图样式"),nd={class:"row"},od=Object(h["createVNode"])("div",{style:{flex:"2"}},"背景填充:",-1),cd={class:"row"},ad=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题配色:",-1),rd={class:"row"},ld=Object(h["createVNode"])("div",{style:{flex:"2"}},"网格颜色:",-1);Object(h["popScopeId"])();var id=Gu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEdit"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Divider"),u=Object(h["resolveComponent"])("Checkbox"),d=Object(h["resolveComponent"])("ColorPicker"),s=Object(h["resolveComponent"])("ColorButton"),f=Object(h["resolveComponent"])("Popover"),p=Object(h["resolveComponent"])("ElementOutline"),b=Object(h["resolveComponent"])("ChartDataEditor"),m=Object(h["resolveComponent"])("Modal");return Object(h["openBlock"])(),Object(h["createBlock"])("div",qu,[Object(h["createVNode"])(l,{class:"full-width-btn",onClick:t[1]||(t[1]=function(t){return e.chartDataEditorVisible=!0})},{default:Gu((function(){return[Object(h["createVNode"])(r,{class:"btn-icon"}),Wu]})),_:1}),Object(h["createVNode"])(i),"line"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Xu,[Object(h["createVNode"])(u,{onChange:t[2]||(t[2]=function(t){return e.updateOptions({showArea:t.target.checked})}),checked:e.showArea,style:{flex:"1"}},{default:Gu((function(){return[Yu]})),_:1},8,["checked"]),Object(h["createVNode"])(u,{onChange:t[3]||(t[3]=function(t){return e.updateOptions({showLine:!t.target.checked})}),checked:!e.showLine,style:{flex:"1"}},{default:Gu((function(){return[Zu]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Ju,[Object(h["createVNode"])(u,{onChange:t[4]||(t[4]=function(t){return e.updateOptions({lineSmooth:t.target.checked})}),checked:e.lineSmooth},{default:Gu((function(){return[Ku]})),_:1},8,["checked"])])],64)):Object(h["createCommentVNode"])("",!0),"bar"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",$u,[Object(h["createVNode"])(u,{onChange:t[5]||(t[5]=function(t){return e.updateOptions({horizontalBars:t.target.checked})}),checked:e.horizontalBars},{default:Gu((function(){return[Qu]})),_:1},8,["checked"])])):Object(h["createCommentVNode"])("",!0),"pie"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ed,[Object(h["createVNode"])(u,{onChange:t[6]||(t[6]=function(t){return e.updateOptions({donut:t.target.checked})}),checked:e.donut},{default:Gu((function(){return[td]})),_:1},8,["checked"])])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])(i),Object(h["createVNode"])("div",nd,[od,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.fill,"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.updateFill(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.fill,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",cd,[ad,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.themeColor,"onUpdate:modelValue":t[8]||(t[8]=function(t){return e.updateTheme(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.themeColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",rd,[ld,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.gridColor,"onUpdate:modelValue":t[9]||(t[9]=function(t){return e.updateGridColor(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.gridColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])(i),Object(h["createVNode"])(p),Object(h["createVNode"])(m,{visible:e.chartDataEditorVisible,"onUpdate:visible":t[12]||(t[12]=function(t){return e.chartDataEditorVisible=t}),footer:null,centered:"",closable:!1,width:648,destroyOnClose:""},{default:Gu((function(){return[Object(h["createVNode"])(b,{data:e.handleElement.data,onClose:t[10]||(t[10]=function(t){return e.chartDataEditorVisible=!1}),onSave:t[11]||(t[11]=function(t){return e.updateData(t)})},null,8,["data"])]})),_:1},8,["visible"])])})),ud=Object(h["withScopeId"])("data-v-73892bc6");Object(h["pushScopeId"])("data-v-73892bc6");var dd={class:"chart-data-editor"},sd={class:"editor-content"},fd={class:"range-box"},pd={class:"btns"},bd=Object(h["createTextVNode"])("取消"),md=Object(h["createTextVNode"])("确认");Object(h["popScopeId"])();var vd=ud((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",dd,[Object(h["createVNode"])("div",sd,[Object(h["createVNode"])("div",fd,[Object(h["createVNode"])("div",{class:"temp-range",style:{width:e.tempRangeSize.width+"px",height:e.tempRangeSize.height+"px"}},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.rangeLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["range-line",e.type],key:e.type,style:e.style},null,6)})),128)),Object(h["createVNode"])("div",{class:"resizable",style:e.resizablePointStyle,onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.changeSelectRange(t)}),["stop"]))},null,36)]),Object(h["createVNode"])("table",null,[Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(30,(function(t){return Object(h["createVNode"])("tr",{key:t},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(7,(function(n){return Object(h["createVNode"])("td",{key:n,class:{head:1===n&&t<=e.selectedRange[1]}},[Object(h["createVNode"])("input",{class:["item",{selected:t<=e.selectedRange[1]&&n<=e.selectedRange[0]}],id:"cell-".concat(t-1,"-").concat(n-1),autocomplete:"off"},null,10,["id"])],2)})),64))])})),64))])])]),Object(h["createVNode"])("div",pd,[Object(h["createVNode"])(r,{class:"btn",onClick:t[2]||(t[2]=function(t){return e.closeEditor()})},{default:ud((function(){return[bd]})),_:1}),Object(h["createVNode"])(r,{type:"primary",class:"btn",onClick:t[3]||(t[3]=function(t){return e.getTableData()})},{default:ud((function(){return[md]})),_:1})])])})),Od=100,hd=32,jd=Object(h["defineComponent"])({name:"chart-data-editor",props:{data:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])([0,0]),c=Object(h["ref"])({width:0,height:0}),a=Object(h["computed"])((function(){var e=o.value[0]*Od,t=o.value[1]*hd;return[{type:"t",style:{width:e+"px"}},{type:"b",style:{top:t+"px",width:e+"px"}},{type:"l",style:{height:t+"px"}},{type:"r",style:{left:e+"px",height:t+"px"}}]})),r=Object(h["computed"])((function(){var e=o.value[0]*Od,t=o.value[1]*hd;return{left:e+"px",top:t+"px"}})),l=function(){for(var t=[],n=e.data,c=n.labels,a=n.series,r=c.length,l=a.length,i=0;i.5*Od&&(i+=Od-i%Od),u%hd>.5*hd&&(u+=hd-u%hd);var d=Math.round(u/hd),s=Math.round(i/Od);d<3&&(d=3),s<2&&(s=2),o.value=[s,d],c.value={width:0,height:0}}}};return{tempRangeSize:c,rangeLines:a,resizablePointStyle:r,changeSelectRange:d,selectedRange:o,getTableData:i,closeEditor:u}}});n("7dcf");jd.render=vd,jd.__scopeId="data-v-73892bc6";var gd=jd,yd=Object(h["defineComponent"])({name:"chart-style-panel",components:{ElementOutline:si,ChartDataEditor:gd,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(!1),o=ge(),c=o.addHistorySnapshot,a=Object(h["ref"])(),r=Object(h["ref"])(""),l=Object(h["ref"])(""),i=Object(h["ref"])(!0),u=Object(h["ref"])(!0),d=Object(h["ref"])(!1),s=Object(h["ref"])(!1),f=Object(h["ref"])(!1);Object(h["watch"])(t,(function(){if(t.value&&"chart"===t.value.type){if(a.value=t.value.fill||"#000",t.value.options){var e=t.value.options,n=e.lineSmooth,o=e.showLine,c=e.showArea,p=e.horizontalBars,b=e.donut;void 0!==n&&(i.value=n),void 0!==o&&(u.value=o),void 0!==c&&(d.value=c),void 0!==p&&(s.value=p),void 0!==b&&(f.value=b)}r.value=t.value.themeColor,l.value=t.value.gridColor||"rgba(0, 0, 0, 0.4)"}}),{deep:!0,immediate:!0});var p=function(o){n.value=!1;var a={data:o};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:a}),c()},b=function(n){var o={fill:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()},m=function(n){var o=t.value.options||{},a=Object(P["a"])(Object(P["a"])({},o),n),r={options:a};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:r}),c()},v=function(n){var o={themeColor:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()},O=function(n){var o={gridColor:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()};return{chartDataEditorVisible:n,handleElement:t,updateData:p,fill:a,updateFill:b,lineSmooth:i,showLine:u,showArea:d,horizontalBars:s,donut:f,updateOptions:m,themeColor:r,gridColor:l,updateTheme:v,updateGridColor:O}}});n("d1ba");yd.render=id,yd.__scopeId="data-v-0bd1ca02";var kd=yd,Ed=Object(h["withScopeId"])("data-v-63aedd01");Object(h["pushScopeId"])("data-v-63aedd01");var Id={class:"table-style-panel"},Sd={class:"row"},Cd=Object(h["createVNode"])("div",{style:{flex:"2"}},"行数:",-1),xd={class:"row"},Nd=Object(h["createVNode"])("div",{style:{flex:"2"}},"列数:",-1),Td={class:"row theme-switch"},wd=Object(h["createVNode"])("div",{style:{flex:"2"}},"启用主题表格:",-1),Ld={class:"switch-wrapper",style:{flex:"3"}},Vd={class:"row"},_d=Object(h["createTextVNode"])("标题行"),Bd=Object(h["createTextVNode"])("汇总行"),Md={class:"row"},Dd=Object(h["createTextVNode"])("第一列"),Ad=Object(h["createTextVNode"])("最后一列"),Pd={class:"row"},Rd=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题颜色:",-1);Object(h["popScopeId"])();var Fd=Ed((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconFontSize"),l=Object(h["resolveComponent"])("SelectOption"),i=Object(h["resolveComponent"])("Select"),u=Object(h["resolveComponent"])("IconAddText"),d=Object(h["resolveComponent"])("InputGroup"),s=Object(h["resolveComponent"])("ColorPicker"),f=Object(h["resolveComponent"])("IconText"),p=Object(h["resolveComponent"])("Button"),b=Object(h["resolveComponent"])("Tooltip"),m=Object(h["resolveComponent"])("Popover"),v=Object(h["resolveComponent"])("IconFill"),O=Object(h["resolveComponent"])("ButtonGroup"),j=Object(h["resolveComponent"])("IconTextBold"),g=Object(h["resolveComponent"])("CheckboxButton"),y=Object(h["resolveComponent"])("IconTextItalic"),k=Object(h["resolveComponent"])("IconTextUnderline"),E=Object(h["resolveComponent"])("IconStrikethrough"),I=Object(h["resolveComponent"])("CheckboxButtonGroup"),S=Object(h["resolveComponent"])("IconAlignTextLeft"),C=Object(h["resolveComponent"])("RadioButton"),x=Object(h["resolveComponent"])("IconAlignTextCenter"),N=Object(h["resolveComponent"])("IconAlignTextRight"),T=Object(h["resolveComponent"])("RadioGroup"),w=Object(h["resolveComponent"])("Divider"),L=Object(h["resolveComponent"])("ElementOutline"),V=Object(h["resolveComponent"])("InputNumber"),_=Object(h["resolveComponent"])("Switch"),B=Object(h["resolveComponent"])("Checkbox"),M=Object(h["resolveComponent"])("ColorButton");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Id,[Object(h["createVNode"])(d,{compact:"",class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(i,{style:{flex:"3"},value:e.textAttrs.fontname,onChange:t[1]||(t[1]=function(t){return e.updateTextAttrs({fontname:t})})},{suffixIcon:Ed((function(){return[Object(h["createVNode"])(r)]})),default:Ed((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.availableFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:e.en,value:e.en},{default:Ed((function(){return[Object(h["createVNode"])("span",{style:{fontFamily:e.en}},Object(h["toDisplayString"])(e.zh),5)]})),_:2},1032,["value"])})),128))]})),_:1},8,["value"]),Object(h["createVNode"])(i,{style:{flex:"2"},value:e.textAttrs.fontsize,onChange:t[2]||(t[2]=function(t){return e.updateTextAttrs({fontsize:t})})},{suffixIcon:Ed((function(){return[Object(h["createVNode"])(u)]})),default:Ed((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.fontSizeOptions,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:e,value:e},{default:Ed((function(){return[Object(h["createTextVNode"])(Object(h["toDisplayString"])(e),1)]})),_:2},1032,["value"])})),128))]})),_:1},8,["value"])]})),_:1}),Object(h["createVNode"])(O,{class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.textAttrs.color,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.updateTextAttrs({color:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"文字颜色"},{default:Ed((function(){return[Object(h["createVNode"])(p,{class:"text-color-btn",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(f),Object(h["createVNode"])("div",{class:"text-color-block",style:{backgroundColor:e.textAttrs.color}},null,4)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.textAttrs.backcolor,"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.updateTextAttrs({backcolor:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"单元格填充"},{default:Ed((function(){return[Object(h["createVNode"])(p,{class:"text-color-btn",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(v),Object(h["createVNode"])("div",{class:"text-color-block",style:{backgroundColor:e.textAttrs.backcolor}},null,4)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1})]})),_:1}),Object(h["createVNode"])(I,{class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"加粗"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.bold,onClick:t[5]||(t[5]=function(t){return e.updateTextAttrs({bold:!e.textAttrs.bold})})},{default:Ed((function(){return[Object(h["createVNode"])(j)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"斜体"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.em,onClick:t[6]||(t[6]=function(t){return e.updateTextAttrs({em:!e.textAttrs.em})})},{default:Ed((function(){return[Object(h["createVNode"])(y)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下划线"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.underline,onClick:t[7]||(t[7]=function(t){return e.updateTextAttrs({underline:!e.textAttrs.underline})})},{default:Ed((function(){return[Object(h["createVNode"])(k)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"删除线"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.strikethrough,onClick:t[8]||(t[8]=function(t){return e.updateTextAttrs({strikethrough:!e.textAttrs.strikethrough})})},{default:Ed((function(){return[Object(h["createVNode"])(E)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(T,{class:"row","button-style":"solid",value:e.textAttrs.align,onChange:t[9]||(t[9]=function(t){return e.updateTextAttrs({align:t.target.value})})},{default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"left",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(S)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"居中"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"center",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(x)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"right",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(N)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["value"]),Object(h["createVNode"])(w),Object(h["createVNode"])(L,{fixed:!0}),Object(h["createVNode"])(w),Object(h["createVNode"])("div",Sd,[Cd,Object(h["createVNode"])(V,{min:e.minRowCount,max:20,value:e.rowCount,"onUpdate:value":t[10]||(t[10]=function(t){return e.rowCount=t}),onPressEnter:t[11]||(t[11]=function(t){return e.setTableRow(t)}),onBlur:t[12]||(t[12]=function(t){return e.setTableRow(t)}),style:{flex:"3"}},null,8,["min","value"])]),Object(h["createVNode"])("div",xd,[Nd,Object(h["createVNode"])(V,{min:e.minColCount,max:20,value:e.colCount,"onUpdate:value":t[13]||(t[13]=function(t){return e.colCount=t}),onPressEnter:t[14]||(t[14]=function(t){return e.setTableCol(t)}),onBlur:t[15]||(t[15]=function(t){return e.setTableCol(t)}),style:{flex:"3"}},null,8,["min","value"])]),Object(h["createVNode"])(w),Object(h["createVNode"])("div",Td,[wd,Object(h["createVNode"])("div",Ld,[Object(h["createVNode"])(_,{checked:e.hasTheme,onChange:t[16]||(t[16]=function(t){return e.toggleTheme(t)})},null,8,["checked"])])]),e.hasTheme?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Vd,[Object(h["createVNode"])(B,{onChange:t[17]||(t[17]=function(t){return e.updateTheme({rowHeader:t.target.checked})}),checked:e.theme.rowHeader,style:{flex:"1"}},{default:Ed((function(){return[_d]})),_:1},8,["checked"]),Object(h["createVNode"])(B,{onChange:t[18]||(t[18]=function(t){return e.updateTheme({rowFooter:t.target.checked})}),checked:e.theme.rowFooter,style:{flex:"1"}},{default:Ed((function(){return[Bd]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Md,[Object(h["createVNode"])(B,{onChange:t[19]||(t[19]=function(t){return e.updateTheme({colHeader:t.target.checked})}),checked:e.theme.colHeader,style:{flex:"1"}},{default:Ed((function(){return[Dd]})),_:1},8,["checked"]),Object(h["createVNode"])(B,{onChange:t[20]||(t[20]=function(t){return e.updateTheme({colFooter:t.target.checked})}),checked:e.theme.colFooter,style:{flex:"1"}},{default:Ed((function(){return[Ad]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Pd,[Rd,Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.theme.color,"onUpdate:modelValue":t[21]||(t[21]=function(t){return e.updateTheme({color:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(M,{color:e.theme.color,style:{flex:"3"}},null,8,["color"])]})),_:1})])],64)):Object(h["createCommentVNode"])("",!0)])})),zd=Object(h["defineComponent"])({name:"table-style-panel",components:{ElementOutline:si,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])({bold:!1,em:!1,underline:!1,strikethrough:!1,color:"#000",backcolor:"#000",fontsize:"12px",fontname:"微软雅黑",align:"left"}),o=Object(h["ref"])(),c=Object(h["ref"])(!1),a=Object(h["ref"])(0),r=Object(h["ref"])(0),l=Object(h["ref"])(0),i=Object(h["ref"])(0);Object(h["watch"])(t,(function(){t.value&&"table"===t.value.type&&(o.value=t.value.theme,c.value=!!o.value,a.value=t.value.data.length,r.value=t.value.data[0].length,l.value=t.value.data.length,i.value=t.value.data[0].length)}),{deep:!0,immediate:!0});var u=Object(h["ref"])([]),d=function(){if(t.value){var e=0,o=0;if(u.value.length){var c=u.value[0];e=+c.split("_")[0],o=+c.split("_")[1]}var a=t.value.data[e][o].style;n.value=a?{bold:!!a.bold,em:!!a.em,underline:!!a.underline,strikethrough:!!a.strikethrough,color:a.color||"#000",backcolor:a.backcolor||"#000",fontsize:a.fontsize||"12px",fontname:a.fontname||"微软雅黑",align:a.align||"left"}:{bold:!1,em:!1,underline:!1,strikethrough:!1,color:"#000",backcolor:"#000",fontsize:"12px",fontname:"微软雅黑",align:"left"}}},s=function(e){u.value=e,d()};Dt.on(_t.UPDATE_TABLE_SELECTED_CELL,(function(e){return s(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.UPDATE_TABLE_SELECTED_CELL,(function(e){return s(e)}))}));var f=Object(h["computed"])((function(){return e.state.availableFonts})),p=["12px","14px","16px","18px","20px","22px","24px","28px","32px"],b=ge(),m=b.addHistorySnapshot,v=function(n){for(var o=JSON.parse(JSON.stringify(t.value.data)),c=0;c
X
Y
',1),Kd={class:"row"},$d=Object(h["createVNode"])("div",{style:{flex:"3"}},"大小:",-1),Qd={key:1,style:{flex:"1"}},es=Object(h["createStaticVNode"])('
',1),ts={class:"row"},ns=Object(h["createVNode"])("div",{style:{flex:"3"}},"旋转:",-1),os=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1);Object(h["popScopeId"])();var cs=qd((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconSendToBack"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Tooltip"),u=Object(h["resolveComponent"])("IconBringToFrontOne"),d=Object(h["resolveComponent"])("IconBringToFront"),s=Object(h["resolveComponent"])("IconSentToBack"),f=Object(h["resolveComponent"])("ButtonGroup"),p=Object(h["resolveComponent"])("IconAlignLeft"),b=Object(h["resolveComponent"])("IconAlignVertically"),m=Object(h["resolveComponent"])("IconAlignRight"),v=Object(h["resolveComponent"])("IconAlignTop"),O=Object(h["resolveComponent"])("IconAlignHorizontally"),j=Object(h["resolveComponent"])("IconAlignBottom"),g=Object(h["resolveComponent"])("Divider"),y=Object(h["resolveComponent"])("InputNumber"),k=Object(h["resolveComponent"])("IconLock"),E=Object(h["resolveComponent"])("IconUnlock"),I=Object(h["resolveComponent"])("IconRotate");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Wd,[Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"置顶层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[1]||(t[1]=function(t){return e.orderElement(e.handleElement,"top")})},{default:qd((function(){return[Object(h["createVNode"])(r)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"置底层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[2]||(t[2]=function(t){return e.orderElement(e.handleElement,"bottom")})},{default:qd((function(){return[Object(h["createVNode"])(u)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上移一层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[3]||(t[3]=function(t){return e.orderElement(e.handleElement,"up")})},{default:qd((function(){return[Object(h["createVNode"])(d)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下移一层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[4]||(t[4]=function(t){return e.orderElement(e.handleElement,"down")})},{default:qd((function(){return[Object(h["createVNode"])(s)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[5]||(t[5]=function(t){return e.alignElementToCanvas("left")})},{default:qd((function(){return[Object(h["createVNode"])(p)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"水平居中"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[6]||(t[6]=function(t){return e.alignElementToCanvas("horizontal")})},{default:qd((function(){return[Object(h["createVNode"])(b)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[7]||(t[7]=function(t){return e.alignElementToCanvas("right")})},{default:qd((function(){return[Object(h["createVNode"])(m)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[8]||(t[8]=function(t){return e.alignElementToCanvas("top")})},{default:qd((function(){return[Object(h["createVNode"])(v)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"垂直居中"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[9]||(t[9]=function(t){return e.alignElementToCanvas("vertical")})},{default:qd((function(){return[Object(h["createVNode"])(O)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[10]||(t[10]=function(t){return e.alignElementToCanvas("bottom")})},{default:qd((function(){return[Object(h["createVNode"])(j)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(g),Object(h["createVNode"])("div",Xd,[Yd,Object(h["createVNode"])(y,{step:5,value:e.left,onChange:t[11]||(t[11]=function(t){return e.updateLeft(t)}),style:{flex:"4"}},null,8,["value"]),Zd,Object(h["createVNode"])(y,{step:5,value:e.top,onChange:t[12]||(t[12]=function(t){return e.updateTop(t)}),style:{flex:"4"}},null,8,["value"])]),Jd,"line"!==e.handleElement.type?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Kd,[$d,Object(h["createVNode"])(y,{min:e.minSize,max:1500,step:5,value:e.width,onChange:t[13]||(t[13]=function(t){return e.updateWidth(t)}),style:{flex:"4"}},null,8,["min","value"]),["image","shape"].includes(e.handleElement.type)?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[e.fixedRatio?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:0,mouseLeaveDelay:0,mouseEnterDelay:.5,title:"解除宽高比锁定"},{default:qd((function(){return[Object(h["createVNode"])(k,{style:{flex:"1"},class:"icon-btn",onClick:t[14]||(t[14]=function(t){return e.updateFixedRatio(!1)})})]})),_:1},8,["mouseEnterDelay"])):(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:1,mouseLeaveDelay:0,mouseEnterDelay:.5,title:"宽高比锁定"},{default:qd((function(){return[Object(h["createVNode"])(E,{style:{flex:"1"},class:"icon-btn",onClick:t[15]||(t[15]=function(t){return e.updateFixedRatio(!0)})})]})),_:1},8,["mouseEnterDelay"]))],64)):(Object(h["openBlock"])(),Object(h["createBlock"])("div",Qd)),Object(h["createVNode"])(y,{min:e.minSize,max:800,step:5,disabled:"text"===e.handleElement.type,value:e.height,onChange:t[16]||(t[16]=function(t){return e.updateHeight(t)}),style:{flex:"4"}},null,8,["min","disabled","value"])]),es],64)):Object(h["createCommentVNode"])("",!0),["text","image","shape"].includes(e.handleElement.type)?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:1},[Object(h["createVNode"])(g),Object(h["createVNode"])("div",ts,[ns,Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"逆时针旋转"},{default:qd((function(){return[Object(h["createVNode"])(I,{class:"icon-btn",onClick:t[17]||(t[17]=function(t){return e.updateRotate45("-")}),style:{flex:"2"}})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"顺时针旋转"},{default:qd((function(){return[Object(h["createVNode"])(I,{class:"icon-btn",onClick:t[18]||(t[18]=function(t){return e.updateRotate45("+")}),style:{flex:2,transform:"rotateY(180deg)"}},null,8,["style"])]})),_:1},8,["mouseEnterDelay"]),os,Object(h["createVNode"])(y,{min:-180,max:180,step:5,value:e.rotate,onChange:t[19]||(t[19]=function(t){return e.updateRotate(t)}),style:{flex:"4"}},null,8,["value"])])],64)):Object(h["createCommentVNode"])("",!0)])})),as=n("b69c"),rs=n.n(as),ls=Object(h["defineComponent"])({name:"element-positopn-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(0),o=Object(h["ref"])(0),c=Object(h["ref"])(0),a=Object(h["ref"])(0),r=Object(h["ref"])(0),l=Object(h["ref"])(!1),i=Object(h["computed"])((function(){return t.value&&Pt[t.value.type]||20}));Object(h["watch"])(t,(function(){t.value&&(n.value=rs()(t.value.left,1),o.value=rs()(t.value.top,1),l.value="fixedRatio"in t.value&&!!t.value.fixedRatio,"line"!==t.value.type&&(c.value=rs()(t.value.width,1),a.value=rs()(t.value.height,1),r.value="rotate"in t.value&&void 0!==t.value.rotate?rs()(t.value.rotate,1):0))}),{deep:!0,immediate:!0});var u=Qt(),d=u.orderElement,s=en(),f=s.alignElementToCanvas,p=ge(),b=p.addHistorySnapshot,m=function(n){var o={left:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},v=function(n){var o={top:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},O=function(n){var o={width:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},j=function(n){var o={height:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},y=function(n){var o={rotate:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},k=function(n){var o={fixedRatio:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},E=function(n){var o=45*Math.floor(r.value/45);"+"===n?o+=45:"-"===n&&(o-=45),o<-180&&(o=-180),o>180&&(o=180);var c={rotate:o};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c}),b()};return{handleElement:t,orderElement:d,alignElementToCanvas:f,left:n,top:o,width:c,height:a,rotate:r,fixedRatio:l,minSize:i,updateLeft:m,updateTop:v,updateWidth:O,updateHeight:j,updateRotate:y,updateFixedRatio:k,updateRotate45:E}}});n("e407");ls.render=cs,ls.__scopeId="data-v-1a79147f";var is=ls,us=Object(h["withScopeId"])("data-v-3483fbf2");Object(h["pushScopeId"])("data-v-3483fbf2");var ds={class:"element-animation-panel"},ss={key:0,class:"element-animation"},fs={class:"animation-pool"},ps={class:"type-title"},bs={class:"pool-item-wrapper"},ms={key:1,class:"tip"},vs=Object(h["createTextVNode"])(" 选中画布中的元素添加动画"),Os={class:"index"},hs={class:"text"},js={class:"handler"};Object(h["popScopeId"])();var gs,ys=us((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEffects"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Popover"),u=Object(h["resolveComponent"])("IconClick"),d=Object(h["resolveComponent"])("Divider"),s=Object(h["resolveComponent"])("IconPlayOne"),f=Object(h["resolveComponent"])("Tooltip"),p=Object(h["resolveComponent"])("IconCloseSmall"),b=Object(h["resolveComponent"])("Draggable");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ds,[e.handleElement?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ss,[Object(h["createVNode"])(i,{trigger:"click",visible:e.animationPoolVisible,"onUpdate:visible":t[2]||(t[2]=function(t){return e.animationPoolVisible=t})},{content:us((function(){return[Object(h["createVNode"])("div",fs,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.animations,(function(n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"pool-type",key:n.name},[Object(h["createVNode"])("div",ps,Object(h["toDisplayString"])(n.name)+":",1),Object(h["createVNode"])("div",bs,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(n.children,(function(n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"pool-item",key:n.name,onMouseenter:function(t){return e.hoverPreviewAnimation=n.value},onMouseleave:t[1]||(t[1]=function(t){return e.hoverPreviewAnimation=""}),onClick:function(t){return e.addAnimation(n.value)}},[Object(h["createVNode"])("div",{class:["animation-box",["animate__animated","animate__faster",e.hoverPreviewAnimation===n.value&&"animate__".concat(n.value)]]},Object(h["toDisplayString"])(n.name),3)],40,["onMouseenter","onClick"])})),128))])])})),128))])]})),default:us((function(){return[Object(h["createVNode"])(l,{class:"element-animation-btn"},{default:us((function(){return[Object(h["createVNode"])(r,{style:{"margin-right":"5px"}}),Object(h["createTextVNode"])(" "+Object(h["toDisplayString"])(e.handleElementAnimation||"点击选择动画"),1)]})),_:1})]})),_:1},8,["visible"])])):(Object(h["openBlock"])(),Object(h["createBlock"])("div",ms,[Object(h["createVNode"])(u),vs])),Object(h["createVNode"])(d),Object(h["createVNode"])(b,{class:"animation-sequence",modelValue:e.animationSequence,animation:300,scroll:!0,scrollSensitivity:50,onEnd:e.handleDragEnd,itemKey:"id"},{item:us((function(t){var n,o=t.element,c=t.index;return[Object(h["createVNode"])("div",{class:["sequence-item",{active:(null===(n=e.handleElement)||void 0===n?void 0:n.id)===o.elId}]},[Object(h["createVNode"])("div",Os,Object(h["toDisplayString"])(c+1),1),Object(h["createVNode"])("div",hs,"【"+Object(h["toDisplayString"])(o.elType)+"】"+Object(h["toDisplayString"])(o.animationType),1),Object(h["createVNode"])("div",js,[Object(h["createVNode"])(f,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"预览"},{default:us((function(){return[Object(h["createVNode"])(s,{class:"handler-btn",onClick:function(t){return e.runAnimation(o.elId,o.type)}},null,8,["onClick"])]})),_:2},1032,["mouseEnterDelay"]),Object(h["createVNode"])(f,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"删除"},{default:us((function(){return[Object(h["createVNode"])(p,{class:"handler-btn",onClick:function(t){return e.deleteAnimation(o.elId)}},null,8,["onClick"])]})),_:2},1032,["mouseEnterDelay"])])],2)]})),_:1},8,["modelValue","onEnd"])])})),ks=[{type:"bounce",name:"弹跳",children:[{name:"弹入",value:"bounceIn"},{name:"向右弹入",value:"bounceInLeft"},{name:"向左弹入",value:"bounceInRight"},{name:"向上弹入",value:"bounceInUp"},{name:"向下弹入",value:"bounceInDown"}]},{type:"fade",name:"浮现",children:[{name:"浮入",value:"fadeIn"},{name:"向下浮入",value:"fadeInDown"},{name:"向下长距浮入",value:"fadeInDownBig"},{name:"向右浮入",value:"fadeInLeft"},{name:"向右长距浮入",value:"fadeInLeftBig"},{name:"向左浮入",value:"fadeInRight"},{name:"向左长距浮入",value:"fadeInRightBig"},{name:"向上浮入",value:"fadeInUp"},{name:"向上长距浮入",value:"fadeInUpBig"},{name:"从左上浮入",value:"fadeInTopLeft"},{name:"从右上浮入",value:"fadeInTopRight"},{name:"从左下浮入",value:"fadeInBottomLeft"},{name:"从右下浮入",value:"fadeInBottomRight"}]},{type:"rotate",name:"旋转",children:[{name:"旋转进入",value:"rotateIn"},{name:"绕左下旋转进入",value:"rotateInDownLeft"},{name:"绕右下旋转进入",value:"rotateInDownRight"},{name:"绕左上旋转进入",value:"rotateInUpLeft"},{name:"绕右上旋转进入",value:"rotateInUpRight"}]},{type:"zoom",name:"缩放",children:[{name:"放大进入",value:"zoomIn"},{name:"向下放大进入",value:"zoomInDown"},{name:"从左放大进入",value:"zoomInLeft"},{name:"从右放大进入",value:"zoomInRight"},{name:"向上放大进入",value:"zoomInUp"}]},{type:"slide",name:"滑入",children:[{name:"向下滑入",value:"slideInDown"},{name:"从右滑入",value:"slideInLeft"},{name:"从左滑入",value:"slideInRight"},{name:"向上滑入",value:"slideInUp"}]},{type:"flip",name:"翻转",children:[{name:"X轴翻转进入",value:"flipInX"},{name:"Y轴翻转进入",value:"flipInY"}]},{type:"back",name:"放大滑入",children:[{name:"向下放大滑入",value:"backInDown"},{name:"从左放大滑入",value:"backInLeft"},{name:"从右放大滑入",value:"backInRight"},{name:"向上放大滑入",value:"backInUp"}]},{type:"lightSpeed",name:"飞入",children:[{name:"从右飞入",value:"lightSpeedInRight"},{name:"从左飞入",value:"lightSpeedInLeft"}]}],Es={},Is=Object(me["a"])(ks);try{for(Is.s();!(gs=Is.n()).done;){var Ss,Cs=gs.value,xs=Object(me["a"])(Cs.children);try{for(xs.s();!(Ss=xs.n()).done;){var Ns=Ss.value;Es[Ns.value]=Ns.name}}catch(cO){xs.e(cO)}finally{xs.f()}}}catch(cO){Is.e(cO)}finally{Is.f()}var Ts=Object(h["defineComponent"])({name:"element-animation-panel",components:{Draggable:Dr.a},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["computed"])((function(){return e.getters.currentSlideAnimations})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["ref"])(""),a=Object(h["ref"])(!1),r=ge(),l=r.addHistorySnapshot,i=ks,u=Object(h["computed"])((function(){if(!n.value)return[];var e,t=[],c=Object(me["a"])(n.value);try{var a=function(){var n=e.value,c=o.value.elements.find((function(e){return e.id===n.elId}));if(!c)return"continue";var a=At[c.type],r=Es[n.type];t.push(Object(P["a"])(Object(P["a"])({},n),{},{elType:a,animationType:r}))};for(c.s();!(e=c.n()).done;)a()}catch(cO){c.e(cO)}finally{c.f()}return t})),d=Object(h["computed"])((function(){if(!t.value)return null;var e=n.value||[],o=e.find((function(e){return e.elId===t.value.id}));return o?Es[o.type]:null})),s=function(o){var c=n.value.map((function(e){return e.elId===t.value.id?Object(P["a"])(Object(P["a"])({},e),{},{type:o}):e}));e.commit(g.UPDATE_SLIDE,{animations:c}),a.value=!1,l()},f=function(o){if(d.value)s(o);else{var c=n.value?JSON.parse(JSON.stringify(n.value)):[];c.push({elId:t.value.id,type:o,duration:1e3}),e.commit(g.UPDATE_SLIDE,{animations:c}),a.value=!1,l()}},p=function(t){var o=n.value.filter((function(e){return e.elId!==t}));e.commit(g.UPDATE_SLIDE,{animations:o}),l()},b=function(t){var o=t.newIndex,c=t.oldIndex;if(c!==o){var a=JSON.parse(JSON.stringify(n.value)),r=a[c];a.splice(c,1),a.splice(o,0,r),e.commit(g.UPDATE_SLIDE,{animations:a}),l()}},m=function(e,t){var n="animate__",o=document.querySelector("#editable-element-".concat(e," [class^=editable-element-]"));if(o){var c="".concat(n).concat(t);o.classList.add("".concat(n,"animated"),c);var a=function(){o.classList.remove("".concat(n,"animated"),c)};o.addEventListener("animationend",a,{once:!0})}};return{handleElement:t,animationPoolVisible:a,animations:i,animationSequence:u,hoverPreviewAnimation:c,handleElementAnimation:d,addAnimation:f,deleteAnimation:p,handleDragEnd:b,runAnimation:m}}});n("6836");Ts.render=ys,Ts.__scopeId="data-v-3483fbf2";var ws=Ts,Ls=Object(h["withScopeId"])("data-v-52253a56");Object(h["pushScopeId"])("data-v-52253a56");var Vs={class:"slide-style-panel"},_s=Object(h["createVNode"])("div",{class:"title"},"背景填充",-1),Bs={class:"row"},Ms=Object(h["createTextVNode"])("纯色填充"),Ds=Object(h["createTextVNode"])("图片填充"),As=Object(h["createTextVNode"])("渐变填充"),Ps=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1),Rs=Object(h["createTextVNode"])("原始大小"),Fs=Object(h["createTextVNode"])("缩放"),zs=Object(h["createTextVNode"])("拼贴"),Hs=Object(h["createTextVNode"])("缩放铺满"),Us=Object(h["createTextVNode"])("线性渐变"),Gs=Object(h["createTextVNode"])("径向渐变"),qs={key:0,class:"background-image-wrapper"},Ws={class:"background-image"},Xs={key:1,class:"background-gradient-wrapper"},Ys={class:"row"},Zs=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点颜色:",-1),Js={class:"row"},Ks=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点颜色:",-1),$s={key:0,class:"row"},Qs=Object(h["createVNode"])("div",{style:{flex:"2"}},"渐变角度:",-1),ef={class:"row"},tf=Object(h["createTextVNode"])("应用背景到全部"),nf=Object(h["createVNode"])("div",{class:"title"},"全局主题",-1),of={class:"row"},cf=Object(h["createVNode"])("div",{style:{flex:"2"}},"字体:",-1),af={class:"row"},rf=Object(h["createVNode"])("div",{style:{flex:"2"}},"字体颜色:",-1),lf={class:"row"},uf=Object(h["createVNode"])("div",{style:{flex:"2"}},"背景颜色:",-1),df={class:"row"},sf=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题色:",-1),ff=Object(h["createVNode"])("div",{class:"title",style:{"margin-top":"20px"}},"应用预置主题:",-1),pf={class:"theme-list"},bf={class:"theme-item-content"},mf={class:"row"},vf=Object(h["createTextVNode"])("应用主题到全部");Object(h["popScopeId"])();var Of=Ls((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("IconPlus"),f=Object(h["resolveComponent"])("FileInput"),p=Object(h["resolveComponent"])("Slider"),b=Object(h["resolveComponent"])("Button"),m=Object(h["resolveComponent"])("Divider"),v=Object(h["resolveComponent"])("SelectOptGroup");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Vs,[_s,Object(h["createVNode"])("div",Bs,[Object(h["createVNode"])(l,{style:{flex:"10"},value:e.background.type,onChange:t[1]||(t[1]=function(t){return e.updateBackgroundType(t)})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"solid"},{default:Ls((function(){return[Ms]})),_:1}),Object(h["createVNode"])(r,{value:"image"},{default:Ls((function(){return[Ds]})),_:1}),Object(h["createVNode"])(r,{value:"gradient"},{default:Ls((function(){return[As]})),_:1})]})),_:1},8,["value"]),Ps,"solid"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])(d,{key:0,trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.color,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateBackground({color:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.color||"#fff",style:{flex:"10"}},null,8,["color"])]})),_:1})):"image"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,style:{flex:"10"},value:e.background.size||"cover",onChange:t[3]||(t[3]=function(t){return e.updateBackground({imageSize:t})})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"initial"},{default:Ls((function(){return[Rs]})),_:1}),Object(h["createVNode"])(r,{value:"contain"},{default:Ls((function(){return[Fs]})),_:1}),Object(h["createVNode"])(r,{value:"repeat"},{default:Ls((function(){return[zs]})),_:1}),Object(h["createVNode"])(r,{value:"cover"},{default:Ls((function(){return[Hs]})),_:1})]})),_:1},8,["value"])):(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:2,style:{flex:"10"},value:e.background.gradientType,onChange:t[4]||(t[4]=function(t){return e.updateBackground({gradientType:t})})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"linear"},{default:Ls((function(){return[Us]})),_:1}),Object(h["createVNode"])(r,{value:"radial"},{default:Ls((function(){return[Gs]})),_:1})]})),_:1},8,["value"]))]),"image"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",qs,[Object(h["createVNode"])(f,{onChange:t[5]||(t[5]=function(t){return e.uploadBackgroundImage(t)})},{default:Ls((function(){return[Object(h["createVNode"])("div",Ws,[Object(h["createVNode"])("div",{class:"content",style:{backgroundImage:"url(".concat(e.background.image,")")}},[Object(h["createVNode"])(s)],4)])]})),_:1})])):Object(h["createCommentVNode"])("",!0),"gradient"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",Xs,[Object(h["createVNode"])("div",Ys,[Zs,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.gradientColor[0],"onUpdate:modelValue":t[6]||(t[6]=function(t){return e.updateBackground({gradientColor:[t,e.background.gradientColor[1]]})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.gradientColor[0],style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",Js,[Ks,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.gradientColor[1],"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.updateBackground({gradientColor:[e.background.gradientColor[0],t]})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.gradientColor[1],style:{flex:"3"}},null,8,["color"])]})),_:1})]),"linear"===e.background.gradientType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",$s,[Qs,Object(h["createVNode"])(p,{min:0,max:360,step:15,value:e.background.gradientRotate,style:{flex:"3"},onChange:t[8]||(t[8]=function(t){return e.updateBackground({gradientRotate:t})})},null,8,["value"])])):Object(h["createCommentVNode"])("",!0)])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",ef,[Object(h["createVNode"])(b,{style:{flex:"1"},onClick:t[9]||(t[9]=function(t){return e.applyBackgroundAllSlide()})},{default:Ls((function(){return[tf]})),_:1})]),Object(h["createVNode"])(m),nf,Object(h["createVNode"])("div",of,[cf,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.theme.fontName,onChange:t[10]||(t[10]=function(t){return e.updateTheme({fontName:t})})},{default:Ls((function(){return[Object(h["createVNode"])(v,{label:"系统字体"},{default:Ls((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.availableFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.en,value:e.en},{default:Ls((function(){return[Object(h["createVNode"])("span",{style:{fontFamily:e.en}},Object(h["toDisplayString"])(e.zh),5)]})),_:2},1032,["value"])})),128))]})),_:1}),Object(h["createVNode"])(v,{label:"在线字体"},{default:Ls((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.webFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.name,value:e.name},{default:Ls((function(){return[Object(h["createVNode"])("span",null,Object(h["toDisplayString"])(e.name),1)]})),_:2},1032,["value"])})),128))]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",af,[rf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.fontColor,"onUpdate:modelValue":t[11]||(t[11]=function(t){return e.updateTheme({fontColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.fontColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",lf,[uf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.backgroundColor,"onUpdate:modelValue":t[12]||(t[12]=function(t){return e.updateTheme({backgroundColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.backgroundColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",df,[sf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.themeColor,"onUpdate:modelValue":t[13]||(t[13]=function(t){return e.updateTheme({themeColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.themeColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),ff,Object(h["createVNode"])("div",pf,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.themes,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"theme-item",key:n,style:{backgroundColor:t.background},onClick:function(n){return e.updateTheme({fontColor:t.text,backgroundColor:t.background,themeColor:t.color})}},[Object(h["createVNode"])("div",bf,[Object(h["createVNode"])("div",{class:"text",style:{color:t.text}},"Aa",4),Object(h["createVNode"])("div",{class:"color-block",style:{backgroundColor:t.color}},null,4)])],12,["onClick"])})),128))]),Object(h["createVNode"])("div",mf,[Object(h["createVNode"])(b,{style:{flex:"1"},onClick:t[14]||(t[14]=function(t){return e.applyThemeAllSlide()})},{default:Ls((function(){return[vf]})),_:1})])])})),hf=[{color:"#d14424",background:"#ffffff",text:"#333"},{color:"#42464b",background:"#ffffff",text:"#333"},{color:"#5d82ba",background:"#ffffff",text:"#333"},{color:"#005a6f",background:"#ffffff",text:"#333"},{color:"#d0614c",background:"#dfb044",text:"#333"},{color:"#86a1ad",background:"#dfdbd4",text:"#333"},{color:"#697586",background:"#d5c4a4",text:"#333"},{color:"#333333",background:"#7acfa6",text:"#333"},{color:"#42464b",background:"#415065",text:"#fff"},{color:"#0c5999",background:"#35a2cd",text:"#fff"},{color:"#c49a41",background:"#8c4357",text:"#fff"},{color:"#dfaa00",background:"#2e4e7d",text:"#fff"},{color:"#d1ad88",background:"#f99070",text:"#fff"},{color:"#464d52",background:"#657984",text:"#fff"},{color:"#ffcfb6",background:"#1e4c6f",text:"#fff"},{color:"#c3a043",background:"#43292a",text:"#fff"},{color:"#ffffff",background:"#171925",text:"#fff"},{color:"#df9636",background:"#5b89a0",text:"#fff"},{color:"#b898a4",background:"#93716b",text:"#fff"},{color:"#c47a11",background:"#187db1",text:"#fff"},{color:"#333333",background:"#759564",text:"#fff"},{color:"#355b5e",background:"#424b50",text:"#fff"},{color:"#d29090",background:"#942a32",text:"#fff"},{color:"#00cfdf",background:"#3b434d",text:"#fff"},{color:"#424246",background:"#c70042",text:"#fff"},{color:"#2e4155",background:"#b35d44",text:"#fff"},{color:"#11bfce",background:"#8f98aa",text:"#fff"},{color:"#333333",background:"#549688",text:"#fff"}],jf=hf,gf=H,yf=Object(h["defineComponent"])({name:"slide-style-panel",components:{ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.theme})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["computed"])((function(){return e.state.availableFonts})),a=Object(h["computed"])((function(){return o.value.background?o.value.background:{type:"solid",value:"#fff"}})),r=ge(),l=r.addHistorySnapshot,i=function(t){if("solid"===t){var n=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"solid",color:a.value.color||"#fff"});e.commit(g.UPDATE_SLIDE,{background:n})}else if("image"===t){var o=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"image",image:a.value.image||"",imageSize:a.value.imageSize||"cover"});e.commit(g.UPDATE_SLIDE,{background:o})}else{var c=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"gradient",gradientType:a.value.gradientType||"linear",gradientColor:a.value.gradientColor||["#fff","#fff"],gradientRotate:a.value.gradientRotate||0});e.commit(g.UPDATE_SLIDE,{background:c})}l()},u=function(t){e.commit(g.UPDATE_SLIDE,{background:Object(P["a"])(Object(P["a"])({},a.value),t)}),l()},d=function(e){var t=e[0];t&&ke(t).then((function(e){return u({image:e})}))},s=function(){var n=t.value.map((function(e){return Object(P["a"])(Object(P["a"])({},e),{},{background:o.value.background})}));e.commit(g.SET_SLIDES,n),l()},f=function(t){e.commit(g.SET_THEME,t)},p=function(){var o,c=JSON.parse(JSON.stringify(t.value)),a=n.value,r=a.themeColor,i=a.backgroundColor,u=a.fontColor,d=Object(me["a"])(c);try{for(d.s();!(o=d.n()).done;){var s=o.value;s.background&&"image"===s.background.type||(s.background=Object(P["a"])(Object(P["a"])({},s.background),{},{type:"solid",color:i}));var f,p=s.elements,b=Object(me["a"])(p);try{for(b.s();!(f=b.n()).done;){var m=f.value;"shape"===m.type?m.fill=r:"line"===m.type?m.color=r:"text"===m.type?m.fill&&(m.fill=r):"table"===m.type?m.theme&&(m.theme.color=r):"chart"===m.type&&(m.themeColor=r,m.gridColor=u)}}catch(cO){b.e(cO)}finally{b.f()}}}catch(cO){d.e(cO)}finally{d.f()}e.commit(g.SET_SLIDES,c),l()};return{availableFonts:c,background:a,updateBackgroundType:i,updateBackground:u,uploadBackgroundImage:d,applyBackgroundAllSlide:s,themes:jf,theme:n,webFonts:gf,updateTheme:f,applyThemeAllSlide:p}}});n("3639");yf.render=Of,yf.__scopeId="data-v-52253a56";var kf=yf,Ef=Object(h["withScopeId"])("data-v-a3bc22da");Object(h["pushScopeId"])("data-v-a3bc22da");var If={class:"slide-animation-panel"},Sf={class:"animation-pool"},Cf={class:"animation-text"},xf=Object(h["createTextVNode"])("应用到全部");Object(h["popScopeId"])();var Nf=Ef((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",If,[Object(h["createVNode"])("div",Sf,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.animations,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["animation-item",{active:e.currentTurningMode===t.value}],key:t.label,onClick:function(n){return e.updateTurningMode(t.value)}},[Object(h["createVNode"])("div",{class:["animation-block",t.value]},null,2),Object(h["createVNode"])("div",Cf,Object(h["toDisplayString"])(t.label),1)],10,["onClick"])})),128))]),Object(h["createVNode"])(r,{style:{width:"100%"},onClick:t[1]||(t[1]=function(t){return e.applyAllSlide()})},{default:Ef((function(){return[xf]})),_:1})])})),Tf=Object(h["defineComponent"])({name:"slide-animation-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.getters.currentSlide})),o=Object(h["computed"])((function(){return n.value.turningMode||"slideY"})),c=[{label:"无",value:"no"},{label:"淡入淡出",value:"fade"},{label:"左右推移",value:"slideX"},{label:"上下推移",value:"slideY"}],a=ge(),r=a.addHistorySnapshot,l=function(t){t!==o.value&&(e.commit(g.UPDATE_SLIDE,{turningMode:t}),r())},i=function(){var o=t.value.map((function(e){return Object(P["a"])(Object(P["a"])({},e),{},{turningMode:n.value.turningMode})}));e.commit(g.SET_SLIDES,o),r()};return{currentTurningMode:o,animations:c,updateTurningMode:l,applyAllSlide:i}}});n("3f04");Tf.render=Nf,Tf.__scopeId="data-v-a3bc22da";var wf=Tf,Lf=Object(h["withScopeId"])("data-v-1040b5b1");Object(h["pushScopeId"])("data-v-1040b5b1");var Vf={class:"multi-position-panel"},_f=Object(h["createTextVNode"])("组合"),Bf=Object(h["createTextVNode"])("取消组合");Object(h["popScopeId"])();var Mf=Lf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconAlignLeft"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Tooltip"),u=Object(h["resolveComponent"])("IconAlignVertically"),d=Object(h["resolveComponent"])("IconAlignRight"),s=Object(h["resolveComponent"])("ButtonGroup"),f=Object(h["resolveComponent"])("IconAlignTop"),p=Object(h["resolveComponent"])("IconAlignHorizontally"),b=Object(h["resolveComponent"])("IconAlignBottom"),m=Object(h["resolveComponent"])("Divider"),v=Object(h["resolveComponent"])("IconGroup"),O=Object(h["resolveComponent"])("IconUngroup");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Vf,[Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[1]||(t[1]=function(t){return e.alignActiveElement("left")})},{default:Lf((function(){return[Object(h["createVNode"])(r)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"水平居中"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[2]||(t[2]=function(t){return e.alignActiveElement("horizontal")})},{default:Lf((function(){return[Object(h["createVNode"])(u)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[3]||(t[3]=function(t){return e.alignActiveElement("right")})},{default:Lf((function(){return[Object(h["createVNode"])(d)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[4]||(t[4]=function(t){return e.alignActiveElement("top")})},{default:Lf((function(){return[Object(h["createVNode"])(f)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"垂直居中"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[5]||(t[5]=function(t){return e.alignActiveElement("vertical")})},{default:Lf((function(){return[Object(h["createVNode"])(p)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[6]||(t[6]=function(t){return e.alignActiveElement("bottom")})},{default:Lf((function(){return[Object(h["createVNode"])(b)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(m),Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(l,{disabled:!e.canCombine,onClick:t[7]||(t[7]=function(t){return e.combineElements()}),style:{flex:"1"}},{default:Lf((function(){return[Object(h["createVNode"])(v,{style:{"margin-right":"3px"}}),_f]})),_:1},8,["disabled"]),Object(h["createVNode"])(l,{disabled:e.canCombine,onClick:t[8]||(t[8]=function(t){return e.uncombineElements()}),style:{flex:"1"}},{default:Lf((function(){return[Object(h["createVNode"])(O,{style:{"margin-right":"3px"}}),Bf]})),_:1},8,["disabled"])]})),_:1})])})),Df=Object(h["defineComponent"])({name:"multi-position-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.getters.activeElementList})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=ge(),a=c.addHistorySnapshot,r=we(),l=r.combineElements,i=r.uncombineElements,u=Object(h["computed"])((function(){var e=n.value[0].groupId;if(!e)return!0;var t=n.value.every((function(t){return(t.groupId&&t.groupId)===e}));return!t})),d=function(c){var r,l=xt(n.value),i=l.minX,u=l.maxX,d=l.minY,s=l.maxY,f=JSON.parse(JSON.stringify(o.value.elements)),p={},b=Object(me["a"])(n.value);try{var m=function(){var e=r.value;if(e.groupId&&!p[e.groupId]){var t=n.value.filter((function(t){return t.groupId===e.groupId}));p[e.groupId]=xt(t)}};for(b.s();!(r=b.n()).done;)m()}catch(cO){b.e(cO)}finally{b.f()}if(c===ht.LEFT)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.minX-i;e.left=e.left-o}else e.left=i}));else if(c===ht.RIGHT)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.maxX-u;e.left=e.left-o}else{var c="line"===e.type?Math.max(e.start[0],e.end[0]):e.width;e.left=u-c}}));else if(c===ht.TOP)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.minY-d;e.top=e.top-o}else e.top=d}));else if(c===ht.BOTTOM)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.maxY-s;e.top=e.top-o}else{var c="line"===e.type?Math.max(e.start[1],e.end[1]):e.height;e.top=s-c}}));else if(c===ht.HORIZONTAL){var v=(i+u)/2;f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=(n.maxX+n.minX)/2,c=o-v;e.left=e.left-c}else{var a="line"===e.type?Math.max(e.start[0],e.end[0]):e.width;e.left=v-a/2}}))}else if(c===ht.VERTICAL){var O=(d+s)/2;f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=(n.maxY+n.minY)/2,c=o-O;e.top=e.top-c}else{var a="line"===e.type?Math.max(e.start[1],e.end[1]):e.height;e.top=O-a/2}}))}e.commit(g.UPDATE_SLIDE,{elements:f}),a()};return{canCombine:u,combineElements:l,uncombineElements:i,alignActiveElement:d}}});n("50dd");Df.render=Mf,Df.__scopeId="data-v-1040b5b1";var Af=Df,Pf=Object(h["defineComponent"])({name:"toolbar",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.toolbarState})),n=[{label:"样式",value:xl.EL_STYLE},{label:"位置",value:xl.EL_POSITION},{label:"动画",value:xl.EL_ANIMATION}],o=[{label:"页面样式",value:xl.SLIDE_STYLE},{label:"切换",value:xl.SLIDE_ANIMATION},{label:"动画",value:xl.EL_ANIMATION}],c=[{label:"位置",value:xl.MULTI_POSITION},{label:"样式",value:xl.EL_STYLE}],a=function(t){e.commit(g.SET_TOOLBAR_STATE,t)},r=Object(h["computed"])((function(){return e.state.activeElementIdList})),l=Object(h["computed"])((function(){return r.value.length?r.value.length>1?c:n:o}));Object(h["watch"])(l,(function(){var n=l.value.map((function(e){return e.value}));n.includes(t.value)||e.commit(g.SET_TOOLBAR_STATE,n[0])}));var i=Object(h["computed"])((function(){var e,n=(e={},Object(C["a"])(e,xl.EL_STYLE,Gd),Object(C["a"])(e,xl.EL_POSITION,is),Object(C["a"])(e,xl.EL_ANIMATION,ws),Object(C["a"])(e,xl.SLIDE_STYLE,kf),Object(C["a"])(e,xl.SLIDE_ANIMATION,wf),Object(C["a"])(e,xl.MULTI_POSITION,Af),e);return n[t.value]||null}));return{toolbarState:t,currentTabs:l,setToolbarState:a,currentPanelComponent:i}}});n("3179");Pf.render=Cl,Pf.__scopeId="data-v-8468ba32";var Rf=Pf,Ff=Object(h["defineComponent"])({name:"editor",components:{EditorHeader:bt,Canvas:Fa,CanvasTool:Tr,Thumbnails:yl,Toolbar:Rf},setup:function(){Re(),Fe()}});n("a6cc");Ff.render=Q,Ff.__scopeId="data-v-d5c6b448";var zf=Ff,Hf=Object(h["withScopeId"])("data-v-048f6280");Object(h["pushScopeId"])("data-v-048f6280");var Uf={class:"hamster-ppt-screen"},Gf={class:"tools"};Object(h["popScopeId"])();var qf=Hf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ScreenSlide"),l=Object(h["resolveComponent"])("SlideThumbnails"),i=Object(h["resolveComponent"])("Modal"),u=Object(h["resolveComponent"])("IconLeftC"),d=Object(h["resolveComponent"])("IconRightC"),s=Object(h["resolveComponent"])("IconSearch"),f=Object(h["resolveComponent"])("WritingBoardTool"),p=Object(h["resolveComponent"])("IconWrite"),b=Object(h["resolveComponent"])("Popover"),m=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Uf,[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"slide-list",onMousewheel:t[1]||(t[1]=function(t){return e.mousewheelListener(t)})},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slides,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["slide-item","turning-mode-".concat(t.turningMode||"slideY"),{current:n===e.slideIndex,before:ne.slideIndex,hide:(n===e.slideIndex-1||n===e.slideIndex+1)&&t.turningMode!==e.currentSlide.turningMode}],key:t.id},[Object(h["createVNode"])("div",{class:"slide-content",style:{width:e.slideWidth+"px",height:e.slideHeight+"px"}},[Object(h["createVNode"])(r,{slide:t,scale:e.scale,animationIndex:e.animationIndex},null,8,["slide","scale","animationIndex"])],4)],2)})),128))],544),[[m,e.contextmenus]]),Object(h["createVNode"])(i,{visible:e.slideThumbnailModelVisible,"onUpdate:visible":t[2]||(t[2]=function(t){return e.slideThumbnailModelVisible=t}),footer:null,centered:"",width:1020,bodyStyle:{padding:"50px 20px 20px 20px"}},{default:Hf((function(){return[Object(h["createVNode"])(l,{turnSlideToIndex:e.turnSlideToIndex},null,8,["turnSlideToIndex"])]})),_:1},8,["visible"]),Object(h["createVNode"])("div",Gf,[Object(h["createVNode"])(u,{class:"tool-btn",onClick:t[3]||(t[3]=function(t){return e.execPrev()})}),Object(h["createVNode"])(d,{class:"tool-btn",onClick:t[4]||(t[4]=function(t){return e.execNext()})}),Object(h["createVNode"])(s,{class:"tool-btn",onClick:t[5]||(t[5]=function(t){return e.slideThumbnailModelVisible=!0})}),Object(h["createVNode"])(b,{trigger:"click",visible:e.writingBoardToolVisible,"onUpdate:visible":t[7]||(t[7]=function(t){return e.writingBoardToolVisible=t})},{content:Hf((function(){return[Object(h["createVNode"])(f,{onClose:t[6]||(t[6]=function(t){return e.writingBoardToolVisible=!1})})]})),default:Hf((function(){return[Object(h["createVNode"])(p,{class:"tool-btn"})]})),_:1},8,["visible"])])])})),Wf=Object(h["withScopeId"])("data-v-5e193d56"),Xf=Wf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ScreenElement");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-slide",style:{width:e.VIEWPORT_SIZE+"px",height:e.VIEWPORT_SIZE*e.VIEWPORT_ASPECT_RATIO+"px",transform:"scale(".concat(e.scale,")")}},[Object(h["createVNode"])("div",{class:"background",style:Object(P["a"])({},e.backgroundStyle)},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slide.elements,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{id:"screen-element-".concat(t.id),key:t.id,elementInfo:t,elementIndex:n+1,animationIndex:e.animationIndex},null,8,["id","elementInfo","elementIndex","animationIndex"])})),128))],4)}));function Yf(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-element",style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName,visibility:e.needWaitAnimation?"hidden":"visible"}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo},null,8,["elementInfo"]))],4)}var Zf=Object(h["withScopeId"])("data-v-1423f8c2"),Jf=Zf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementOutline"),l=Object(h["resolveComponent"])("Chart");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-element-chart",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px"}},[Object(h["createVNode"])("div",{class:"element-content",style:{backgroundColor:e.elementInfo.fill}},[Object(h["createVNode"])(r,{width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"]),Object(h["createVNode"])(l,{width:e.elementInfo.width,height:e.elementInfo.height,type:e.elementInfo.chartType,data:e.elementInfo.data,options:e.elementInfo.options,themeColor:e.elementInfo.themeColor,gridColor:e.elementInfo.gridColor},null,8,["width","height","type","data","options","themeColor","gridColor"])],4)],4)})),Kf=Object(h["defineComponent"])({name:"screen-element-chart",components:{ElementOutline:To,Chart:lc},props:{elementInfo:{type:Object,required:!0}}});n("1539");Kf.render=Jf,Kf.__scopeId="data-v-1423f8c2";var $f=Kf,Qf=Object(h["defineComponent"])({name:"screen-element",props:{elementInfo:{type:Object,required:!0},elementIndex:{type:Number,required:!0},animationIndex:{type:Number,default:-1}},setup:function(e){var t=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,Ur),Object(C["a"])(t,Jt.TEXT,Xr),Object(C["a"])(t,Jt.SHAPE,$r),Object(C["a"])(t,Jt.LINE,nl),Object(C["a"])(t,Jt.CHART,$f),Object(C["a"])(t,Jt.TABLE,ml),t);return n[e.elementInfo.type]||null})),n=X(),o=Object(h["computed"])((function(){return n.state.theme})),c=Object(h["computed"])((function(){return n.getters.currentSlide})),a=Object(h["computed"])((function(){var t=c.value.animations||[],n=t.findIndex((function(t){return t.elId===e.elementInfo.id}));return-1!==n&&n>=e.animationIndex}));return{currentElementComponent:t,needWaitAnimation:a,theme:o}}});Qf.render=Yf;var ep=Qf,tp=Object(h["defineComponent"])({name:"screen-slide",components:{ScreenElement:ep},props:{slide:{type:Object,required:!0},scale:{type:Number,required:!0},animationIndex:{type:Number,default:-1}},setup:function(e){var t=Object(h["computed"])((function(){return e.slide.background})),n=Mc(t),o=n.backgroundStyle;return{backgroundStyle:o,VIEWPORT_SIZE:Ee,VIEWPORT_ASPECT_RATIO:Ie}}});n("993a");tp.render=Xf,tp.__scopeId="data-v-5e193d56";var np=tp,op=Object(h["withScopeId"])("data-v-5b8ebe1d");Object(h["pushScopeId"])("data-v-5b8ebe1d");var cp={class:"slide-thumbnails"};Object(h["popScopeId"])();var ap=op((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ThumbnailSlide");return Object(h["openBlock"])(),Object(h["createBlock"])("div",cp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slides,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["thumbnail",{active:n===e.slideIndex}],key:t.id,onClick:function(t){return e.turnSlideToIndex(n)}},[Object(h["createVNode"])(r,{slide:t,size:150},null,8,["slide"])],10,["onClick"])})),128))])})),rp=Object(h["defineComponent"])({name:"slide-thumbnails",components:{ThumbnailSlide:jl},props:{turnSlideToIndex:{type:Function}},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.slideIndex}));return{slides:t,slideIndex:n}}});n("add0");rp.render=ap,rp.__scopeId="data-v-5b8ebe1d";var lp=rp,ip=Object(h["withScopeId"])("data-v-0ecab351");Object(h["pushScopeId"])("data-v-0ecab351");var up={class:"writing-board-tool"},dp={class:"tools"},sp={class:"colors"};Object(h["popScopeId"])();var fp=ip((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("WritingBoard"),l=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",up,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Teleport"],{to:"body"},[e.writingBoardVisible?Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,ref:"writingBoardRef",color:e.writingBoardColor,model:e.writingBoardModel},null,8,["color","model"])),[[l,e.contextmenus]]):Object(h["createCommentVNode"])("",!0)])),Object(h["createVNode"])("div",dp,[Object(h["createVNode"])("div",{class:"btn",onClick:t[1]||(t[1]=function(t){return e.changePen()})},"画笔"),Object(h["createVNode"])("div",{class:"btn",onClick:t[2]||(t[2]=function(t){return e.changeEraser()})},"橡皮擦"),Object(h["createVNode"])("div",{class:"btn",onClick:t[3]||(t[3]=function(t){return e.clearCanvas()})},"擦除所有墨迹"),Object(h["createVNode"])("div",{class:"btn",onClick:t[4]||(t[4]=function(t){return e.closeWritingBoard()})},"退出画笔"),Object(h["createVNode"])("div",sp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.writingBoardColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["color",{active:t===e.writingBoardColor}],key:t,style:{backgroundColor:t},onClick:function(n){return e.changeColor(t)}},null,14,["onClick"])})),128))])])])})),pp=Object(h["withScopeId"])("data-v-5b8a1ac6");Object(h["pushScopeId"])("data-v-5b8a1ac6");var bp={class:"writing-board",ref:"writingBoardRef"};Object(h["popScopeId"])();var mp=pp((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconWrite"),l=Object(h["resolveComponent"])("IconClearFormat");return Object(h["openBlock"])(),Object(h["createBlock"])("div",bp,[Object(h["createVNode"])("canvas",{class:"canvas",ref:"canvasRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMousedown(t)}),onMousemove:t[2]||(t[2]=function(t){return e.handleMousemove(t)}),onMouseup:t[3]||(t[3]=function(t){return e.handleMouseup()}),onMouseleave:t[4]||(t[4]=function(t){e.handleMouseup(),e.mouseInCanvas=!1}),onMouseenter:t[5]||(t[5]=function(t){return e.mouseInCanvas=!0})},null,544),e.mouseInCanvas&&"pen"===e.model?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:"pen",style:{left:e.mouse.x-e.penSize/2+"px",top:e.mouse.y-36+e.penSize/2+"px",color:e.color}},[Object(h["createVNode"])(r,{class:"icon",size:"36"})],4)):Object(h["createCommentVNode"])("",!0),e.mouseInCanvas&&"eraser"===e.model?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:1,class:"eraser",style:{left:e.mouse.x-e.rubberSize/2+"px",top:e.mouse.y-e.rubberSize/2+"px",width:e.rubberSize+"px",height:e.rubberSize+"px"}},[Object(h["createVNode"])(l,{class:"icon",size:.6*e.rubberSize},null,8,["size"])],4)):Object(h["createCommentVNode"])("",!0)],512)})),vp=6,Op=80,hp=Object(h["defineComponent"])({name:"writing-board",props:{color:{type:String,default:"#ffcc00"},model:{type:String,default:"pen"}},setup:function(e){var t=null,n=Object(h["ref"])(),o=Object(h["ref"])(),c={x:0,y:0},a=!1,r=0,l=-1,i=Object(h["reactive"])({x:0,y:0}),u=Object(h["ref"])(!1),d=function(){o.value&&n.value&&(t=o.value.getContext("2d"),t&&(o.value.width=n.value.clientWidth,o.value.height=n.value.clientHeight,o.value.style.width=n.value.clientWidth+"px",o.value.style.height=n.value.clientHeight+"px",t.lineCap="round",t.lineJoin="round"))},s=function(e,t){var n=c.x,o=c.y;return Math.sqrt((e-n)*(e-n)+(t-o)*(t-o))},f=function(e,t){var n,o=10,c=.1,a=vp,r=3,i=e/t;return n=i<=c?a:i>=o?r:a-i/o*a,-1===l?n:1*n/3+2*l/3},p=function(n,o,a){if(t){var r=c.x,l=c.y;t.lineWidth=a,t.strokeStyle=e.color,t.beginPath(),t.moveTo(r,l),t.lineTo(n,o),t.stroke(),t.closePath()}},b=function(e,n){var a,r,l,i;if(t&&o.value){var u=c.x,d=c.y,s=Op/2,f=s*Math.sin(Math.atan((n-d)/(e-u))),p=s*Math.cos(Math.atan((n-d)/(e-u))),b=[u+f,d-p],m=[u-f,d+p],v=[e+f,n-p],O=[e-f,n+p];t.save(),t.beginPath(),t.arc(e,n,s,0,2*Math.PI),t.clip(),t.clearRect(0,0,o.value.width,o.value.height),t.restore(),t.save(),t.beginPath(),(a=t).moveTo.apply(a,b),(r=t).lineTo.apply(r,v),(l=t).lineTo.apply(l,O),(i=t).lineTo.apply(i,m),t.closePath(),t.clip(),t.clearRect(0,0,o.value.width,o.value.height),t.restore()}},m=function(e,t){c={x:e,y:t},r=(new Date).getTime()},v=function(t,n){var o=(new Date).getTime();if("pen"===e.model){var a=s(t,n),i=o-r,u=f(a,i);p(t,n,u),l=u}else b(t,n);c={x:t,y:n},r=(new Date).getTime()},O=function(e){a=!0,m(e.offsetX,e.offsetY)},j=function(e){i.x=e.pageX,i.y=e.pageY},g=function(e){j(e),a&&v(e.offsetX,e.offsetY)},y=function(){a&&(a=!1)},k=function(){t&&o.value&&t.clearRect(0,0,o.value.width,o.value.height)};return Object(h["onMounted"])(d),{mouse:i,mouseInCanvas:u,penSize:vp,rubberSize:Op,writingBoardRef:n,canvasRef:o,handleMousedown:O,handleMousemove:g,handleMouseup:y,clearCanvas:k}}});n("45ac");hp.render=mp,hp.__scopeId="data-v-5b8a1ac6";var jp=hp,gp=["#000000","#ffffff","#1e497b","#4e81bb","#e2534d","#9aba60","#8165a0","#47acc5","#f9974c"],yp=Object(h["defineComponent"])({name:"writing-board-tool",components:{WritingBoard:jp},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=Object(h["ref"])(!1),a=Object(h["ref"])("#e2534d"),r=Object(h["ref"])("pen"),l=function(){c.value||(c.value=!0),r.value="pen",n("close")},i=function(){r.value="eraser",n("close")},u=function(){o.value.clearCanvas(),n("close")},d=function(e){"pen"!==r.value&&(r.value="pen"),a.value=e,n("close")},s=function(){c.value=!1,n("close")},f=function(){return[{text:"画笔",handler:l,disable:"pen"===r.value},{text:"橡皮擦",handler:i,disable:"eraser"===r.value},{text:"擦除所有墨迹",handler:u},{text:"退出画笔",handler:s}]};return{writingBoardRef:o,writingBoardVisible:c,writingBoardColors:gp,writingBoardColor:a,writingBoardModel:r,changePen:l,changeEraser:i,clearCanvas:u,changeColor:d,closeWritingBoard:s,contextmenus:f}}});n("8a4a");yp.render=fp,yp.__scopeId="data-v-0ecab351";var kp=yp,Ep=Object(h["defineComponent"])({name:"screen",components:{ScreenSlide:np,SlideThumbnails:lp,WritingBoardTool:kp},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.slideIndex})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["ref"])(0),a=Object(h["ref"])(0),r=Object(h["computed"])((function(){return c.value/Ee})),l=Object(h["ref"])(!1),i=Object(h["ref"])(!1),u=function(){var e,t,n=document.body.clientWidth,o=document.body.clientHeight;o/n===Ie?(e=n,t=o):o/n>Ie?(e=n,t=n*Ie):(e=o/Ie,t=o),c.value=e,a.value=t},d=Ae(),s=d.exitScreening,f=function(){u(),De()||s()},p=Object(h["ref"])(0),b=Object(h["computed"])((function(){return o.value.animations||[]})),m=function(){var e="animate__",t=b.value[p.value];p.value+=1;var n=document.querySelector("#screen-element-".concat(t.elId," [class^=base-element-]"));if(n){var o="".concat(e).concat(t.type);n.classList.add("".concat(e,"animated"),o);var c=function(){n.classList.remove("".concat(e,"animated"),o)};n.addEventListener("animationend",c,{once:!0})}},v=function(){if(b.value.length&&p.value>0)p.value-=1;else if(n.value>0){e.commit(g.UPDATE_SLIDE_INDEX,n.value-1);var t=b.value?b.value.length:0;p.value=t}},O=function(){b.value.length&&p.value0&&O()}),500,{leading:!0,trailing:!1});Object(h["onMounted"])((function(){window.addEventListener("resize",f),document.addEventListener("keydown",j)})),Object(h["onUnmounted"])((function(){window.removeEventListener("resize",f),document.removeEventListener("keydown",j)}));var k=function(){e.commit(g.UPDATE_SLIDE_INDEX,n.value-1),p.value=0},E=function(){e.commit(g.UPDATE_SLIDE_INDEX,n.value+1),p.value=0},I=function(t){l.value=!1,e.commit(g.UPDATE_SLIDE_INDEX,t),p.value=0},S=function(){return[{text:"上一页",disable:n.value<=0,handler:function(){return k()}},{text:"下一页",disable:n.value>=t.value.length-1,handler:function(){return E()}},{text:"结束放映",subText:"ESC",handler:s}]};return Object(h["provide"])("slideScale",r),{slides:t,slideIndex:n,currentSlide:o,slideWidth:c,slideHeight:a,scale:r,mousewheelListener:y,animationIndex:p,contextmenus:S,execPrev:v,execNext:O,slideThumbnailModelVisible:l,turnSlideToIndex:I,writingBoardToolVisible:i}}});n("2c96");Ep.render=qf,Ep.__scopeId="data-v-048f6280";var Ip=Ep,Sp=Object(h["defineComponent"])({name:"app",components:{Editor:zf,Screen:Ip},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.screening}));return Object(h["onMounted"])((function(){e.commit(g.SET_AVAILABLE_FONTS),e.dispatch(y.INIT_SNAPSHOT_DATABASE)})),{screening:t}}});n("a2af");Sp.render=j;var Cp=Sp;n("793f"),n("41ed"),n("5952"),n("c860"),n("ae3f"),n("8c56"),n("77ed");function xp(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("MenuContent");return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,[Object(h["createVNode"])("div",{class:"mask",onContextmenu:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.removeContextMenu()}),["prevent"])),onMousedown:t[2]||(t[2]=function(t){return e.removeContextMenu()})},null,32),Object(h["createVNode"])("div",{class:"contextmenu",style:{left:e.style.left,top:e.style.top},onContextmenu:t[3]||(t[3]=Object(h["withModifiers"])((function(){}),["prevent"]))},[Object(h["createVNode"])(r,{menus:e.menus,subMenuPosition:e.style.subMenuPosition,handleClickMenuItem:e.handleClickMenuItem},null,8,["menus","subMenuPosition","handleClickMenuItem"])],36)],64)}var Np=Object(h["withScopeId"])("data-v-3cad6828");Object(h["pushScopeId"])("data-v-3cad6828");var Tp={class:"menu-content"},wp={class:"text"},Lp={key:0,class:"sub-text"};Object(h["popScopeId"])();var Vp=Np((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("_self");return Object(h["openBlock"])(),Object(h["createBlock"])("ul",Tp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.menus,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,[t.hide?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])("li",{class:["menu-item",{divider:t.divider,disable:t.disable}],key:t.text||n,onClick:Object(h["withModifiers"])((function(n){return e.handleClickMenuItem(t)}),["stop"])},[t.divider?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["menu-item-content",{"has-sub-menu":t.children}]},[Object(h["createVNode"])("span",wp,Object(h["toDisplayString"])(t.text),1),t.subText&&!t.children?(Object(h["openBlock"])(),Object(h["createBlock"])("span",Lp,Object(h["toDisplayString"])(t.subText),1)):Object(h["createCommentVNode"])("",!0),t.children&&t.children.length?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,class:"sub-menu",style:Object(C["a"])({},e.subMenuPosition,"112.5%"),menus:t.children,handleClickMenuItem:e.handleClickMenuItem},null,8,["style","menus","handleClickMenuItem"])):Object(h["createCommentVNode"])("",!0)],2))],10,["onClick"]))],64)})),256))])})),_p=Object(h["defineComponent"])({name:"menu-content",props:{menus:{type:Array,required:!0},subMenuPosition:{type:String,default:"left"},handleClickMenuItem:{type:Function,required:!0}}});n("e344");_p.render=Vp,_p.__scopeId="data-v-3cad6828";var Bp=_p,Mp=160,Dp=30,Ap=11,Pp=120,Rp=Object(h["defineComponent"])({name:"contextmenu",components:{MenuContent:Bp},props:{axis:{type:Object,required:!0},el:{type:Object,required:!0},menus:{type:Array,required:!0},removeContextMenu:{type:Function,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){var t=e.axis,n=t.x,o=t.y,c=e.menus.filter((function(e){return!e.divider&&!e.hide})).length,a=e.menus.filter((function(e){return e.divider})).length,r=10,l=Mp,i=c*Dp+a*Ap+r,u=Mp+Pp-10,d=document.body.clientWidth,s=document.body.clientHeight,f=d<=n+l?n-l:n,p=s<=o+i?o-i:o,b=d<=f+u?"right":"left";return{left:f+"px",top:p+"px",subMenuPosition:b}})),n=function(t){t.disable||t.children||(t.handler&&t.handler(e.el),e.removeContextMenu())};return{style:t,handleClickMenuItem:n}}});n("1c62");Rp.render=xp;var Fp=Rp,zp="CTX_CONTEXTMENU_HANDLER",Hp=function(e,t,n){t.stopPropagation(),t.preventDefault();var o=n.value(e);if(o){var c=null,a=function t(){c&&(document.body.removeChild(c),c=null),e.classList.remove("contextmenu-active"),document.body.removeEventListener("scroll",t),window.removeEventListener("resize",t)},r={axis:{x:t.x,y:t.y},el:e,menus:o,removeContextMenu:a};c=document.createElement("div");var l=Object(h["createVNode"])(Fp,r,null);Object(h["render"])(l,c),document.body.appendChild(c),e.classList.add("contextmenu-active"),document.body.addEventListener("scroll",a),window.addEventListener("resize",a)}},Up={mounted:function(e,t){e[zp]=function(n){return Hp(e,n,t)},e.addEventListener("contextmenu",e[zp])},unmounted:function(e){e&&e[zp]&&(e.removeEventListener("contextmenu",e[zp]),delete e[zp])}},Gp=Up,qp="CTX_CLICK_OUTSIDE_HANDLER",Wp=function(e,t,n){var o=n.value,c=t.composedPath(),a=c?c.indexOf(e)<0:!e.contains(t.target);a&&o(t)},Xp={mounted:function(e,t){e[qp]=function(n){return Wp(e,n,t)},setTimeout((function(){document.addEventListener("click",e[qp])}),0)},unmounted:function(e){e[qp]&&(document.removeEventListener("click",e[qp]),delete e[qp])}},Yp=Xp,Zp=n("a3ef"),Jp=n("8331"),Kp=n("4040"),$p=n("f745"),Qp=n("5d58"),eb=n("2e2d"),tb=n("6010"),nb=n("1fcb"),ob=n("6b77"),cb=n("8db9"),ab=n("0996"),rb=n("a26d"),lb=n("1646"),ib=n("9c0a"),ub=n("622c"),db=n("e5ce"),sb=n("3f19"),fb=n("2dba"),pb=n("10de"),bb=n("fbe7"),mb=n("460f"),vb=n("cfe0"),Ob=n("84e7"),hb=n("1b42"),jb=n("b8af"),gb=n("f59e"),yb=n("bdf8"),kb=n("bf2c"),Eb=n("5168"),Ib=n("1b1c"),Sb=n("e970"),Cb=n("c53e"),xb=n("5a28"),Nb=n("23fa"),Tb=n("fd52"),wb=n("8377"),Lb=n("246f"),Vb=n("4be2"),_b=n("33a2"),Bb=n("fdbcb"),Mb=n("031f"),Db=n("d26b"),Ab=n("a17d"),Pb=n("0ad3"),Rb=n("3a3e"),Fb=n("500e"),zb=n("eac59"),Hb=n("694b"),Ub=n("e9ec"),Gb=n("ea01"),qb=n("74f3"),Wb=n("4bad"),Xb=n("e7f4"),Yb=n("eb50"),Zb=n("0be2"),Jb=n("a90c"),Kb=n("c90a"),$b=n("d41d6"),Qb=n("2c06"),em=n("a5dc"),tm=n("8678"),nm=n("d7fb"),om=n("ce42"),cm=n("7abc"),am=n("5b20"),rm=n("69de"),lm=n("d0c6"),im=n("dcc2"),um=n("5683"),dm=n("69f5"),sm=n("f1d2"),fm=n("d16b"),pm=n("a5f1"),bm=n("df0d"),mm=n("70f2"),vm=n("b7c8"),Om=n("f99d"),hm=n("40bb"),jm=n("ae33"),gm=n("8c1a"),ym=n("b7b3"),km=n("96be"),Em=n("5a69"),Im=n("f9e5"),Sm=n("bbce"),Cm=n("77ad"),xm=n("46cd"),Nm=n("c4a8"),Tm=n("3ee3"),wm=n("dde4"),Lm=n("cead"),Vm=n("a7ac"),_m=n("45b9"),Bm=n("5a81"),Mm=n("0aba"),Dm=n("fa00d"),Am=n("f3c2"),Pm=n("c8bf"),Rm=n("5294b"),Fm=n("9fbc"),zm={install:function(e){e.component("IconFontSize",Fm["a"]),e.component("IconPicture",Rm["a"]),e.component("IconPentagonOne",Pm["a"]),e.component("IconConnection",Am["a"]),e.component("IconInsertTable",Dm["a"]),e.component("IconSymbol",Mm["a"]),e.component("IconCopy",Bm["a"]),e.component("IconClipboard",_m["a"]),e.component("IconCuttingOne",Vm["a"]),e.component("IconLock",Lm["a"]),e.component("IconUnlock",wm["a"]),e.component("IconFullScreen",Tm["a"]),e.component("IconOffScreen",Nm["a"]),e.component("IconBack",xm["a"]),e.component("IconNext",Cm["a"]),e.component("IconAlignTop",Sm["a"]),e.component("IconAlignLeft",Im["a"]),e.component("IconAlignRight",Em["a"]),e.component("IconAlignBottom",km["a"]),e.component("IconAlignVertically",ym["a"]),e.component("IconAlignHorizontally",gm["a"]),e.component("IconBringToFront",jm["a"]),e.component("IconSentToBack",hm["a"]),e.component("IconBringToFrontOne",Om["a"]),e.component("IconSendToBack",vm["a"]),e.component("IconGroup",mm["a"]),e.component("IconUngroup",bm["a"]),e.component("IconFill",pm["a"]),e.component("IconBackgroundColor",fm["a"]),e.component("IconPlatte",sm["a"]),e.component("IconSplitCells",dm["a"]),e.component("IconMergeCells",um["a"]),e.component("IconTailoring",im["a"]),e.component("IconColorFilter",lm["a"]),e.component("IconFlipVertically",rm["a"]),e.component("IconFlipHorizontally",am["a"]),e.component("IconText",cm["a"]),e.component("IconAddText",om["a"]),e.component("IconAlignTextLeft",nm["a"]),e.component("IconAlignTextRight",tm["a"]),e.component("IconAlignTextCenter",em["a"]),e.component("IconRowHeight",Qb["a"]),e.component("IconFullwidth",$b["a"]),e.component("IconCode",Kb["a"]),e.component("IconTextBold",Jb["a"]),e.component("IconTextItalic",Zb["a"]),e.component("IconTextUnderline",Yb["a"]),e.component("IconStrikethrough",Xb["a"]),e.component("IconQuote",Wb["a"]),e.component("IconList",qb["a"]),e.component("IconOrderedList",Gb["a"]),e.component("IconUpOne",Ub["a"]),e.component("IconDownOne",Hb["a"]),e.component("IconFormat",zb["a"]),e.component("IconUp",Fb["a"]),e.component("IconDown",Rb["a"]),e.component("IconLeft",Pb["a"]),e.component("IconRight",Ab["a"]),e.component("IconLeftC",Db["a"]),e.component("IconRightC",Mb["a"]),e.component("IconPlus",Bb["a"]),e.component("IconMinus",_b["a"]),e.component("IconCheck",Vb["a"]),e.component("IconClose",Lb["a"]),e.component("IconCloseSmall",wb["a"]),e.component("IconChartRing",Tb["a"]),e.component("IconChartLine",Nb["a"]),e.component("IconChartHistogramOne",xb["a"]),e.component("IconChartHistogram",Cb["a"]),e.component("IconChartProportion",Sb["a"]),e.component("IconChartScatter",Ib["a"]),e.component("IconHome",Eb["a"]),e.component("IconPlayOne",kb["a"]),e.component("IconSearch",yb["a"]),e.component("IconDelete",gb["a"]),e.component("IconPpt",jb["a"]),e.component("IconSettingOne",hb["a"]),e.component("IconClear",Ob["a"]),e.component("IconLinkOne",vb["a"]),e.component("IconDrag",mb["a"]),e.component("IconHelpcenter",bb["a"]),e.component("IconEnterTheKeyboard",pb["a"]),e.component("IconFind",fb["a"]),e.component("IconFullSelection",sb["a"]),e.component("IconClearFormat",db["a"]),e.component("IconGridFour",ub["a"]),e.component("IconPageTemplate",ib["a"]),e.component("IconGithub",lb["a"]),e.component("IconMore",rb["a"]),e.component("IconWrite",ab["a"]),e.component("IconAddThree",cb["a"]),e.component("IconNewlybuild",ob["a"]),e.component("IconEffects",nb["a"]),e.component("IconRotate",tb["a"]),e.component("IconEdit",eb["a"]),e.component("IconSeoFolder",Qp["a"]),e.component("IconUndo",$p["a"]),e.component("IconTransform",Kp["a"]),e.component("IconClick",Jp["a"]),e.component("IconTheme",Zp["a"])}},Hm=Object(h["withScopeId"])("data-v-59732924"),Um=Hm((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"file-input",onClick:t[2]||(t[2]=function(t){return e.handleClick()})},[Object(h["renderSlot"])(e.$slots,"default"),Object(h["createVNode"])("input",{class:"input",type:"file",name:"upload",ref:"inputRef",accept:e.accept,onChange:t[1]||(t[1]=function(t){return e.handleChange(t)})},null,40,["accept"])])})),Gm=Object(h["defineComponent"])({name:"file-input",props:{accept:{type:String,default:"image/*"}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=function(){o.value&&(o.value.value="",o.value.click())},a=function(e){var t=e.target.files;t&&n("change",t)};return{handleClick:c,handleChange:a,inputRef:o}}});n("6a17");Gm.render=Um,Gm.__scopeId="data-v-59732924";var qm=Gm,Wm={xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",version:"1.1"};function Xm(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("svg",Wm,[Object(h["renderSlot"])(e.$slots,"default")])}var Ym={name:"svg-wrapper"};Ym.render=Xm;var Zm=Ym,Jm=Object(h["withScopeId"])("data-v-7cae2b90"),Km=Jm((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("button",{class:["checkbox-button",{checked:n.checked}]},[Object(h["renderSlot"])(e.$slots,"default")],2)})),$m={name:"checkbox-button",props:{checked:{type:Boolean,default:!1}}};n("782e");$m.render=Km,$m.__scopeId="data-v-7cae2b90";var Qm=$m,ev=Object(h["withScopeId"])("data-v-7dafd0a9");Object(h["pushScopeId"])("data-v-7dafd0a9");var tv={class:"checkbox-button-group"};Object(h["popScopeId"])();var nv=ev((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",tv,[Object(h["renderSlot"])(e.$slots,"default")])})),ov={name:"checkbox-button-group"};n("69d58");ov.render=nv,ov.__scopeId="data-v-7dafd0a9";var cv=ov,av=Object(h["withScopeId"])("data-v-dc0cf132");Object(h["pushScopeId"])("data-v-dc0cf132");var rv={class:"color-picker"},lv={class:"picker-saturation-wrap"},iv={class:"picker-controls"},uv={class:"picker-color-wrap"},dv={class:"picker-sliders"},sv={class:"picker-hue-wrap"},fv={class:"picker-alpha-wrap"},pv={class:"picker-field"},bv={class:"picker-presets"},mv={class:"picker-gradient-presets"},vv={class:"picker-presets"};Object(h["popScopeId"])();var Ov=av((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Saturation"),l=Object(h["resolveComponent"])("Checkboard"),i=Object(h["resolveComponent"])("Hue"),u=Object(h["resolveComponent"])("Alpha"),d=Object(h["resolveComponent"])("EditableInput");return Object(h["openBlock"])(),Object(h["createBlock"])("div",rv,[Object(h["createVNode"])("div",lv,[Object(h["createVNode"])(r,{value:e.color,hue:e.hue,onColorChange:t[1]||(t[1]=function(t){return e.changeColor(t)})},null,8,["value","hue"])]),Object(h["createVNode"])("div",iv,[Object(h["createVNode"])("div",uv,[Object(h["createVNode"])("div",{class:"picker-current-color",style:{background:e.currentColor}},null,4),Object(h["createVNode"])(l)]),Object(h["createVNode"])("div",dv,[Object(h["createVNode"])("div",sv,[Object(h["createVNode"])(i,{value:e.color,hue:e.hue,onColorChange:t[2]||(t[2]=function(t){return e.changeColor(t)})},null,8,["value","hue"])]),Object(h["createVNode"])("div",fv,[Object(h["createVNode"])(u,{value:e.color,onColorChange:t[3]||(t[3]=function(t){return e.changeColor(t)})},null,8,["value"])])])]),Object(h["createVNode"])("div",pv,[Object(h["createVNode"])(d,{value:e.color,onColorChange:t[4]||(t[4]=function(t){return e.changeColor(t)})},null,8,["value"])]),Object(h["createVNode"])("div",bv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.themeColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-presets-color",key:t,style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))]),Object(h["createVNode"])("div",mv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.presetColors,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-gradient-col",key:n},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(t,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-gradient-color",key:t,style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))])})),128))]),Object(h["createVNode"])("div",vv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.standardColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:t,class:"picker-presets-color",style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))])])})),hv=Object(h["withScopeId"])("data-v-40ed15f5");Object(h["pushScopeId"])("data-v-40ed15f5");var jv={class:"alpha"},gv={class:"alpha-checkboard-wrap"},yv=Object(h["createVNode"])("div",{class:"alpha-picker"},null,-1);Object(h["popScopeId"])();var kv=hv((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Checkboard");return Object(h["openBlock"])(),Object(h["createBlock"])("div",jv,[Object(h["createVNode"])("div",gv,[Object(h["createVNode"])(r)]),Object(h["createVNode"])("div",{class:"alpha-gradient",style:{background:e.gradientColor}},null,4),Object(h["createVNode"])("div",{class:"alpha-container",ref:"alphaRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Object(h["createVNode"])("div",{class:"alpha-pointer",style:{left:100*e.color.a+"%"}},[yv],4)],544)])})),Ev=Object(h["withScopeId"])("data-v-2352ea60"),Iv=Ev((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"checkerboard",style:e.bgStyle},null,4)})),Sv={},Cv=function(e,t,n){var o=document.createElement("canvas");o.width=o.height=2*n;var c=o.getContext("2d");return c?(c.fillStyle=e,c.fillRect(0,0,o.width,o.height),c.fillStyle=t,c.fillRect(0,0,n,n),c.translate(n,n),c.fillRect(0,0,n,n),o.toDataURL()):null},xv=function(e,t,n){var o=e+","+t+","+n;if(Sv[o])return Sv[o];var c=Cv(e,t,n);return Sv[o]=c,c},Nv=Object(h["defineComponent"])({name:"checkboard",props:{size:{type:Number,default:8},white:{type:String,default:"#fff"},grey:{type:String,default:"#e6e6e6"}},setup:function(e){var t=Object(h["computed"])((function(){var t=xv(e.white,e.grey,e.size);return{backgroundImage:"url(".concat(t,")")}}));return{bgStyle:t}}});n("13cd");Nv.render=Iv,Nv.__scopeId="data-v-2352ea60";var Tv=Nv,wv=Object(h["defineComponent"])({name:"alpha",components:{Checkboard:Tv},props:{value:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){return e.value})),c=Object(h["computed"])((function(){var e=[o.value.r,o.value.g,o.value.b].join(",");return"linear-gradient(to right, rgba(".concat(e,", 0) 0%, rgba(").concat(e,", 1) 100%)")})),a=Object(h["ref"])(),r=function(e){if(e.preventDefault(),a.value){var t,c=a.value.clientWidth,r=a.value.getBoundingClientRect().left+window.pageXOffset,l=e.pageX-r;t=l<0?0:l>c?1:Math.round(100*l/c)/100,o.value.a!==t&&n("colorChange",{r:o.value.r,g:o.value.g,b:o.value.b,a:t})}},l=function e(){window.removeEventListener("mousemove",r),window.removeEventListener("mouseup",e)},i=function(e){r(e),window.addEventListener("mousemove",r),window.addEventListener("mouseup",l)};return Object(h["onUnmounted"])(l),{alphaRef:a,gradientColor:c,handleMouseDown:i,color:o}}});n("b295");wv.render=kv,wv.__scopeId="data-v-40ed15f5";var Lv=wv,Vv=Object(h["withScopeId"])("data-v-0cb6d507");Object(h["pushScopeId"])("data-v-0cb6d507");var _v={class:"hue"},Bv=Object(h["createVNode"])("div",{class:"hue-picker"},null,-1);Object(h["popScopeId"])();var Mv=Vv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",_v,[Object(h["createVNode"])("div",{class:"hue-container",ref:"hueRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Object(h["createVNode"])("div",{class:"hue-pointer",style:{left:e.pointerLeft}},[Bv],4)],544)])})),Dv=Object(h["defineComponent"])({name:"hue",props:{value:{type:Object,required:!0},hue:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(0),c=Object(h["ref"])(""),a=Object(h["computed"])((function(){var t=oc()(e.value).toHsl();return 0===t.s&&(t.h=e.hue),t})),r=Object(h["computed"])((function(){return 0===a.value.h&&"right"===c.value?"100%":100*a.value.h/360+"%"}));Object(h["watch"])((function(){return e.value}),(function(){var t=oc()(e.value).toHsl(),n=0===t.s?e.hue:t.h;0!==n&&n-o.value>0&&(c.value="right"),0!==n&&n-o.value<0&&(c.value="left"),o.value=n}));var l=Object(h["ref"])(),i=function(e){if(e.preventDefault(),l.value){var t,o,c=l.value.clientWidth,r=l.value.getBoundingClientRect().left+window.pageXOffset,i=e.pageX-r;i<0?t=0:i>c?t=360:(o=100*i/c,t=360*o/100),a.value.h!==t&&n("colorChange",{h:t,l:a.value.l,s:a.value.s,a:a.value.a})}},u=function e(){window.removeEventListener("mousemove",i),window.removeEventListener("mouseup",e)},d=function(e){i(e),window.addEventListener("mousemove",i),window.addEventListener("mouseup",u)};return Object(h["onUnmounted"])(u),{hueRef:l,handleMouseDown:d,pointerLeft:r}}});n("dc91");Dv.render=Mv,Dv.__scopeId="data-v-0cb6d507";var Av=Dv,Pv=Object(h["withScopeId"])("data-v-792755a0");Object(h["pushScopeId"])("data-v-792755a0");var Rv=Object(h["createVNode"])("div",{class:"saturation-white"},null,-1),Fv=Object(h["createVNode"])("div",{class:"saturation-black"},null,-1),zv=Object(h["createVNode"])("div",{class:"saturation-circle"},null,-1);Object(h["popScopeId"])();var Hv=Pv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"saturation",ref:"saturationRef",style:{background:e.bgColor},onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Rv,Fv,Object(h["createVNode"])("div",{class:"saturation-pointer",style:{top:e.pointerTop,left:e.pointerLeft}},[zv],4)],36)})),Uv=n("f678"),Gv=n.n(Uv),qv=Object(h["defineComponent"])({name:"saturation",props:{value:{type:Object,required:!0},hue:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){var t=oc()(e.value).toHsv();return 0===t.s&&(t.h=e.hue),t})),c=Object(h["computed"])((function(){return"hsl(".concat(o.value.h,", 100%, 50%)")})),a=Object(h["computed"])((function(){return-100*o.value.v+1+100+"%"})),r=Object(h["computed"])((function(){return 100*o.value.s+"%"})),l=je()((function(e){n("colorChange",e)}),20,{leading:!0,trailing:!1}),i=Object(h["ref"])(),u=function(e){if(e.preventDefault(),i.value){var t=i.value.clientWidth,n=i.value.clientHeight,c=i.value.getBoundingClientRect().left+window.pageXOffset,a=i.value.getBoundingClientRect().top+window.pageYOffset,r=Gv()(e.pageX-c,0,t),u=Gv()(e.pageY-a,0,n),d=r/t,s=Gv()(-u/n+1,0,1);l({h:o.value.h,s:d,v:s,a:o.value.a})}},d=function e(){window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",e)},s=function(e){u(e),window.addEventListener("mousemove",u),window.addEventListener("mouseup",d)};return Object(h["onUnmounted"])(d),{saturationRef:i,bgColor:c,handleMouseDown:s,pointerTop:a,pointerLeft:r}}});n("97cd");qv.render=Hv,qv.__scopeId="data-v-792755a0";var Wv=qv,Xv=Object(h["withScopeId"])("data-v-67f94aae");Object(h["pushScopeId"])("data-v-67f94aae");var Yv={class:"editable-input"};Object(h["popScopeId"])();var Zv=Xv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",Yv,[Object(h["createVNode"])("input",{class:"input-content",value:e.val,onInput:t[1]||(t[1]=function(t){return e.handleInput(t)})},null,40,["value"])])})),Jv=Object(h["defineComponent"])({name:"editable-input",props:{value:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){var t="";return t=e.value.a<1?oc()(e.value).toHex8String().toUpperCase():oc()(e.value).toHexString().toUpperCase(),t.replace("#","")})),c=function(e){var t=e.target.value;t.length>=6&&n("colorChange",oc()(t).toRgb())};return{val:o,handleInput:c}}});n("a73d");Jv.render=Zv,Jv.__scopeId="data-v-67f94aae";var Kv=Jv,$v=[["#7f7f7f","#f2f2f2"],["#0d0d0d","#808080"],["#1c1a10","#ddd8c3"],["#0e243d","#c6d9f0"],["#233f5e","#dae5f0"],["#632623","#f2dbdb"],["#4d602c","#eaf1de"],["#3f3150","#e6e0ec"],["#1e5867","#d9eef3"],["#99490f","#fee9da"]],Qv=function(e,t,n){for(var o=oc()(e).toRgb(),c=oc()(t).toRgb(),a=(c.r-o.r)/n,r=(c.g-o.g)/n,l=(c.b-o.b)/n,i=[],u=0;u\n \n \n\n\n\n\n","export const enum MutationTypes {\r\n\r\n // editor\r\n SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList',\r\n SET_HANDLE_ELEMENT_ID = 'setHandleElementId',\r\n SET_CANVAS_PERCENTAGE = 'setCanvasPercentage',\r\n SET_CANVAS_SCALE = 'setCanvasScale',\r\n SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus',\r\n SET_EDITORAREA_FOCUS = 'setEditorAreaFocus',\r\n SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState',\r\n SET_GRID_LINES_STATE = 'setGridLinesState',\r\n SET_CREATING_ELEMENT = 'setCreatingElement',\r\n SET_AVAILABLE_FONTS = 'setAvailableFonts',\r\n SET_TOOLBAR_STATE = 'setToolbarState',\r\n SET_CLIPING_IMAGE_ELEMENT_ID = 'setClipingImageElementId',\r\n\r\n // slides\r\n SET_THEME = 'setTheme',\r\n SET_SLIDES = 'setSlides',\r\n ADD_SLIDE = 'addSlide',\r\n UPDATE_SLIDE = 'updateSlide',\r\n DELETE_SLIDE = 'deleteSlide',\r\n UPDATE_SLIDE_INDEX = 'updateSlideIndex',\r\n ADD_ELEMENT = 'addElement',\r\n UPDATE_ELEMENT = 'updateElement',\r\n REMOVE_ELEMENT_PROPS = 'removeElementProps',\r\n\r\n // snapshot\r\n SET_SNAPSHOT_CURSOR = 'setSnapshotCursor',\r\n SET_SNAPSHOT_LENGTH = 'setSnapshotLength',\r\n\r\n // keyboard\r\n SET_CTRL_KEY_STATE = 'setCtrlKeyState',\r\n SET_SHIFT_KEY_STATE = 'setShiftKeyState',\r\n\r\n // screen\r\n SET_SCREENING = 'setScreening',\r\n}\r\n\r\nexport const enum ActionTypes {\r\n INIT_SNAPSHOT_DATABASE = 'initSnapshotDatabase',\r\n ADD_SNAPSHOT = 'addSnapshot',\r\n UN_DO = 'undo',\r\n RE_DO = 'redo',\r\n}","import { Slide } from '@/types/slides'\n\nexport const slides: Slide[] = [\n {\n id: 'xsxa123',\n elements: [\n {\n id: 'sdasaxs',\n type: 'chart',\n left: 680,\n top: 20,\n width: 300,\n height: 300,\n chartType: 'line',\n themeColor: '#d70206',\n data: {\n labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],\n series: [\n [5, 2, 4, 2, 10],\n ],\n },\n },\n {\n id: '1213asa',\n type: 'table',\n left: 20,\n top: 20,\n width: 400,\n height: 108,\n colWidths: [0.25, 0.25, 0.25, 0.25],\n outline: {\n width: 1,\n style: 'solid',\n color: '#999',\n },\n data: [\n [\n { id: '1', colspan: 1, rowspan: 1, text: '1' },\n { id: '2', colspan: 1, rowspan: 1, text: '2' },\n { id: '3', colspan: 1, rowspan: 1, text: '3' },\n { id: '4', colspan: 1, rowspan: 1, text: '4' },\n ],\n [\n { id: '6', colspan: 1, rowspan: 1, text: '6' },\n { id: '7', colspan: 1, rowspan: 1, text: '7' },\n { id: '8', colspan: 1, rowspan: 1, text: '8' },\n { id: '9', colspan: 1, rowspan: 1, text: '9' },\n ],\n [\n { id: '11', colspan: 1, rowspan: 1, text: '11' },\n { id: '12', colspan: 1, rowspan: 1, text: '12' },\n { id: '13', colspan: 1, rowspan: 1, text: '13' },\n { id: '14', colspan: 1, rowspan: 1, text: '14' },\n ],\n ],\n },\n ],\n },\n {\n id: 'xxx1',\n background: {\n type: 'solid',\n color: '#fff',\n },\n elements: [\n {\n id: 'xxx1',\n type: 'text',\n left: 190,\n top: 50,\n width: 320,\n height: 104,\n rotate: 0,\n shadow: {\n h: 1,\n v: 1,\n blur: 3,\n color: 'rgba(10, 10, 10, .5)'\n },\n opacity: 1,\n lock: false,\n content: '

一段测试文字,字号固定为28px

',\n },\n {\n id: 'xxx3',\n type: 'image',\n left: 80,\n top: 250,\n width: 180,\n height: 180,\n rotate: 0,\n outline: {\n width: 4,\n style: 'solid',\n color: '#333'\n },\n clip: {\n range: [[30, 0], [100, 70]],\n shape: 'ellipse'\n },\n fixedRatio: false,\n lock: false,\n src: 'https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/1573622467064v2-7aa3ce420052983d91c6d01b47a7441d_hd.jpg',\n },\n {\n id: 'xxx2',\n type: 'image',\n left: 750,\n top: 320,\n width: 150,\n height: 150,\n rotate: 0,\n fixedRatio: true,\n lock: false,\n src: 'https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/62d9adb3-e7a6-4dc4-a352-095cffb49f08/b1be1a2f-f893-47d3-a8a3-eac7d04d395f/1596159381259v2-b2c69096d25ae16bf6ca09e30add3e65_hd.jpg',\n },\n ],\n animations: [\n {\n elId: 'xxx1',\n type: 'rotateIn',\n duration: 1000,\n },\n {\n elId: 'xxx2',\n type: 'zoomIn',\n duration: 1000,\n },\n ],\n },\n {\n id: 'sajd172',\n elements: [\n {\n id: 'yyx1',\n type: 'text',\n left: 590,\n top: 90,\n width: 220,\n height: 188,\n rotate: 0,\n opacity: 1,\n lock: false,\n content: '
😀 😐 😶 😜 🔔 ⭐ ⚡ 🔥 👍 💡 🔰 🎀 🎁 🥇 🏅 🏆 🎈 🎉 💎 🚧 ⛔ 📢 ⌛ ⏰ 🕒 🧩 🎵 📎 🔒 🔑 ⛳ 📌 📍 💬 📅 📈 📋 📜 📁 📱 💻 💾 🌏 🚚 🚡 🚢💧 🌐 🧭 💰 💳 🛒
',\n },\n {\n id: 'xsfdas',\n type: 'line',\n width: 2,\n left: 100,\n top: 400,\n end: [0, 0],\n start: [300, 120],\n style: 'solid',\n color: '#888',\n points: ['', 'arrow'],\n },\n {\n id: 'xxx7',\n type: 'shape',\n left: 130,\n top: 50,\n width: 150,\n height: 150,\n rotate: 0,\n fill: '#eebc29',\n opacity: 0.9,\n fixedRatio: false,\n lock: false,\n viewBox: 1024,\n path: 'M721.35111111 475.59111111H302.64888889c-5.00622222 0-9.10222222 4.096-9.10222222 9.10222222v54.61333334c0 5.00622222 4.096 9.10222222 9.10222222 9.10222222h418.70222222c5.00622222 0 9.10222222-4.096 9.10222222-9.10222222v-54.61333334c0-5.00622222-4.096-9.10222222-9.10222222-9.10222222z M512 2.27555555C230.51377778 2.27555555 2.27555555 230.51377778 2.27555555 512s228.23822222 509.72444445 509.72444445 509.72444445 509.72444445-228.23822222 509.72444445-509.72444445S793.48622222 2.27555555 512 2.27555555z m0 932.97777778c-233.69955555 0-423.25333333-189.55377778-423.25333333-423.25333333s189.55377778-423.25333333 423.25333333-423.25333333 423.25333333 189.55377778 423.25333333 423.25333333-189.55377778 423.25333333-423.25333333 423.25333333z',\n }\n ],\n animations: [\n {\n elId: 'yyx1',\n type: 'flipInX',\n duration: 1000,\n },\n ],\n },\n]","import { Slide, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { ToolbarState } from '@/types/toolbar'\r\nimport { slides } from '@/mocks/index'\r\nimport { SYS_FONTS } from '@/configs/font'\r\n\r\nexport interface State {\r\n activeElementIdList: string[];\r\n handleElementId: string;\r\n canvasPercentage: number;\r\n canvasScale: number;\r\n thumbnailsFocus: boolean;\r\n editorAreaFocus: boolean;\r\n disableHotkeys: boolean;\r\n showGridLines: boolean;\r\n creatingElement: CreatingElement | null;\r\n availableFonts: typeof SYS_FONTS;\r\n toolbarState: ToolbarState;\r\n theme: SlideTheme;\r\n slides: Slide[];\r\n slideIndex: number;\r\n snapshotCursor: number;\r\n snapshotLength: number;\r\n ctrlKeyState: boolean;\r\n shiftKeyState: boolean;\r\n screening: boolean;\r\n clipingImageElementId: string;\r\n}\r\n\r\nexport const state: State = {\r\n activeElementIdList: [],\r\n handleElementId: '',\r\n canvasPercentage: 90,\r\n canvasScale: 1,\r\n thumbnailsFocus: false,\r\n editorAreaFocus: false,\r\n disableHotkeys: false,\r\n showGridLines: false,\r\n creatingElement: null,\r\n availableFonts: [],\r\n toolbarState: 'slideStyle',\r\n theme: {\r\n themeColor: '#d14424',\r\n fontColor: '#333',\r\n fontName: '微软雅黑',\r\n backgroundColor: '#fff',\r\n },\r\n slides: slides,\r\n slideIndex: 0,\r\n snapshotCursor: -1,\r\n snapshotLength: 0,\r\n ctrlKeyState: false,\r\n shiftKeyState: false,\r\n screening: false,\r\n clipingImageElementId: '',\r\n}","import { GetterTree } from 'vuex'\r\nimport { State } from './state'\r\n\r\nexport const getters: GetterTree = {\r\n currentSlide(state) {\r\n return state.slides[state.slideIndex] || null\r\n },\r\n\r\n currentSlideAnimations(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide) return null\r\n const animations = currentSlide.animations\r\n if(!animations) return null\r\n\r\n const els = currentSlide.elements\r\n const elIds = els.map(el => el.id)\r\n return animations.filter(animation => elIds.includes(animation.elId))\r\n },\r\n\r\n activeElementList(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide || !currentSlide.elements) return []\r\n return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))\r\n },\r\n\r\n handleElement(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide || !currentSlide.elements) return null\r\n return currentSlide.elements.find(element => state.handleElementId === element.id) || null\r\n },\r\n\r\n canUndo(state) {\r\n return state.snapshotCursor > 0\r\n },\r\n\r\n canRedo(state) {\r\n return state.snapshotCursor < state.snapshotLength - 1\r\n },\r\n\r\n ctrlOrShiftKeyActive(state) {\r\n return state.ctrlKeyState || state.shiftKeyState\r\n },\r\n}","import Dexie from 'dexie'\nimport { Slide } from '@/types/slides'\n\nexport interface Snapshot {\n index: number;\n slides: Slide[];\n}\n\nclass SnapshotDatabase extends Dexie {\n public snapshots: Dexie.Table\n\n public constructor() {\n super('SnapshotDatabase')\n this.version(1).stores({\n snapshots: '++id'\n })\n this.snapshots = this.table('snapshots')\n }\n}\n\nexport default new SnapshotDatabase()","import { ActionTree } from 'vuex'\nimport { IndexableTypeArray } from 'dexie'\nimport { State } from './state'\nimport { ActionTypes, MutationTypes } from './constants'\nimport db, { Snapshot } from '@/utils/database'\n\nexport const actions: ActionTree = {\n async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit, state }) {\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const lastSnapshot = snapshots.slice(-1)[0]\n\n if(lastSnapshot) {\n db.snapshots.clear()\n }\n\n const newFirstSnapshot = {\n index: state.slideIndex,\n slides: state.slides,\n }\n await db.snapshots.add(newFirstSnapshot)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, 0)\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, 1)\n },\n\n async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {\n const allKeys = await db.snapshots.orderBy('id').keys()\n\n let needDeleteKeys: IndexableTypeArray = []\n\n if(state.snapshotCursor >= 0 && state.snapshotCursor < allKeys.length - 1) {\n needDeleteKeys = allKeys.slice(state.snapshotCursor + 1)\n }\n\n const snapshot = {\n index: state.slideIndex,\n slides: state.slides,\n }\n await db.snapshots.add(snapshot)\n\n let snapshotLength = allKeys.length - needDeleteKeys.length + 1\n\n if(snapshotLength > 20) {\n needDeleteKeys.push(allKeys[0])\n snapshotLength--\n }\n if(snapshotLength >= 2) {\n db.snapshots.update(allKeys[snapshotLength - 2] as number, { index: state.slideIndex })\n }\n\n await db.snapshots.bulkDelete(needDeleteKeys)\n\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotLength - 1)\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, snapshotLength)\n },\n\n async [ActionTypes.UN_DO]({ state, commit }) {\n if(state.snapshotCursor <= 0) return\n\n const snapshotCursor = state.snapshotCursor - 1\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const snapshot = snapshots[snapshotCursor]\n const { index, slides } = snapshot\n\n commit(MutationTypes.SET_SLIDES, slides)\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n },\n\n async [ActionTypes.RE_DO]({ state, commit }) {\n if(state.snapshotCursor >= state.snapshotLength - 1) return\n\n const snapshotCursor = state.snapshotCursor + 1\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const snapshot = snapshots[snapshotCursor]\n const { index, slides } = snapshot\n\n commit(MutationTypes.SET_SLIDES, slides)\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n },\n}","export const SYS_FONTS = [\n { zh: '微软雅黑', en: 'Microsoft Yahei' },\n { zh: '宋体', en: 'SimSun' },\n { zh: '黑体', en: 'SimHei' },\n { zh: '楷体', en: 'KaiTi' },\n { zh: '新宋体', en: 'NSimSun' },\n { zh: '仿宋', en: 'FangSong' },\n { zh: '苹方', en: 'PingFang SC' },\n { zh: '华文黑体', en: 'STHeiti' },\n { zh: '华文楷体', en: 'STKaiti' },\n { zh: '华文宋体', en: 'STSong' },\n { zh: '华文仿宋', en: 'STFangSong' },\n { zh: '华文中宋', en: 'STZhongSong' },\n { zh: '华文琥珀', en: 'STHupo' },\n { zh: '华文新魏', en: 'STXinwei' },\n { zh: '华文隶书', en: 'STLiti' },\n { zh: '华文行楷', en: 'STXingkai' },\n { zh: '冬青黑体简', en: 'Hiragino Sans GB' },\n { zh: '兰亭黑-简', en: 'Lantinghei SC' },\n { zh: '偏偏体-简', en: 'Hanzipen SC' },\n { zh: '手札体-简', en: 'Hannotate SC' },\n { zh: '宋体-简', en: 'Songti SC' },\n { zh: '娃娃体-简', en: 'Wawati SC' },\n { zh: '行楷-简', en: 'Xingkai SC' },\n { zh: '圆体-简', en: 'Yuanti SC' },\n { zh: '华文细黑', en: 'STXihei' },\n { zh: '幼圆', en: 'YouYuan' },\n { zh: '隶书', en: 'LiSu' },\n { zh: 'Arial', en: 'Arial' },\n]\n\nexport const WEB_FONTS = [\n { name: '仓耳小丸子' },\n { name: '优设标题黑' },\n { name: '峰广明锐体' },\n { name: '摄图摩登小方体' },\n { name: '站酷快乐体' },\n { name: '站酷酷黑体' },\n { name: '素材集市康康体' },\n { name: '联盟起艺卢帅正锐黑体' },\n { name: '谦度手写楷体' },\n { name: '途牛类圆体' },\n { name: '锐字真言体' },\n { name: '问藏书房' },\n]","// 判断用户的操作系统是否安装了某字体\nexport const isSupportFontFamily = (fontFamily: string) => {\n if(typeof fontFamily !== 'string') return false\n const arial = 'Arial'\n if(fontFamily.toLowerCase() === arial.toLowerCase()) return true\n const a = 'a'\n const size = 100\n const width = 100\n const height = 100\n\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n\n if(!ctx) return false\n\n canvas.width = width\n canvas.height = height\n ctx.textAlign = 'center'\n ctx.fillStyle = 'black'\n ctx.textBaseline = 'middle'\n\n const getDotArray = (_fontFamily: string) => {\n ctx.clearRect(0, 0, width, height)\n ctx.font = `${size}px ${_fontFamily}, ${arial}`\n ctx.fillText(a, width / 2, height / 2)\n const imageData = ctx.getImageData(0, 0, width, height).data\n return [].slice.call(imageData).filter(item => item !== 0)\n }\n\n return getDotArray(arial).join('') !== getDotArray(fontFamily).join('')\n}","import { MutationTree } from 'vuex'\r\nimport omit from 'lodash/omit'\r\nimport { MutationTypes } from './constants'\r\nimport { State } from './state'\r\nimport { Slide, PPTElement, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { SYS_FONTS } from '@/configs/font'\r\nimport { isSupportFontFamily } from '@/utils/fontFamily'\r\n\r\ninterface RemoveElementPropData {\r\n id: string;\r\n propName: string | string[];\r\n}\r\n\r\ninterface UpdateElementData {\r\n id: string | string[];\r\n props: Partial;\r\n}\r\n\r\nexport const mutations: MutationTree = {\r\n\r\n // editor\r\n\r\n [MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST](state, activeElementIdList: string[]) {\r\n if(activeElementIdList.length === 1) state.handleElementId = activeElementIdList[0]\r\n else state.handleElementId = ''\r\n \r\n state.activeElementIdList = activeElementIdList\r\n },\r\n \r\n [MutationTypes.SET_HANDLE_ELEMENT_ID](state, handleElementId: string) {\r\n state.handleElementId = handleElementId\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_PERCENTAGE](state, percentage: number) {\r\n state.canvasPercentage = percentage\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_SCALE](state, scale: number) {\r\n state.canvasScale = scale\r\n },\r\n\r\n [MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) {\r\n state.thumbnailsFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_EDITORAREA_FOCUS](state, isFocus: boolean) {\r\n state.editorAreaFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_DISABLE_HOTKEYS_STATE](state, disable: boolean) {\r\n state.disableHotkeys = disable\r\n },\r\n\r\n [MutationTypes.SET_GRID_LINES_STATE](state, show: boolean) {\r\n state.showGridLines = show\r\n },\r\n\r\n [MutationTypes.SET_CREATING_ELEMENT](state, element: CreatingElement | null) {\r\n state.creatingElement = element\r\n },\r\n\r\n [MutationTypes.SET_AVAILABLE_FONTS](state) {\r\n state.availableFonts = SYS_FONTS.filter(font => isSupportFontFamily(font.en))\r\n },\r\n\r\n [MutationTypes.SET_TOOLBAR_STATE](state, type) {\r\n state.toolbarState = type\r\n },\r\n\r\n [MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID](state, elId) {\r\n state.clipingImageElementId = elId\r\n },\r\n\r\n // slides\r\n\r\n [MutationTypes.SET_THEME](state, themeProps: Partial) {\r\n state.theme = { ...state.theme, ...themeProps }\r\n },\r\n\r\n [MutationTypes.SET_SLIDES](state, slides: Slide[]) {\r\n state.slides = slides\r\n },\r\n\r\n [MutationTypes.ADD_SLIDE](state, slide: Slide) {\r\n const addIndex = state.slideIndex + 1\r\n state.slides.splice(addIndex, 0, slide)\r\n state.slideIndex = addIndex\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE](state, props: Partial) {\r\n const slideIndex = state.slideIndex\r\n state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }\r\n },\r\n\r\n [MutationTypes.DELETE_SLIDE](state, slideId: string) {\r\n const deleteIndex = state.slides.findIndex(item => item.id === slideId)\r\n\r\n if(deleteIndex === state.slides.length - 1) {\r\n state.slideIndex = deleteIndex - 1\r\n }\r\n state.slides.splice(deleteIndex, 1)\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE_INDEX](state, index: number) {\r\n state.slideIndex = index\r\n },\r\n\r\n [MutationTypes.ADD_ELEMENT](state, element: PPTElement | PPTElement[]) {\r\n const elements = Array.isArray(element) ? element : [element]\r\n const currentSlideEls = state.slides[state.slideIndex].elements\r\n const newEls = [...currentSlideEls, ...elements]\r\n state.slides[state.slideIndex].elements = newEls\r\n },\r\n\r\n [MutationTypes.UPDATE_ELEMENT](state, data: UpdateElementData) {\r\n const { id, props } = data\r\n const elIdList = typeof id === 'string' ? [id] : id\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return elIdList.includes(el.id) ? { ...el, ...props } : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n [MutationTypes.REMOVE_ELEMENT_PROPS](state, data: RemoveElementPropData) {\r\n const { id, propName } = data\r\n const propsNames = typeof propName === 'string' ? [propName] : propName\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return el.id === id ? omit(el, propsNames) : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n // snapshot\r\n\r\n [MutationTypes.SET_SNAPSHOT_CURSOR](state, cursor: number) {\r\n state.snapshotCursor = cursor\r\n },\r\n\r\n [MutationTypes.SET_SNAPSHOT_LENGTH](state, length: number) {\r\n state.snapshotLength = length\r\n },\r\n\r\n // keyboard\r\n\r\n [MutationTypes.SET_CTRL_KEY_STATE](state, isActive: boolean) {\r\n state.ctrlKeyState = isActive\r\n },\r\n [MutationTypes.SET_SHIFT_KEY_STATE](state, isActive: boolean) {\r\n state.shiftKeyState = isActive\r\n },\r\n\r\n // screen\r\n\r\n [MutationTypes.SET_SCREENING](state, screening) {\r\n state.screening = screening\r\n },\r\n}","import { InjectionKey } from 'vue'\nimport { createStore, Store, useStore as baseUseStore } from 'vuex'\nimport { state, State } from './state'\nimport { getters } from './getters'\nimport { actions } from './actions'\nimport { mutations } from './mutations'\nimport { MutationTypes, ActionTypes } from './constants'\n\nexport { MutationTypes, ActionTypes }\n\nexport const key: InjectionKey> = Symbol()\n\nexport const store = createStore({\n state,\n getters,\n mutations,\n actions,\n})\n\nexport const useStore = () => baseUseStore(key)","\n\n\n\n","export const enum KEYS {\n C = 'C',\n X = 'X',\n Z = 'Z',\n Y = 'Y',\n A = 'A',\n G = 'G',\n L = 'L',\n F = 'F',\n D = 'D',\n MINUS = '-',\n EQUAL = '=',\n DIGIT_0 = '0',\n DELETE = 'DELETE',\n UP = 'ARROWUP',\n DOWN = 'ARROWDOWN',\n LEFT = 'ARROWLEFT',\n RIGHT = 'ARROWRIGHT',\n ENTER = 'ENTER',\n SPACE = ' ',\n TAB = 'TAB',\n}","import padStart from 'lodash/padStart'\n\n// 生成随机码\nexport const createRandomCode = (len = 6) => {\n const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`\n const maxLen = charset.length\n let ret = ''\n for(let i = 0; i < len; i++) {\n const randomIndex = Math.floor(Math.random() * maxLen)\n ret += charset[randomIndex]\n }\n return ret\n}\n\n// 数字补足位数,例如将6补足3位 -> 003\nexport const fillDigit = (digit: number, len: number) => {\n return padStart('' + digit, len, '0')\n}","import Clipboard from 'clipboard'\n\n// 复制文本到剪贴板\nexport const copyText = (text: string) => {\n return new Promise((resolve, reject) => {\n const fakeElement = document.createElement('button')\n const clipboard = new Clipboard(fakeElement, {\n text: () => text,\n action: () => 'copy',\n container: document.body,\n })\n clipboard.on('success', e => {\n clipboard.destroy()\n resolve(e)\n })\n clipboard.on('error', e => {\n clipboard.destroy()\n reject(e)\n })\n document.body.appendChild(fakeElement)\n fakeElement.click()\n document.body.removeChild(fakeElement)\n })\n}\n\n// 读取剪贴板\nexport const readClipboard = (): Promise => {\n return new Promise((resolve, reject) => {\n if(navigator.clipboard) {\n navigator.clipboard.readText().then(text => {\n if(!text) reject('剪贴板为空或者不包含文本')\n return resolve(text)\n })\n }\n else reject('浏览器不支持或禁止访问剪贴板')\n })\n}","import CryptoJS from 'crypto-js'\n\nconst CRYPTO_KEY = 'pptist'\n\n// 加密函数\nexport const encrypt = (msg: string) => {\n return CryptoJS.AES.encrypt(msg, CRYPTO_KEY).toString()\n}\n\n// 解密函数\nexport const decrypt = (ciphertext: string) => {\n const bytes = CryptoJS.AES.decrypt(ciphertext, CRYPTO_KEY)\n return bytes.toString(CryptoJS.enc.Utf8)\n}","import debounce from 'lodash/debounce'\nimport throttle from 'lodash/throttle'\nimport { ActionTypes, useStore } from '@/store'\n\nexport default () => {\n const store = useStore()\n\n const addHistorySnapshot = debounce(function() {\n store.dispatch(ActionTypes.ADD_SNAPSHOT)\n }, 300, { trailing: true })\n\n const redo = throttle(function() {\n store.dispatch(ActionTypes.RE_DO)\n }, 100, { leading: true, trailing: false })\n\n const undo = throttle(function() {\n store.dispatch(ActionTypes.UN_DO)\n }, 100, { leading: true, trailing: false })\n\n return {\n addHistorySnapshot,\n redo,\n undo,\n }\n}","interface ImageSize {\n width: number;\n height: number;\n}\n\n// 获取图片的原始宽高\nexport const getImageSize = (src: string): Promise => {\n return new Promise(resolve => {\n const img = document.createElement('img')\n img.src = src\n img.style.opacity = '0'\n document.body.appendChild(img)\n\n img.onload = () => {\n const imgWidth = img.clientWidth\n const imgHeight = img.clientHeight\n \n img.onload = null\n img.onerror = null\n\n document.body.removeChild(img)\n\n resolve({ width: imgWidth, height: imgHeight })\n }\n\n img.onerror = () => {\n img.onload = null\n img.onerror = null\n }\n })\n}\n\n// 获取图片文件的dataURL\nexport const getImageDataURL = (file: File): Promise => {\n return new Promise(resolve => {\n const reader = new FileReader()\n reader.addEventListener('load', () => {\n resolve(reader.result as string)\n })\n reader.readAsDataURL(file)\n })\n}","export const VIEWPORT_SIZE = 1000\r\nexport const VIEWPORT_ASPECT_RATIO = 0.5625","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { createRandomCode } from '@/utils/common'\nimport { getImageSize } from '@/utils/image'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { ChartType, PPTElement, TableCell } from '@/types/slides'\nimport { ShapePoolItem } from '@/configs/shapes'\nimport { LinePoolItem } from '@/configs/lines'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\ninterface CommonElementPosition {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\ninterface LineElementPosition {\n top: number;\n left: number;\n start: [number, number];\n end: [number, number];\n}\n\nexport default () => {\n const store = useStore()\n const themeColor = computed(() => store.state.theme.themeColor)\n const fontColor = computed(() => store.state.theme.fontColor)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const createElement = (element: PPTElement) => {\n store.commit(MutationTypes.ADD_ELEMENT, element)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.id])\n addHistorySnapshot()\n }\n\n const createImageElement = (src: string) => {\n getImageSize(src).then(({ width, height }) => {\n const scale = height / width\n \n if(scale < VIEWPORT_ASPECT_RATIO && width > VIEWPORT_SIZE) {\n width = VIEWPORT_SIZE\n height = width * scale\n }\n else if(height > VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO) {\n height = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n width = height / scale\n }\n\n createElement({\n type: 'image',\n id: createRandomCode(),\n src,\n width,\n height,\n left: (VIEWPORT_SIZE - width) / 2,\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\n fixedRatio: true,\n })\n })\n }\n \n const createChartElement = (chartType: ChartType) => {\n createElement({\n type: 'chart',\n id: createRandomCode(),\n chartType,\n left: 300,\n top: 81.25,\n width: 400,\n height: 400,\n themeColor: themeColor.value,\n gridColor: fontColor.value,\n data: {\n labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],\n series: [\n [12, 19, 5, 2, 18],\n ],\n },\n })\n }\n \n const createTableElement = (row: number, col: number) => {\n const rowCells: TableCell[] = new Array(col).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n const data: TableCell[][] = new Array(row).fill(rowCells)\n\n const DEFAULT_CELL_WIDTH = 100\n const DEFAULT_CELL_HEIGHT = 36\n\n const colWidths: number[] = new Array(col).fill(1 / col)\n\n const width = col * DEFAULT_CELL_WIDTH\n const height = row * DEFAULT_CELL_HEIGHT\n\n createElement({\n type: 'table',\n id: createRandomCode(),\n width,\n height,\n colWidths,\n data,\n left: (VIEWPORT_SIZE - width) / 2,\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\n outline: {\n width: 2,\n style: 'solid',\n color: '#eeece1',\n },\n theme: {\n color: themeColor.value,\n rowHeader: true,\n rowFooter: false,\n colHeader: false,\n colFooter: false,\n },\n })\n }\n \n const createTextElement = (position: CommonElementPosition, content = '请输入内容') => {\n const { left, top, width, height } = position\n createElement({\n type: 'text',\n id: createRandomCode(),\n left, \n top, \n width, \n height,\n content,\n })\n }\n \n const createShapeElement = (position: CommonElementPosition, data: ShapePoolItem) => {\n const { left, top, width, height } = position\n createElement({\n type: 'shape',\n id: createRandomCode(),\n left, \n top, \n width, \n height,\n viewBox: data.viewBox,\n path: data.path,\n fill: themeColor.value,\n fixedRatio: false,\n })\n }\n \n const createLineElement = (position: LineElementPosition, data: LinePoolItem) => {\n const { left, top, start, end } = position\n createElement({\n type: 'line',\n id: createRandomCode(),\n left, \n top, \n start,\n end,\n points: data.points,\n color: themeColor.value,\n style: 'solid',\n width: 2,\n })\n }\n\n return {\n createImageElement,\n createChartElement,\n createTableElement,\n createTextElement,\n createShapeElement,\n createLineElement,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { decrypt } from '@/utils/crypto'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCreateElement from '@/hooks/useCreateElement'\n\ninterface PasteTextClipboardDataOptions {\n onlySlide?: boolean;\n onlyElements?: boolean;\n}\n\nexport default () => {\n const store = useStore()\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n const { createTextElement } = useCreateElement()\n\n const pasteElement = (elements: PPTElement[]) => {\n const groupIdMap = {}\n const elIdMap = {}\n for(const element of elements) {\n const groupId = element.groupId\n if(groupId && !groupIdMap[groupId]) {\n groupIdMap[groupId] = createRandomCode()\n }\n elIdMap[element.id] = createRandomCode()\n }\n const currentSlideElementIdList = currentSlide.value.elements.map(el => el.id)\n \n for(const element of elements) {\n const inCurrentSlide = currentSlideElementIdList.includes(element.id)\n \n element.id = elIdMap[element.id]\n\n if(inCurrentSlide) {\n element.left = element.left + 10\n element.top = element.top + 10\n }\n\n if(element.groupId) element.groupId = groupIdMap[element.groupId]\n }\n store.commit(MutationTypes.ADD_ELEMENT, elements)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))\n addHistorySnapshot()\n }\n\n const pasteSlide = (slide: Slide) => {\n store.commit(MutationTypes.ADD_SLIDE, slide)\n addHistorySnapshot()\n }\n\n const pasteText = (text: string) => {\n createTextElement({\n left: 0,\n top: 0,\n width: 600,\n height: 50,\n }, text)\n }\n\n const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {\n const onlySlide = options?.onlySlide || false\n const onlyElements = options?.onlyElements || false\n\n let clipboardData\n try {\n clipboardData = JSON.parse(decrypt(text))\n }\n catch {\n clipboardData = text\n }\n\n // 粘贴自定义元素或页面\n if(typeof clipboardData === 'object') {\n const { type, data } = clipboardData\n\n if(type === 'elements' && !onlySlide) pasteElement(data)\n else if(type === 'slide' && !onlyElements) pasteSlide(data)\n }\n\n // 粘贴普通文本\n else if(!onlyElements && !onlySlide) pasteText(clipboardData)\n }\n\n return {\n pasteTextClipboardData,\n }\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { copyText, readClipboard } from '@/utils/clipboard'\r\nimport { encrypt } from '@/utils/crypto'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { message } from 'ant-design-vue'\r\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n const theme = computed(() => store.state.theme)\r\n const slidesLength = computed(() => store.state.slides.length)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const { pasteTextClipboardData } = usePasteTextClipboardData()\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateSlideIndex = (command: string) => {\r\n let targetIndex = 0\r\n if(command === KEYS.UP && slideIndex.value > 0) {\r\n targetIndex = slideIndex.value - 1\r\n }\r\n else if(command === KEYS.DOWN && slideIndex.value < slidesLength.value - 1) {\r\n targetIndex = slideIndex.value + 1\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)\r\n }\r\n\r\n const copySlide = () => {\r\n const text = encrypt(JSON.stringify({\r\n type: 'slide',\r\n data: currentSlide.value,\r\n }))\r\n\r\n copyText(text).then(() => {\r\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, true)\r\n })\r\n }\r\n\r\n const pasteSlide = () => {\r\n readClipboard().then(text => {\r\n pasteTextClipboardData(text, { onlySlide: true })\r\n }).catch(err => message.warning(err))\r\n }\r\n\r\n const createSlide = () => {\r\n const emptySlide = {\r\n id: createRandomCode(8),\r\n elements: [],\r\n background: {\r\n type: 'solid',\r\n color: theme.value.backgroundColor,\r\n },\r\n }\r\n store.commit(MutationTypes.ADD_SLIDE, emptySlide)\r\n addHistorySnapshot()\r\n }\r\n\r\n const copyAndPasteSlide = () => {\r\n store.commit(MutationTypes.ADD_SLIDE, currentSlide.value)\r\n addHistorySnapshot()\r\n }\r\n\r\n const deleteSlide = () => {\r\n store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)\r\n addHistorySnapshot()\r\n }\r\n\r\n const cutSlide = () => {\r\n copySlide()\r\n deleteSlide()\r\n }\r\n\r\n return {\r\n updateSlideIndex,\r\n copySlide,\r\n pasteSlide,\r\n createSlide,\r\n copyAndPasteSlide,\r\n deleteSlide,\r\n cutSlide,\r\n }\r\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const lockElement = () => {\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n \n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id)) element.lock = true\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n addHistorySnapshot()\n }\n\n const unlockElement = (handleElement: PPTElement) => {\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n\n if(handleElement.groupId) {\n for(const element of newElementList) {\n if(element.groupId === handleElement.groupId) element.lock = false\n }\n return newElementList\n }\n \n for(const element of newElementList) {\n if(element.id === handleElement.id) {\n element.lock = false\n break\n }\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [handleElement.id])\n addHistorySnapshot()\n }\n\n return {\n lockElement,\n unlockElement,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const deleteElement = () => {\n if(!activeElementIdList.value.length) return\n const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id))\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n const deleteAllElements = () => {\n if(!currentSlide.value.elements.length) return\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })\n addHistorySnapshot()\n }\n\n return {\n deleteElement,\n deleteAllElements,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n // 组合元素(为当前所有激活元素添加一个相同的groupId)\n const combineElements = () => {\n if(!activeElementList.value.length) return\n\n let newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n const groupId = createRandomCode()\n\n const combineElementList: PPTElement[] = []\n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id)) {\n element.groupId = groupId\n combineElementList.push(element)\n }\n }\n\n // 注意,组合元素的层级应该是连续的,所以需要获取该组元素中最顶层的元素,将组内其他成员从原位置移动到最顶层的元素的下面\n const combineElementMaxIndex = newElementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id)\n const combineElementIdList = combineElementList.map(_element => _element.id)\n newElementList = newElementList.filter(_element => !combineElementIdList.includes(_element.id))\n\n const insertIndex = combineElementMaxIndex - combineElementList.length + 1\n newElementList.splice(insertIndex, 0, ...combineElementList)\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n // 取消组合元素(移除所有被激活元素的groupId)\n const uncombineElements = () => {\n if(!activeElementList.value.length) return\n const hasElementInGroup = activeElementList.value.some(item => item.groupId)\n if(!hasElementInGroup) return\n \n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id) && element.groupId) delete element.groupId\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n return {\n combineElements,\n uncombineElements,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { copyText, readClipboard } from '@/utils/clipboard'\nimport { encrypt } from '@/utils/crypto'\nimport { message } from 'ant-design-vue'\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\nimport useDeleteElement from './useDeleteElement'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n\n const { pasteTextClipboardData } = usePasteTextClipboardData()\n const { deleteElement } = useDeleteElement()\n\n const copyElement = () => {\n if(!activeElementIdList.value.length) return\n\n const text = encrypt(JSON.stringify({\n type: 'elements',\n data: activeElementList.value,\n }))\n\n copyText(text).then(() => {\n store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n })\n }\n\n const cutElement = () => {\n copyElement()\n deleteElement()\n }\n\n const pasteElement = () => {\n readClipboard().then(text => {\n pasteTextClipboardData(text)\n }).catch(err => message.warning(err))\n }\n\n const quickCopyElement = () => {\n copyElement()\n pasteElement()\n }\n\n return {\n copyElement,\n cutElement,\n pasteElement,\n quickCopyElement,\n }\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const selectAllElement = () => {\r\n const unlockedElements = currentSlide.value.elements.filter(el => !el.lock)\r\n const newActiveElementIdList = unlockedElements.map(el => el.id)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\r\n }\r\n\r\n return {\r\n selectAllElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const moveElement = (command: string) => {\r\n const newElementList = currentSlide.value.elements.map(el => {\r\n if(activeElementIdList.value.includes(el.id)) {\r\n let { left, top } = el\r\n switch(command) {\r\n case KEYS.LEFT: \r\n left = left - 1\r\n break\r\n case KEYS.RIGHT: \r\n left = left + 1\r\n break\r\n case KEYS.UP: \r\n top = top - 1\r\n break\r\n case KEYS.DOWN: \r\n top = top + 1\r\n break\r\n default: break\r\n }\r\n return { ...el, left, top }\r\n }\r\n return el\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n moveElement,\r\n }\r\n}","// 进入全屏\nexport const enterFullscreen = () => {\n const docElm = document.documentElement\n if(docElm.requestFullscreen) docElm.requestFullscreen() \n else if(docElm.mozRequestFullScreen) docElm.mozRequestFullScreen() \n else if(docElm.webkitRequestFullScreen) docElm.webkitRequestFullScreen()\n}\n\n// 退出全屏\nexport const exitFullscreen = () => {\n if(document.exitFullscreen) document.exitFullscreen()\n else if(document.mozCancelFullScreen) document.mozCancelFullScreen()\n else if(document.webkitCancelFullScreen) document.webkitCancelFullScreen()\n}\n\n// 判断是否全屏\nexport const isFullscreen = () => (\n document.mozFullScreen || \n document.webkitIsFullScreen || \n document.webkitFullScreen\n)","import { MutationTypes, useStore } from '@/store'\nimport { enterFullscreen, exitFullscreen, isFullscreen } from '@/utils/fullscreen'\n\nexport default () => {\n const store = useStore()\n\n const enterScreening = () => {\n enterFullscreen()\n store.commit(MutationTypes.SET_SCREENING, true)\n }\n\n const enterScreeningFromStart = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)\n enterScreening()\n }\n\n const exitScreening = () => {\n store.commit(MutationTypes.SET_SCREENING, false)\n if(isFullscreen()) exitFullscreen()\n }\n\n return {\n enterScreening,\n enterScreeningFromStart,\n exitScreening,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\n\nexport default () => {\n const store = useStore()\n const canvasPercentage = computed(() => store.state.canvasPercentage)\n\n const scaleCanvas = (command: '+' | '-') => {\n let percentage = canvasPercentage.value\n const step = 5\n const max = 120\n const min = 60\n if(command === '+' && percentage <= max) percentage += step\n if(command === '-' && percentage >= min) percentage -= step\n \n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\n }\n\n const setCanvasPercentage = (percentage: number) => {\n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\n }\n \n return {\n scaleCanvas,\n setCanvasPercentage,\n }\n}","import { computed, onMounted, onUnmounted } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { KEYS } from '@/configs/hotkey'\n\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useLockElement from '@/hooks/useLockElement'\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCombineElement from '@/hooks/useCombineElement'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\nimport useMoveElement from '@/hooks/useMoveElement'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useScreening from '@/hooks/useScreening'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\n\nexport default () => {\n const store = useStore()\n\n const ctrlKeyActive = computed(() => store.state.ctrlKeyState)\n const shiftKeyActive = computed(() => store.state.shiftKeyState)\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n\n const {\n updateSlideIndex,\n copySlide,\n createSlide,\n deleteSlide,\n cutSlide,\n copyAndPasteSlide,\n } = useSlideHandler()\n\n const { combineElements, uncombineElements } = useCombineElement()\n const { deleteElement } = useDeleteElement()\n const { lockElement } = useLockElement()\n const { copyElement, cutElement, quickCopyElement } = useCopyAndPasteElement()\n const { selectAllElement } = useSelectAllElement()\n const { moveElement } = useMoveElement()\n const { redo, undo } = useHistorySnapshot()\n const { enterScreening } = useScreening()\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\n\n const copy = () => {\n if(activeElementIdList.value.length) copyElement()\n else if(thumbnailsFocus.value) copySlide()\n }\n\n const cut = () => {\n if(activeElementIdList.value.length) cutElement()\n else if(thumbnailsFocus.value) cutSlide()\n }\n\n const quickCopy = () => {\n if(activeElementIdList.value.length) quickCopyElement()\n else if(thumbnailsFocus.value) copyAndPasteSlide()\n }\n\n const selectAll = () => {\n if(!editorAreaFocus.value) return\n selectAllElement()\n }\n\n const lock = () => {\n if(!editorAreaFocus.value) return\n lockElement()\n }\n const combine = () => {\n if(!editorAreaFocus.value) return\n combineElements()\n }\n\n const uncombine = () => {\n if(!editorAreaFocus.value) return\n uncombineElements()\n }\n\n const remove = () => {\n if(activeElementIdList.value.length) deleteElement()\n else if(thumbnailsFocus.value) deleteSlide()\n }\n\n const move = (key: string) => {\n if(activeElementIdList.value.length) moveElement(key)\n else if(key === KEYS.UP || key === KEYS.DOWN) updateSlideIndex(key)\n }\n\n const create = () => {\n if(!thumbnailsFocus.value) return\n createSlide()\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const { ctrlKey, shiftKey, metaKey } = e\n\n const key = e.key.toUpperCase()\n\n if(ctrlKey && !ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, true)\n if(shiftKey && !shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, true)\n\n if(ctrlKey && key === KEYS.F) {\n e.preventDefault()\n enterScreening()\n store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\n }\n \n if(!editorAreaFocus.value && !thumbnailsFocus.value) return \n\n if((ctrlKey || metaKey) && key === KEYS.C) {\n if(disableHotkeys.value) return\n e.preventDefault()\n copy()\n }\n if(ctrlKey && key === KEYS.X) {\n if(disableHotkeys.value) return\n e.preventDefault()\n cut()\n }\n if(ctrlKey && key === KEYS.D) {\n if(disableHotkeys.value) return\n e.preventDefault()\n quickCopy()\n }\n if(ctrlKey && key === KEYS.Z) {\n if(disableHotkeys.value) return\n e.preventDefault()\n undo()\n }\n if(ctrlKey && key === KEYS.Y) {\n if(disableHotkeys.value) return\n e.preventDefault()\n redo()\n }\n if(ctrlKey && key === KEYS.A) {\n if(disableHotkeys.value) return\n e.preventDefault()\n selectAll()\n }\n if(ctrlKey && key === KEYS.L) {\n if(disableHotkeys.value) return\n e.preventDefault()\n lock()\n }\n if(!shiftKey && ctrlKey && key === KEYS.G) {\n if(disableHotkeys.value) return\n e.preventDefault()\n combine()\n }\n if(shiftKey && ctrlKey && key === KEYS.G) {\n if(disableHotkeys.value) return\n e.preventDefault()\n uncombine()\n }\n if(key === KEYS.DELETE) {\n if(disableHotkeys.value) return\n e.preventDefault()\n remove()\n }\n if(key === KEYS.UP) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.UP)\n }\n if(key === KEYS.DOWN) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.DOWN)\n }\n if(key === KEYS.LEFT) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.LEFT)\n }\n if(key === KEYS.RIGHT) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.RIGHT)\n }\n if(key === KEYS.ENTER) {\n if(disableHotkeys.value) return\n e.preventDefault()\n create()\n }\n if(key === KEYS.MINUS) {\n if(disableHotkeys.value) return\n e.preventDefault()\n scaleCanvas('-')\n }\n if(key === KEYS.EQUAL) {\n if(disableHotkeys.value) return\n e.preventDefault()\n scaleCanvas('+')\n }\n if(key === KEYS.DIGIT_0) {\n if(disableHotkeys.value) return\n e.preventDefault()\n setCanvasPercentage(90)\n }\n }\n \n const keyupListener = () => {\n if(ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\n if(shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, false)\n }\n\n onMounted(() => {\n document.addEventListener('keydown', keydownListener)\n document.addEventListener('keyup', keyupListener)\n window.addEventListener('blur', keyupListener)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keydownListener)\n document.removeEventListener('keyup', keyupListener)\n window.removeEventListener('blur', keyupListener)\n })\n}","import { computed, onMounted, onUnmounted } from 'vue'\nimport { useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default () => {\n const store = useStore()\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n\n const { pasteTextClipboardData } = usePasteTextClipboardData()\n const { createImageElement } = useCreateElement()\n\n const pasteImageFile = (imageFile: File) => {\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n\n const pasteListener = (e: ClipboardEvent) => {\n if(!editorAreaFocus.value && !thumbnailsFocus.value) return\n if(disableHotkeys.value) return\n\n if(!e.clipboardData) return\n\n const clipboardDataItems = e.clipboardData.items\n const clipboardDataFirstItem = clipboardDataItems[0]\n\n if(!clipboardDataFirstItem) return\n\n for(const item of clipboardDataItems) {\n if(item.kind === 'file' && item.type.indexOf('image') !== -1) {\n const imageFile = item.getAsFile()\n if(imageFile) pasteImageFile(imageFile)\n return\n }\n }\n\n if(clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\n clipboardDataFirstItem.getAsString(text => pasteTextClipboardData(text))\n }\n }\n\n onMounted(() => {\n document.addEventListener('paste', pasteListener)\n })\n onUnmounted(() => {\n document.removeEventListener('paste', pasteListener)\n })\n}","\n\n\n\n","\nimport { computed, defineComponent, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { createRandomCode } from '@/utils/common'\nimport useScreening from '@/hooks/useScreening'\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport { message } from 'ant-design-vue'\n\nconst hotkeys = [\n {\n type: '通用',\n children: [\n { label: '剪切', value: 'Ctrl + X' },\n { label: '复制', value: 'Ctrl + C' },\n { label: '粘贴', value: 'Ctrl + V' },\n { label: '快速复制粘贴', value: 'Ctrl + D' },\n { label: '全选', value: 'Ctrl + A' },\n { label: '撤销', value: 'Ctrl + Z' },\n { label: '恢复', value: 'Ctrl + Y' },\n { label: '删除', value: 'Delete' },\n ],\n },\n {\n type: '幻灯片放映',\n children: [\n { label: '开始放映幻灯片', value: 'Ctrl + F' },\n { label: '切换上一页', value: '↑ / ←' },\n { label: '切换下一页', value: '↓ / → / Enter / Space' },\n { label: '退出放映', value: 'ESC' },\n ],\n },\n {\n type: '幻灯片编辑',\n children: [\n { label: '新建幻灯片', value: 'Enter' },\n { label: '缩放画布', value: 'Ctrl + 鼠标滚动' },\n { label: '放大画布', value: 'Ctrl + =' },\n { label: '缩小画布', value: 'Ctrl + -' },\n { label: '缩放画布到合适大小', value: 'Ctrl + 0' },\n { label: '编辑上一页', value: '↑ / ←' },\n { label: '编辑下一页', value: '↓ / →' },\n ],\n },\n {\n type: '元素操作',\n children: [\n { label: '移动', value: '↑ / ← / ↓ / →' },\n { label: '锁定', value: 'Ctrl + L' },\n { label: '组合', value: 'Ctrl + G' },\n { label: '取消组合', value: 'Ctrl + Shift + G' },\n { label: '多选', value: '按住 Ctrl 或 Shift' },\n { label: '锁定宽高比例', value: '按住 Ctrl 或 Shift' },\n { label: '创建水平 / 垂直线条', value: '按住 Ctrl 或 Shift' },\n { label: '确认图片裁剪', value: 'Enter' },\n ],\n },\n {\n type: '表格编辑',\n children: [\n { label: '聚焦到下一个单元格', value: 'Tab' },\n ],\n },\n {\n type: '文本编辑',\n children: [\n { label: '加粗', value: 'Ctrl + B' },\n { label: '斜体', value: 'Ctrl + I' },\n { label: '下划线', value: 'Ctrl + U' },\n { label: '删除线', value: 'Ctrl + D' },\n ],\n },\n]\n\nexport default defineComponent({\n name: 'editor-header',\n setup() {\n const store = useStore()\n\n const { enterScreening, enterScreeningFromStart } = useScreening()\n const { createSlide, deleteSlide } = useSlideHandler()\n const { redo, undo } = useHistorySnapshot()\n\n const showGridLines = computed(() => store.state.showGridLines)\n const toggleGridLines = () => {\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\n }\n\n const resetSlides = () => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.SET_SLIDES, [{\n id: createRandomCode(),\n elements: [],\n }])\n }\n\n const openDoc = () => {\n message.warning('作者努力编写中...')\n }\n\n const hotkeyDrawerVisible = ref(false)\n\n return {\n enterScreening,\n enterScreeningFromStart,\n createSlide,\n deleteSlide,\n redo,\n undo,\n toggleGridLines,\n showGridLines,\n resetSlides,\n openDoc,\n hotkeyDrawerVisible,\n hotkeys,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=2accc3e9&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=2accc3e9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2accc3e9\"\n\nexport default script","\n\n\n\n","import { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\n\r\nexport type ElementOrderCommand = 'up' | 'down' | 'top' | 'bottom'\r\n\r\nexport const enum ElementOrderCommands {\r\n UP = 'up',\r\n DOWN = 'down',\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n}\r\n\r\nexport type ElementAlignCommand = 'top'| 'bottom' | 'left' | 'right' | 'vertical' | 'horizontal'\r\n\r\nexport const enum ElementAlignCommands {\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n VERTICAL = 'vertical',\r\n HORIZONTAL = 'horizontal',\r\n}\r\n\r\nexport type OperateBorderLine = 'top' | 'bottom' | 'left' | 'right'\r\n\r\nexport const enum OperateBorderLines {\r\n T = 'top',\r\n B = 'bottom',\r\n L = 'left',\r\n R = 'right',\r\n}\r\n\r\nexport type OperateResizeHandler = '' | 'left-top' | 'top' | 'right-top' | 'left' | 'right' | 'left-bottom' | 'bottom' | 'right-bottom'\r\n\r\nexport const enum OperateResizeHandlers {\r\n LEFT_TOP = 'left-top',\r\n TOP = 'top',\r\n RIGHT_TOP = 'right-top',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n LEFT_BOTTOM = 'left-bottom',\r\n BOTTOM = 'bottom',\r\n RIGHT_BOTTOM = 'right-bottom',\r\n}\r\n\r\nexport type OperateLineHandler = 'start' | 'end'\r\n\r\nexport const enum OperateLineHandlers {\r\n START = 'start',\r\n END = 'end,'\r\n}\r\n\r\nexport interface AlignmentLineAxis {\r\n x: number; \r\n y: number;\r\n}\r\n\r\nexport interface AlignmentLineProps {\r\n type: 'vertical' | 'horizontal';\r\n axis: AlignmentLineAxis;\r\n length: number;\r\n}\r\n\r\nexport interface MultiSelectRange {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n}\r\n\r\nexport type ImageClipDataRange = [[number, number], [number, number]]\r\n\r\nexport interface ImageClipData {\r\n range: ImageClipDataRange;\r\n path: string;\r\n}\r\n\r\nexport interface ImageClipedEmitData {\r\n range: ImageClipDataRange;\r\n position: {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n };\r\n}\r\n\r\nexport interface CreateElementSelectionData {\r\n start: [number, number];\r\n end: [number, number];\r\n}\r\n\r\nexport interface CreatingTextElement {\r\n type: 'text';\r\n}\r\nexport interface CreatingShapeElement {\r\n type: 'shape';\r\n data: ShapePoolItem;\r\n}\r\nexport interface CreatingLineElement {\r\n type: 'line';\r\n data: LinePoolItem;\r\n}\r\nexport type CreatingElement = CreatingTextElement | CreatingShapeElement | CreatingLineElement","export const removeAllRanges = () => {\n const selection = window.getSelection()\n selection && selection.removeAllRanges()\n}","import { ref, computed, onMounted, onUnmounted, Ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\n\nexport default (canvasRef: Ref) => {\n const viewportLeft = ref(0)\n const viewportTop = ref(0)\n\n const store = useStore()\n const canvasPercentage = computed(() => store.state.canvasPercentage)\n\n const setViewportSize = () => {\n if(!canvasRef.value) return\n const canvasWidth = canvasRef.value.clientWidth\n const canvasHeight = canvasRef.value.clientHeight\n\n if(canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {\n const viewportActualWidth = canvasWidth * (canvasPercentage.value / 100)\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualWidth / VIEWPORT_SIZE)\n viewportLeft.value = (canvasWidth - viewportActualWidth) / 2\n viewportTop.value = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2\n }\n else {\n const viewportActualHeight = canvasHeight * (canvasPercentage.value / 100)\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO))\n viewportLeft.value = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2\n viewportTop.value = (canvasHeight - viewportActualHeight) / 2\n }\n }\n\n watch(canvasPercentage, setViewportSize)\n\n const viewportStyles = computed(() => ({\n width: VIEWPORT_SIZE,\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\n left: viewportLeft.value,\n top: viewportTop.value,\n }))\n\n const resizeObserver = new ResizeObserver(setViewportSize)\n\n onMounted(() => {\n if(canvasRef.value) resizeObserver.observe(canvasRef.value)\n })\n onUnmounted(() => {\n if(canvasRef.value) resizeObserver.unobserve(canvasRef.value)\n })\n\n return {\n viewportStyles,\n }\n}","import { PPTElement } from '@/types/slides'\r\n\r\n// 获取矩形旋转后在画布中的位置范围\r\ninterface RotatedElementData {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n rotate: number;\r\n}\r\nexport const getRectRotatedRange = (element: RotatedElementData) => {\r\n const { left, top, width, height, rotate = 0 } = element\r\n\r\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\r\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\r\n\r\n const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180\r\n const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180\r\n\r\n const halfWidth = width / 2\r\n const halfHeight = height / 2\r\n\r\n const middleLeft = left + halfWidth\r\n const middleTop = top + halfHeight\r\n\r\n const xAxis = [\r\n middleLeft + radius * Math.cos(tlbraRadian),\r\n middleLeft + radius * Math.cos(trblaRadian),\r\n middleLeft - radius * Math.cos(tlbraRadian),\r\n middleLeft - radius * Math.cos(trblaRadian),\r\n ]\r\n const yAxis = [\r\n middleTop - radius * Math.sin(tlbraRadian),\r\n middleTop - radius * Math.sin(trblaRadian),\r\n middleTop + radius * Math.sin(tlbraRadian),\r\n middleTop + radius * Math.sin(trblaRadian),\r\n ]\r\n\r\n return {\r\n xRange: [Math.min(...xAxis), Math.max(...xAxis)],\r\n yRange: [Math.min(...yAxis), Math.max(...yAxis)],\r\n }\r\n}\r\n\r\n// 获取元素在画布中的位置范围\r\nexport const getElementRange = (element: PPTElement) => {\r\n let minX, maxX, minY, maxY\r\n\r\n if(element.type === 'line') {\r\n minX = element.left\r\n maxX = element.left + Math.max(element.start[0], element.end[0])\r\n minY = element.top\r\n maxY = element.top + Math.max(element.start[1], element.end[1])\r\n }\r\n else if('rotate' in element && element.rotate) {\r\n const { left, top, width, height, rotate } = element\r\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\r\n minX = xRange[0]\r\n maxX = xRange[1]\r\n minY = yRange[0]\r\n maxY = yRange[1]\r\n }\r\n else {\r\n minX = element.left\r\n maxX = element.left + element.width\r\n minY = element.top\r\n maxY = element.top + element.height\r\n }\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\n// 获取元素集合在画布中的位置范围\r\nexport const getElementListRange = (elementList: PPTElement[]) => {\r\n const leftValues: number[] = []\r\n const topValues: number[] = []\r\n const rightValues: number[] = []\r\n const bottomValues: number[] = []\r\n\r\n elementList.forEach(element => {\r\n const { minX, maxX, minY, maxY } = getElementRange(element)\r\n leftValues.push(minX)\r\n topValues.push(minY)\r\n rightValues.push(maxX)\r\n bottomValues.push(maxY)\r\n })\r\n\r\n const minX = Math.min(...leftValues)\r\n const maxX = Math.max(...rightValues)\r\n const minY = Math.min(...topValues)\r\n const maxY = Math.max(...bottomValues)\r\n\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\nexport interface AlignLine {\r\n value: number;\r\n range: [number, number];\r\n}\r\n\r\n// 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条\r\nexport const uniqAlignLines = (lines: AlignLine[]) => {\r\n const uniqLines: AlignLine[] = []\r\n lines.forEach(line => {\r\n const index = uniqLines.findIndex(_line => _line.value === line.value)\r\n if(index === -1) uniqLines.push(line)\r\n else {\r\n const uniqLine = uniqLines[index]\r\n const rangeMin = Math.min(uniqLine.range[0], line.range[0])\r\n const rangeMax = Math.max(uniqLine.range[1], line.range[1])\r\n const range: [number, number] = [rangeMin, rangeMax]\r\n const _line = { value: line.value, range }\r\n uniqLines[index] = _line\r\n }\r\n })\r\n return uniqLines\r\n}","import { Ref, reactive, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { getElementRange } from '@/utils/element'\n\nexport default (elementList: Ref, viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const mouseSelectionState = reactive({\n isShow: false,\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n quadrant: 1,\n })\n\n const updateMouseSelection = (e: MouseEvent) => {\n if(!viewportRef.value) return\n\n let isMouseDown = true\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const minSelectionRange = 5\n \n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const left = (startPageX - viewportRect.x) / canvasScale.value\n const top = (startPageY - viewportRect.y) / canvasScale.value\n\n mouseSelectionState.isShow = false\n mouseSelectionState.quadrant = 4\n mouseSelectionState.top = top\n mouseSelectionState.left = left\n mouseSelectionState.width = 0\n mouseSelectionState.height = 0\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const offsetWidth = (currentPageX - startPageX) / canvasScale.value\n const offsetHeight = (currentPageY - startPageY) / canvasScale.value\n\n const width = Math.abs(offsetWidth)\n const height = Math.abs(offsetHeight)\n\n if( width < minSelectionRange || height < minSelectionRange ) return\n \n let quadrant = 0\n if( offsetWidth > 0 && offsetHeight > 0 ) quadrant = 4\n else if( offsetWidth < 0 && offsetHeight < 0 ) quadrant = 1\n else if( offsetWidth > 0 && offsetHeight < 0 ) quadrant = 2\n else if( offsetWidth < 0 && offsetHeight > 0 ) quadrant = 3\n\n mouseSelectionState.isShow = true\n mouseSelectionState.quadrant = quadrant\n mouseSelectionState.width = width\n mouseSelectionState.height = height\n }\n\n document.onmouseup = () => {\n document.onmousemove = null\n document.onmouseup = null\n isMouseDown = false\n\n // 计算当前页面中的每一个元素是否处在鼠标选择范围中(必须完全包裹)\n // 将选择范围中的元素添加为激活元素\n let inRangeElementList: PPTElement[] = []\n for(let i = 0; i < elementList.value.length; i++) {\n const element = elementList.value[i]\n const mouseSelectionLeft = mouseSelectionState.left\n const mouseSelectionTop = mouseSelectionState.top\n const mouseSelectionWidth = mouseSelectionState.width\n const mouseSelectionHeight = mouseSelectionState.height\n\n const quadrant = mouseSelectionState.quadrant\n\n const { minX, maxX, minY, maxY } = getElementRange(element)\n\n let isInclude = false\n if(quadrant === 4) {\n isInclude = minX > mouseSelectionLeft && \n maxX < mouseSelectionLeft + mouseSelectionWidth && \n minY > mouseSelectionTop && \n maxY < mouseSelectionTop + mouseSelectionHeight\n }\n else if(quadrant === 1) {\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \n minY > (mouseSelectionTop - mouseSelectionHeight) && \n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\n }\n else if(quadrant === 2) {\n isInclude = minX > mouseSelectionLeft && \n maxX < mouseSelectionLeft + mouseSelectionWidth && \n minY > (mouseSelectionTop - mouseSelectionHeight) && \n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\n }\n else if(quadrant === 3) {\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \n minY > mouseSelectionTop && \n maxY < mouseSelectionTop + mouseSelectionHeight\n }\n\n // 被锁定的元素除外\n if(isInclude && !element.lock) inRangeElementList.push(element)\n }\n\n // 对于组合元素成员,必须所有成员都在选择范围中才算被选中\n inRangeElementList = inRangeElementList.filter(inRangeElement => {\n if(inRangeElement.groupId) {\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\n const groupElementList = elementList.value.filter(element => element.groupId === inRangeElement.groupId)\n return groupElementList.every(groupElement => inRangeElementIdList.includes(groupElement.id))\n }\n return true\n })\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\n if(inRangeElementIdList.length) store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, inRangeElementIdList)\n\n mouseSelectionState.isShow = false\n }\n }\n\n return {\n mouseSelectionState,\n updateMouseSelection,\n }\n}","import { computed, onMounted, onUnmounted, Ref } from 'vue'\nimport { useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default (elementRef: Ref) => {\n const store = useStore()\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n\n const { createImageElement, createTextElement } = useCreateElement()\n\n const handleDrop = (e: DragEvent) => {\n if(!e.dataTransfer) return\n const dataTransferItem = e.dataTransfer.items[0]\n\n if(dataTransferItem.kind === 'file' && dataTransferItem.type.indexOf('image') !== -1) {\n const imageFile = dataTransferItem.getAsFile()\n if(imageFile) {\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n }\n else if(dataTransferItem.kind === 'string' && dataTransferItem.type === 'text/plain') {\n dataTransferItem.getAsString(text => {\n if(disableHotkeys.value) return\n createTextElement({\n left: 0,\n top: 0,\n width: 600,\n height: 50,\n }, text)\n })\n }\n }\n\n onMounted(() => {\n elementRef.value && elementRef.value.addEventListener('drop', handleDrop)\n\n document.ondragleave = e => e.preventDefault()\n document.ondrop = e => e.preventDefault()\n document.ondragenter = e => e.preventDefault()\n document.ondragover = e => e.preventDefault()\n })\n onUnmounted(() => {\n elementRef.value && elementRef.value.removeEventListener('drop', handleDrop)\n\n document.ondragleave = null\n document.ondrop = null\n document.ondragenter = null\n document.ondragover = null\n })\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\n// 给定一个坐标,计算该坐标到(0, 0)点连线的弧度值\n// 注意,Math.atan2的一般用法是Math.atan2(y, x)返回的是原点(0,0)到(x,y)点的线段与X轴正方向之间的弧度值\n// 这里将使用时将x与y的传入顺序交换了,为的是获取原点(0,0)到(x,y)点的线段与Y轴正方向之间的弧度值\nconst getAngleFromCoordinate = (x: number, y: number) => {\n const radian = Math.atan2(x, y)\n const angle = 180 / Math.PI * radian\n return angle\n}\n\nexport default (elementList: Ref, viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {\n let isMouseDown = true\n let angle = 0\n const elOriginRotate = element.rotate || 0\n\n // 计算元素中心(旋转的中心,坐标原点)\n const elLeft = element.left\n const elTop = element.top\n const elWidth = element.width\n const elHeight = element.height\n const centerX = elLeft + elWidth / 2\n const centerY = elTop + elHeight / 2\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n // 计算鼠标基于旋转中心的坐标\n const mouseX = (e.pageX - viewportRect.left) / canvasScale.value\n const mouseY = (e.pageY - viewportRect.top) / canvasScale.value\n const x = mouseX - centerX\n const y = centerY - mouseY\n\n angle = getAngleFromCoordinate(x, y)\n\n // 45°的倍数位置有吸附效果\n const sorptionRange = 5\n if( Math.abs(angle) <= sorptionRange ) angle = 0\n else if( angle > 0 && Math.abs(angle - 45) <= sorptionRange ) angle -= (angle - 45)\n else if( angle < 0 && Math.abs(angle + 45) <= sorptionRange ) angle -= (angle + 45)\n else if( angle > 0 && Math.abs(angle - 90) <= sorptionRange ) angle -= (angle - 90)\n else if( angle < 0 && Math.abs(angle + 90) <= sorptionRange ) angle -= (angle + 90)\n else if( angle > 0 && Math.abs(angle - 135) <= sorptionRange ) angle -= (angle - 135)\n else if( angle < 0 && Math.abs(angle + 135) <= sorptionRange ) angle -= (angle + 135)\n else if( angle > 0 && Math.abs(angle - 180) <= sorptionRange ) angle -= (angle - 180)\n else if( angle < 0 && Math.abs(angle + 180) <= sorptionRange ) angle -= (angle + 180)\n\n // 修改元素角度\n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, rotate: angle } : el)\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n if(elOriginRotate === angle) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n rotateElement,\n }\n}","import mitt, { Emitter } from 'mitt'\n\nexport const enum EmitterEvents {\n UPDATE_TEXT_STATE = 'UPDATE_TEXT_STATE',\n EXEC_TEXT_COMMAND = 'EXEC_TEXT_COMMAND',\n UPDATE_TABLE_SELECTED_CELL = 'UPDATE_TABLE_SELECTED_CELL',\n SCALE_ELEMENT_STATE = 'SCALE_ELEMENT_STATE',\n}\n\nconst emitter: Emitter = mitt()\n\nexport default emitter","export const ELEMENT_TYPE_ZH = {\n text: '文本',\n image: '图片',\n shape: '形状',\n line: '线条',\n chart: '图表',\n table: '表格',\n}\n\nexport const MIN_SIZE = {\n text: 20,\n image: 20,\n shape: 15,\n chart: 200,\n table: 20,\n}","import { computed, Ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandlers, AlignmentLineProps, MultiSelectRange } from '@/types/edit'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { MIN_SIZE } from '@/configs/element'\nimport { AlignLine, uniqAlignLines } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\n// 计算元素被旋转一定角度后,八个操作点的新坐标\ninterface RotateElementData {\n left: number;\n top: number;\n width: number;\n height: number;\n}\nconst getRotateElementPoints = (element: RotateElementData, angle: number) => {\n const { left, top, width, height } = element\n\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\n\n const tlbraRadian = (180 - angle - auxiliaryAngle) * Math.PI / 180\n const trblaRadian = (auxiliaryAngle - angle) * Math.PI / 180\n const taRadian = (90 - angle) * Math.PI / 180\n const raRadian = angle * Math.PI / 180\n\n const halfWidth = width / 2\n const halfHeight = height / 2\n\n const middleLeft = left + halfWidth\n const middleTop = top + halfHeight\n\n const leftTopPoint = {\n left: middleLeft + radius * Math.cos(tlbraRadian),\n top: middleTop - radius * Math.sin(tlbraRadian),\n }\n const topPoint = {\n left: middleLeft + halfHeight * Math.cos(taRadian),\n top: middleTop - halfHeight * Math.sin(taRadian),\n }\n const rightTopPoint = {\n left: middleLeft + radius * Math.cos(trblaRadian),\n top: middleTop - radius * Math.sin(trblaRadian),\n }\n const rightPoint = {\n left: middleLeft + halfWidth * Math.cos(raRadian),\n top: middleTop + halfWidth * Math.sin(raRadian),\n }\n const rightBottomPoint = {\n left: middleLeft - radius * Math.cos(tlbraRadian),\n top: middleTop + radius * Math.sin(tlbraRadian),\n }\n const bottomPoint = {\n left: middleLeft - halfHeight * Math.sin(raRadian),\n top: middleTop + halfHeight * Math.cos(raRadian),\n }\n const leftBottomPoint = {\n left: middleLeft - radius * Math.cos(trblaRadian),\n top: middleTop + radius * Math.sin(trblaRadian),\n }\n const leftPoint = {\n left: middleLeft - halfWidth * Math.cos(raRadian),\n top: middleTop - halfWidth * Math.sin(raRadian),\n }\n\n return { leftTopPoint, topPoint, rightTopPoint, rightPoint, rightBottomPoint, bottomPoint, leftBottomPoint, leftPoint }\n}\n\n// 获取元素某个操作点对角线上另一端的操作点坐标(例如:左上 <-> 右下)\nconst getOppositePoint = (direction: string, points: ReturnType): { left: number; top: number } => {\n const oppositeMap = {\n [OperateResizeHandlers.RIGHT_BOTTOM]: points.leftTopPoint,\n [OperateResizeHandlers.LEFT_BOTTOM]: points.rightTopPoint,\n [OperateResizeHandlers.LEFT_TOP]: points.rightBottomPoint,\n [OperateResizeHandlers.RIGHT_TOP]: points.leftBottomPoint,\n [OperateResizeHandlers.TOP]: points.bottomPoint,\n [OperateResizeHandlers.BOTTOM]: points.topPoint,\n [OperateResizeHandlers.LEFT]: points.rightPoint,\n [OperateResizeHandlers.RIGHT]: points.leftPoint,\n }\n return oppositeMap[direction]\n}\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n alignmentLines: Ref,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const scaleElement = (e: MouseEvent, element: Exclude, command: OperateResizeHandlers) => {\n let isMouseDown = true\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, true)\n\n const elOriginLeft = element.left\n const elOriginTop = element.top\n const elOriginWidth = element.width\n const elOriginHeight = element.height\n\n const fixedRatio = ctrlOrShiftKeyActive.value || ('fixedRatio' in element && element.fixedRatio)\n const aspectRatio = elOriginWidth / elOriginHeight\n \n const elRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n const rotateRadian = Math.PI * elRotate / 180\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const minSize = MIN_SIZE[element.type] || 20\n const getSizeWithinRange = (size: number) => size < minSize ? minSize : size\n\n let points: ReturnType\n let baseLeft = 0\n let baseTop = 0\n let horizontalLines: AlignLine[] = []\n let verticalLines: AlignLine[] = []\n\n if('rotate' in element && element.rotate) {\n // 元素旋转后的各点坐标以及对角坐标\n const { left, top, width, height } = element\n points = getRotateElementPoints({ left, top, width, height }, elRotate)\n const oppositePoint = getOppositePoint(command, points)\n\n // 基点坐标(以操作点相对的点为基点,例如拖动右下角,实际上是保持左上角不变的前提下修改其他信息)\n baseLeft = oppositePoint.left\n baseTop = oppositePoint.top\n }\n else {\n const edgeWidth = VIEWPORT_SIZE\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n const isActiveGroupElement = element.id === activeGroupElementId.value\n \n for(const el of elementList.value) {\n if('rotate' in el && el.rotate) continue\n if(el.type === 'line') continue\n if(isActiveGroupElement && el.id === element.id) continue\n if(!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\n\n const left = el.left\n const top = el.top\n const width = el.width\n const height = el.height\n const right = left + width\n const bottom = top + height\n\n const topLine: AlignLine = { value: top, range: [left, right] }\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\n\n horizontalLines.push(topLine, bottomLine)\n verticalLines.push(leftLine, rightLine)\n }\n\n // 页面边界、水平和垂直的中心位置\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\n\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\n \n horizontalLines = uniqAlignLines(horizontalLines)\n verticalLines = uniqAlignLines(verticalLines)\n }\n \n // 对齐吸附方法\n const alignedAdsorption = (currentX: number | null, currentY: number | null) => {\n const sorptionRange = 5\n\n const _alignmentLines: AlignmentLineProps[] = []\n let isVerticalAdsorbed = false\n let isHorizontalAdsorbed = false\n const correctionVal = { offsetX: 0, offsetY: 0 }\n \n if(currentY || currentY === 0) {\n for(let i = 0; i < horizontalLines.length; i++) {\n const { value, range } = horizontalLines[i]\n const min = Math.min(...range, currentX || 0)\n const max = Math.max(...range, currentX || 0)\n \n if(Math.abs(currentY - value) < sorptionRange && !isHorizontalAdsorbed) {\n correctionVal.offsetY = currentY - value\n isHorizontalAdsorbed = true\n _alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })\n }\n }\n }\n if(currentX || currentX === 0) {\n for(let i = 0; i < verticalLines.length; i++) {\n const { value, range } = verticalLines[i]\n const min = Math.min(...range, (currentY || 0))\n const max = Math.max(...range, (currentY || 0))\n\n if(Math.abs(currentX - value) < sorptionRange && !isVerticalAdsorbed) {\n correctionVal.offsetX = currentX - value\n isVerticalAdsorbed = true\n _alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })\n }\n }\n }\n alignmentLines.value = _alignmentLines\n return correctionVal\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const x = currentPageX - startPageX\n const y = currentPageY - startPageY\n\n let width = elOriginWidth\n let height = elOriginHeight\n let left = elOriginLeft\n let top = elOriginTop\n \n // 元素被旋转的情况下\n if(elRotate) {\n // 根据元素旋转的角度,修正鼠标按下后移动的距离(因为拖动的方向发生了改变)\n const revisedX = (Math.cos(rotateRadian) * x + Math.sin(rotateRadian) * y) / canvasScale.value\n let revisedY = (Math.cos(rotateRadian) * y - Math.sin(rotateRadian) * x) / canvasScale.value\n\n // 锁定宽高比例\n if(fixedRatio) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) revisedY = revisedX / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) revisedY = -revisedX / aspectRatio\n }\n\n // 根据不同的操作点分别计算元素缩放后的大小和位置\n // 这里计算的位置是错误的,因为旋转后缩放实际上也改变了元素的位置,需要在后面进行矫正\n // 这里计算的大小是正确的,因为上面修正鼠标按下后移动的距离时其实已经进行过了矫正\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n height = getSizeWithinRange(elOriginHeight + revisedY)\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n height = getSizeWithinRange(elOriginHeight + revisedY)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n height = getSizeWithinRange(elOriginHeight - revisedY)\n left = elOriginLeft - (width - elOriginWidth)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n height = getSizeWithinRange(elOriginHeight - revisedY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.TOP) {\n height = getSizeWithinRange(elOriginHeight - revisedY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n height = getSizeWithinRange(elOriginHeight + revisedY)\n }\n else if(command === OperateResizeHandlers.LEFT) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n }\n\n // 获取当前元素基点坐标,与初始状态的基点坐标进行对比并矫正差值\n const currentPoints = getRotateElementPoints({ width, height, left, top }, elRotate)\n const currentOppositePoint = getOppositePoint(command, currentPoints)\n const currentBaseLeft = currentOppositePoint.left\n const currentBaseTop = currentOppositePoint.top\n\n const offsetX = currentBaseLeft - baseLeft\n const offsetY = currentBaseTop - baseTop\n\n left = left - offsetX\n top = top - offsetY\n }\n\n // 元素未被旋转的情况下,根据所操纵点的位置添加对齐吸附\n else {\n let moveX = x / canvasScale.value\n let moveY = y / canvasScale.value\n\n if(fixedRatio) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) moveY = moveX / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) moveY = -moveX / aspectRatio\n }\n\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + elOriginHeight + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = moveY * aspectRatio\n else moveY = moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth + moveX)\n height = getSizeWithinRange(elOriginHeight + moveY)\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + elOriginHeight + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = -moveY * aspectRatio\n else moveY = -moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth - moveX)\n height = getSizeWithinRange(elOriginHeight + moveY)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = moveY * aspectRatio\n else moveY = moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth - moveX)\n height = getSizeWithinRange(elOriginHeight - moveY)\n left = elOriginLeft - (width - elOriginWidth)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = -moveY * aspectRatio\n else moveY = -moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth + moveX)\n height = getSizeWithinRange(elOriginHeight - moveY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.LEFT) {\n const { offsetX } = alignedAdsorption(elOriginLeft + moveX, null)\n moveX = moveX - offsetX\n width = getSizeWithinRange(elOriginWidth - moveX)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n const { offsetX } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, null)\n moveX = moveX - offsetX\n width = getSizeWithinRange(elOriginWidth + moveX)\n }\n else if(command === OperateResizeHandlers.TOP) {\n const { offsetY } = alignedAdsorption(null, elOriginTop + moveY)\n moveY = moveY - offsetY\n height = getSizeWithinRange(elOriginHeight - moveY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n const { offsetY } = alignedAdsorption(null, elOriginTop + elOriginHeight + moveY)\n moveY = moveY - offsetY\n height = getSizeWithinRange(elOriginHeight + moveY)\n }\n }\n \n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, left, top, width, height } : el)\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n alignmentLines.value = []\n \n if(startPageX === e.pageX && startPageY === e.pageY) return\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, false)\n \n addHistorySnapshot()\n }\n }\n\n const scaleMultiElement = (e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandlers) => {\n let isMouseDown = true\n \n const { minX, maxX, minY, maxY } = range\n const operateWidth = maxX - minX\n const operateHeight = maxY - minY\n const aspectRatio = operateWidth / operateHeight\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 鼠标按下后移动的距离\n const x = (currentPageX - startPageX) / canvasScale.value\n let y = (currentPageY - startPageY) / canvasScale.value\n\n // 锁定宽高比例\n if(ctrlOrShiftKeyActive.value) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) y = x / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) y = -x / aspectRatio\n }\n\n // 获取鼠标缩放时当前所有激活元素的范围\n let currentMinX = minX\n let currentMaxX = maxX\n let currentMinY = minY\n let currentMaxY = maxY\n\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n currentMaxX = maxX + x\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n currentMinX = minX + x\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n currentMinX = minX + x\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n currentMaxX = maxX + x\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.TOP) {\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT) {\n currentMinX = minX + x\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n currentMaxX = maxX + x\n }\n\n // 多选下所有元素整体宽高\n const currentOppositeWidth = currentMaxX - currentMinX\n const currentOppositeHeight = currentMaxY - currentMinY\n\n // 所有元素的整体宽高与被操作元素宽高的比例\n let widthScale = currentOppositeWidth / operateWidth\n let heightScale = currentOppositeHeight / operateHeight\n\n if(widthScale <= 0) widthScale = 0\n if(heightScale <= 0) heightScale = 0\n \n // 根据上面计算的比例,修改所有被激活元素的位置大小\n // 宽高通过乘以对应的比例得到,位置通过将被操作元素在所有元素整体中的相对位置乘以对应比例获得\n elementList.value = elementList.value.map(el => {\n if((el.type === 'image' || el.type === 'shape') && activeElementIdList.value.includes(el.id)) {\n const originElement = originElementList.find(originEl => originEl.id === el.id) as PPTImageElement | PPTShapeElement\n return {\n ...el,\n width: originElement.width * widthScale,\n height: originElement.height * heightScale,\n left: currentMinX + (originElement.left - minX) * widthScale,\n top: currentMinY + (originElement.top - minY) * heightScale,\n }\n }\n return el\n })\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n if(startPageX === e.pageX && startPageY === e.pageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n scaleElement,\n scaleMultiElement,\n }\n}","import { Ref, computed } from 'vue'\nimport uniq from 'lodash/uniq'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n moveElement: (e: MouseEvent, element: PPTElement) => void,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const handleElementId = computed(() => store.state.handleElementId)\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n\n const selectElement = (e: MouseEvent, element: PPTElement, canMove = true) => {\n if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n\n // 如果被点击的元素处于未激活状态,则将他设置为激活元素(单选),或者加入到激活元素中(多选)\n if(!activeElementIdList.value.includes(element.id)) {\n let newActiveIdList: string[] = []\n\n if(ctrlOrShiftKeyActive.value) {\n newActiveIdList = [...activeElementIdList.value, element.id]\n }\n else newActiveIdList = [element.id]\n \n // 同时如果该元素是分组成员,需要将和他同组的元素一起激活\n if(element.groupId) {\n const groupMembersId: string[] = []\n elementList.value.forEach((el: PPTElement) => {\n if(el.groupId === element.groupId) groupMembersId.push(el.id)\n })\n newActiveIdList = [...newActiveIdList, ...groupMembersId]\n }\n\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, uniq(newActiveIdList))\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\n }\n\n // 如果被点击的元素已激活,且按下了多选按钮,则取消其激活状态(除非该元素或分组是最后的一个激活元素)\n else if(ctrlOrShiftKeyActive.value) {\n let newActiveIdList: string[] = []\n\n // 同时如果该元素是分组成员,需要将和他同组的元素一起取消\n if(element.groupId) {\n const groupMembersId: string[] = []\n elementList.value.forEach((el: PPTElement) => {\n if(el.groupId === element.groupId) groupMembersId.push(el.id)\n })\n newActiveIdList = activeElementIdList.value.filter(id => !groupMembersId.includes(id))\n }\n else {\n newActiveIdList = activeElementIdList.value.filter(id => id !== element.id)\n }\n\n if(newActiveIdList.length > 0) {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveIdList)\n }\n }\n\n // 如果被点击的元素已激活,且没有按下多选按钮,且该元素不是当前操作元素,则将其设置为当前操作元素\n else if(handleElementId.value !== element.id) {\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\n }\n\n // 如果被点击的元素是当前操作元素,且没有按下多选按钮,则该元素下次保持该状态再次被点击时,将被设置为多选元素中的激活成员\n else if(activeGroupElementId.value !== element.id) {\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n ;(e.target as HTMLElement).onmouseup = (e: MouseEvent) => {\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n if(startPageX === currentPageX && startPageY === currentPageY) {\n activeGroupElementId.value = element.id\n ;(e.target as HTMLElement).onmouseup = null\n }\n }\n }\n\n if(canMove) moveElement(e, element)\n }\n\n const selectAllElement = () => {\n const unlockedElements = elementList.value.filter(el => !el.lock)\n const newActiveElementIdList = unlockedElements.map(el => el.id)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\n }\n\n return {\n selectElement,\n selectAllElement,\n }\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { AlignmentLineProps } from '@/types/edit'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n alignmentLines: Ref,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const dragElement = (e: MouseEvent, element: PPTElement) => {\n if(!activeElementIdList.value.includes(element.id)) return\n let isMouseDown = true\n\n // 可视范围宽高,用于边缘对齐吸附\n const edgeWidth = VIEWPORT_SIZE\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\n const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))\n\n const sorptionRange = 5\n const elOriginLeft = element.left\n const elOriginTop = element.top\n const elOriginWidth = element.width\n const elOriginHeight = ('height' in element && element.height) ? element.height : 0\n const elOriginRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n let isMisoperation: boolean | null = null\n\n const isActiveGroupElement = element.id === activeGroupElementId.value\n\n // 收集对齐参考线\n // 包括页面内出被操作元素以外的所有元素在页面内水平和垂直方向的范围和中心位置、页面边界和水平和垂直的中心位置\n let horizontalLines: AlignLine[] = []\n let verticalLines: AlignLine[] = []\n\n // 元素在页面内水平和垂直方向的范围和中心位置(需要特殊计算线条和被旋转的元素)\n for(const el of elementList.value) {\n if(el.type === 'line') continue\n if(isActiveGroupElement && el.id === element.id) continue\n if(!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\n\n let left, top, width, height\n if('rotate' in el && el.rotate) {\n const { xRange, yRange } = getRectRotatedRange({\n left: el.left,\n top: el.top,\n width: el.width,\n height: el.height,\n rotate: el.rotate,\n })\n left = xRange[0]\n top = yRange[0]\n width = xRange[1] - xRange[0]\n height = yRange[1] - yRange[0]\n }\n else {\n left = el.left\n top = el.top\n width = el.width\n height = el.height\n }\n \n const right = left + width\n const bottom = top + height\n const centerX = top + height / 2\n const centerY = left + width / 2\n\n const topLine: AlignLine = { value: top, range: [left, right] }\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\n const horizontalCenterLine: AlignLine = { value: centerX, range: [left, right] }\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\n const verticalCenterLine: AlignLine = { value: centerY, range: [top, bottom] }\n\n horizontalLines.push(topLine, bottomLine, horizontalCenterLine)\n verticalLines.push(leftLine, rightLine, verticalCenterLine)\n }\n\n // 页面边界、水平和垂直的中心位置\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\n\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\n \n // 参考线去重\n horizontalLines = uniqAlignLines(horizontalLines)\n verticalLines = uniqAlignLines(verticalLines)\n\n document.onmousemove = e => {\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对于鼠标第一次滑动距离过小的操作判定为误操作\n // 这里仅在误操作标记未被赋值(null,第一次触发移动),以及被标记为误操作时(true,当前处于误操作范围,但可能会脱离该范围转变成正常操作),才会去计算\n // 已经被标记为非误操作时(false),不需要再次计算(因为不可能从非误操作转变成误操作)\n if(isMisoperation !== false) {\n isMisoperation = Math.abs(startPageX - currentPageX) < sorptionRange && \n Math.abs(startPageY - currentPageY) < sorptionRange\n }\n if(!isMouseDown || isMisoperation) return\n\n // 鼠标按下后移动的距离\n const moveX = (currentPageX - startPageX) / canvasScale.value\n const moveY = (currentPageY - startPageY) / canvasScale.value\n\n // 被操作元素需要移动到的位置\n let targetLeft = elOriginLeft + moveX\n let targetTop = elOriginTop + moveY\n\n // 计算被操作元素在页面中的范围(用于吸附对齐)\n // 需要区分计算:多选状态、线条、被旋转的元素\n // 注意这里需要用元素的原始信息结合移动信息来计算\n let targetMinX: number, targetMaxX: number, targetMinY: number, targetMaxY: number\n\n if(activeElementIdList.value.length === 1 || isActiveGroupElement) {\n if(elOriginRotate) {\n const { xRange, yRange } = getRectRotatedRange({\n left: targetLeft,\n top: targetTop,\n width: elOriginWidth,\n height: elOriginHeight,\n rotate: elOriginRotate,\n })\n targetMinX = xRange[0]\n targetMaxX = xRange[1]\n targetMinY = yRange[0]\n targetMaxY = yRange[1]\n }\n else if(element.type === 'line') {\n targetMinX = targetLeft\n targetMaxX = targetLeft + Math.max(element.start[0], element.end[0])\n targetMinY = targetTop\n targetMaxY = targetTop + Math.max(element.start[1], element.end[1])\n }\n else {\n targetMinX = targetLeft\n targetMaxX = targetLeft + elOriginWidth\n targetMinY = targetTop\n targetMaxY = targetTop + elOriginHeight\n }\n }\n else {\n const leftValues = []\n const topValues = []\n const rightValues = []\n const bottomValues = []\n \n for(let i = 0; i < originActiveElementList.length; i++) {\n const element = originActiveElementList[i]\n const left = element.left + moveX\n const top = element.top + moveY\n const width = element.width\n const height = ('height' in element && element.height) ? element.height : 0\n const rotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n\n if('rotate' in element && element.rotate) {\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\n leftValues.push(xRange[0])\n topValues.push(yRange[0])\n rightValues.push(xRange[1])\n bottomValues.push(yRange[1])\n }\n else if(element.type === 'line') {\n leftValues.push(left)\n topValues.push(top)\n rightValues.push(left + Math.max(element.start[0], element.end[0]))\n bottomValues.push(top + Math.max(element.start[1], element.end[1]))\n }\n else {\n leftValues.push(left)\n topValues.push(top)\n rightValues.push(left + width)\n bottomValues.push(top + height)\n }\n }\n\n targetMinX = Math.min(...leftValues)\n targetMaxX = Math.max(...rightValues)\n targetMinY = Math.min(...topValues)\n targetMaxY = Math.max(...bottomValues)\n }\n \n const targetCenterX = targetMinX + (targetMaxX - targetMinX) / 2\n const targetCenterY = targetMinY + (targetMaxY - targetMinY) / 2\n\n // 根据收集到的参考线,分别执行垂直和水平两个方向的对齐吸附\n const _alignmentLines: AlignmentLineProps[] = []\n let isVerticalAdsorbed = false\n let isHorizontalAdsorbed = false\n for(let i = 0; i < horizontalLines.length; i++) {\n const { value, range } = horizontalLines[i]\n const min = Math.min(...range, targetMinX, targetMaxX)\n const max = Math.max(...range, targetMinX, targetMaxX)\n \n if(Math.abs(targetMinY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetMinY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n if(Math.abs(targetMaxY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetMaxY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n if(Math.abs(targetCenterY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetCenterY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n }\n for(let i = 0; i < verticalLines.length; i++) {\n const { value, range } = verticalLines[i]\n const min = Math.min(...range, targetMinY, targetMaxY)\n const max = Math.max(...range, targetMinY, targetMaxY)\n\n if(Math.abs(targetMinX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetMinX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n if(Math.abs(targetMaxX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetMaxX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n if(Math.abs(targetCenterX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetCenterX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n }\n alignmentLines.value = _alignmentLines\n \n // 非多选,或者当前操作的元素时激活的组合元素\n if(activeElementIdList.value.length === 1 || isActiveGroupElement) {\n elementList.value = elementList.value.map(el => {\n return el.id === element.id ? { ...el, left: targetLeft, top: targetTop } : el\n })\n }\n\n // 修改元素位置,如果需要修改位置的元素不是被操作的元素(例如多选下的操作)\n // 那么其他非操作元素要移动的位置通过操作元素的移动偏移量计算\n else {\n const handleElement = elementList.value.find(el => el.id === element.id)\n if(!handleElement) return\n\n elementList.value = elementList.value.map(el => {\n if(activeElementIdList.value.includes(el.id)) {\n if(el.id === element.id) {\n return {\n ...el,\n left: targetLeft,\n top: targetTop,\n }\n }\n return {\n ...el,\n left: el.left + (targetLeft - handleElement.left),\n top: el.top + (targetTop - handleElement.top),\n }\n }\n return el\n })\n }\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n alignmentLines.value = []\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对比初始位置,没有实际的位移不更新数据\n if(startPageX === currentPageX && startPageY === currentPageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n dragElement,\n }\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTLineElement } from '@/types/slides'\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\ninterface AdsorptionPoint {\n x: number;\n y: number;\n}\n\nexport default (elementList: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {\n let isMouseDown = true\n\n const sorptionRange = 8\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const adsorptionPoints: AdsorptionPoint[] = []\n\n // 获取全部非线条且未旋转元素的8个点作为吸附点\n for(let i = 0; i < elementList.value.length; i++) {\n const _element = elementList.value[i]\n if(_element.type === 'line' || ('rotate' in _element && _element.rotate)) continue\n\n const left = _element.left\n const top = _element.top\n const width = _element.width\n const height = _element.height\n \n const right = left + width\n const bottom = top + height\n const centerX = top + height / 2\n const centerY = left + width / 2\n\n const topPoint = { x: centerY, y: top }\n const bottomPoint = { x: centerY, y: bottom }\n const leftPoint = { x: left, y: centerX }\n const rightPoint = { x: right, y: centerX }\n\n const leftTopPoint = { x: left, y: top }\n const rightTopPoint = { x: right, y: top }\n const leftBottomPoint = { x: left, y: bottom }\n const rightBottomPoint = { x: right, y: bottom }\n\n adsorptionPoints.push(\n topPoint,\n bottomPoint,\n leftPoint,\n rightPoint,\n leftTopPoint,\n rightTopPoint,\n leftBottomPoint,\n rightBottomPoint,\n )\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 鼠标按下后移动的距离\n const moveX = (currentPageX - startPageX) / canvasScale.value\n const moveY = (currentPageY - startPageY) / canvasScale.value\n \n // 线条两个端点(起点和终点)基于编辑区域的位置\n let startX = element.left + element.start[0]\n let startY = element.top + element.start[1]\n let endX = element.left + element.end[0]\n let endY = element.top + element.end[1]\n\n // 根据拖拽的点,选择修改起点或终点的位置\n // 两点在水平和垂直方向上有对齐吸附\n // 靠近其他元素的吸附点有对齐吸附\n if(command === OperateLineHandlers.START) {\n startX = startX + moveX\n startY = startY + moveY\n\n if(Math.abs(startX - endX) < sorptionRange) startX = endX\n if(Math.abs(startY - endY) < sorptionRange) startY = endY\n\n for(const adsorptionPoint of adsorptionPoints) {\n const { x, y } = adsorptionPoint\n if(Math.abs(x - startX) < sorptionRange && Math.abs(y - startY) < sorptionRange) {\n startX = x\n startY = y\n break\n }\n }\n }\n else {\n endX = endX + moveX\n endY = endY + moveY\n\n if(Math.abs(startX - endX) < sorptionRange) endX = startX\n if(Math.abs(startY - endY) < sorptionRange) endY = startY\n\n for(const adsorptionPoint of adsorptionPoints) {\n const { x, y } = adsorptionPoint\n if(Math.abs(x - endX) < sorptionRange && Math.abs(y - endY) < sorptionRange) {\n endX = x\n endY = y\n break\n }\n }\n }\n\n // 计算两个端点基于自身元素位置的坐标\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n const start: [number, number] = [0, 0]\n const end: [number, number] = [maxX - minX, maxY - minY]\n if(startX > endX) {\n start[0] = maxX - minX\n end[0] = 0\n }\n if(startY > endY) {\n start[1] = maxY - minY\n end[1] = 0\n }\n\n // 修改线条的位置和两点的坐标\n elementList.value = elementList.value.map(el => {\n if(el.id === element.id) {\n return {\n ...el,\n left: minX,\n top: minY,\n start: start,\n end: end,\n }\n }\n return el\n })\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对比原始鼠标位置,没有实际的位移不更新数据\n if(startPageX === currentPageX && startPageY === currentPageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n dragLineElement,\n }\n}","import { computed, Ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { CreateElementSelectionData, CreatingLineElement, CreatingShapeElement } from '@/types/edit'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default (viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const creatingElement = computed(() => store.state.creatingElement)\n\n const formatCreateSelection = (selectionData: CreateElementSelectionData) => {\n const { start, end } = selectionData\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const [startX, startY] = start\n const [endX, endY] = end\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const left = (minX - viewportRect.x) / canvasScale.value\n const top = (minY - viewportRect.y) / canvasScale.value\n const width = (maxX - minX) / canvasScale.value\n const height = (maxY - minY) / canvasScale.value\n\n return { left, top, width, height }\n }\n\n const formatCreateSelectionForLine = (selectionData: CreateElementSelectionData) => {\n const { start, end } = selectionData\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const [startX, startY] = start\n const [endX, endY] = end\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const left = (minX - viewportRect.x) / canvasScale.value\n const top = (minY - viewportRect.y) / canvasScale.value\n const width = (maxX - minX) / canvasScale.value\n const height = (maxY - minY) / canvasScale.value\n\n const _start: [number, number] = [\n startX === minX ? 0 : width,\n startY === minY ? 0 : height,\n ]\n const _end: [number, number] = [\n endX === minX ? 0 : width,\n endY === minY ? 0 : height,\n ]\n\n return {\n left,\n top,\n start: _start,\n end: _end,\n }\n }\n\n const { createTextElement, createShapeElement, createLineElement } = useCreateElement()\n\n const insertElementFromCreateSelection = (selectionData: CreateElementSelectionData) => {\n if(!creatingElement.value) return\n\n const type = creatingElement.value.type\n if(type === 'text') {\n const position = formatCreateSelection(selectionData)\n position && createTextElement(position)\n }\n else if(type === 'shape') {\n const position = formatCreateSelection(selectionData)\n position && createShapeElement(position, (creatingElement.value as CreatingShapeElement).data)\n }\n else if(type === 'line') {\n const position = formatCreateSelectionForLine(selectionData)\n position && createLineElement(position, (creatingElement.value as CreatingLineElement).data)\n }\n store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\n }\n\n return {\n insertElementFromCreateSelection,\n }\n}","\n\n","import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\n\nexport interface PPTElementShadow {\n h: number;\n v: number;\n blur: number;\n color: string;\n}\n\nexport const enum ElementTypes {\n TEXT = 'text',\n IMAGE = 'image',\n SHAPE = 'shape',\n LINE = 'line',\n CHART = 'chart',\n TABLE = 'table',\n}\n\nexport interface PPTElementOutline {\n style?: 'dashed' | 'solid';\n width?: number;\n color?: string;\n}\n\nexport interface PPTTextElement {\n type: 'text';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n content: string;\n rotate?: number;\n outline?: PPTElementOutline;\n fill?: string;\n lineHeight?: number;\n wordSpace?: number;\n opacity?: number;\n shadow?: PPTElementShadow;\n}\n\nexport interface ImageElementFilters {\n 'blur'?: string;\n 'brightness'?: string;\n 'contrast'?: string;\n 'grayscale'?: string;\n 'saturate'?: string;\n 'hue-rotate'?: string;\n 'opacity'?: string;\n}\nexport interface PPTImageElement {\n type: 'image';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n fixedRatio: boolean;\n src: string;\n rotate?: number;\n outline?: PPTElementOutline;\n filters?: ImageElementFilters;\n clip?: {\n range: [[number, number], [number, number]];\n shape: 'rect' | 'roundRect' | 'ellipse' | 'triangle' | 'pentagon' | 'rhombus' | 'star';\n };\n flip?: { x?: number; y?: number };\n shadow?: PPTElementShadow;\n}\n\nexport interface ShapeGradient {\n type: 'linear' | 'radial';\n color: [string, string];\n rotate: number;\n}\nexport interface PPTShapeElement {\n type: 'shape';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n viewBox: number;\n path: string;\n fixedRatio: boolean;\n fill: string;\n gradient?: ShapeGradient;\n rotate?: number;\n outline?: PPTElementOutline;\n opacity?: number;\n shadow?: PPTElementShadow;\n}\n\nexport interface PPTLineElement {\n type: 'line';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n start: [number, number];\n end: [number, number];\n width: number;\n style: string;\n color: string;\n points: [string, string];\n shadow?: PPTElementShadow;\n}\n\nexport type ChartType = 'bar' | 'line' | 'pie'\nexport interface ChartData {\n labels: string[];\n series: number[][];\n}\nexport interface PPTChartElement {\n type: 'chart';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n fill?: string;\n chartType: ChartType;\n data: ChartData;\n options?: ILineChartOptions & IBarChartOptions & IPieChartOptions;\n outline?: PPTElementOutline;\n themeColor: string;\n gridColor?: string;\n}\n\nexport interface TableCellStyle {\n bold?: boolean;\n em?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n color?: string;\n backcolor?: string;\n fontsize?: string;\n fontname?: string;\n align?: string;\n}\nexport interface TableCell {\n id: string;\n colspan: number;\n rowspan: number;\n text: string;\n style?: TableCellStyle;\n}\nexport interface TableTheme {\n color: string;\n rowHeader: boolean;\n rowFooter: boolean;\n colHeader: boolean;\n colFooter: boolean;\n} \nexport interface PPTTableElement {\n type: 'table';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n outline: PPTElementOutline;\n theme?: TableTheme;\n colWidths: number[];\n data: TableCell[][];\n}\n\nexport type PPTElement = PPTTextElement | PPTImageElement | PPTShapeElement | PPTLineElement | PPTChartElement | PPTTableElement\n\nexport interface PPTAnimation {\n elId: string;\n type: string;\n duration: number;\n}\n\nexport interface SlideBackground {\n type: 'solid' | 'image' | 'gradient';\n color?: string;\n image?: string;\n imageSize?: 'cover' | 'contain' | 'repeat' | 'initial';\n gradientType?: 'linear' | 'radial';\n gradientColor?: [string, string];\n gradientRotate?: number;\n}\n\nexport interface Slide {\n id: string;\n elements: PPTElement[];\n background?: SlideBackground;\n animations?: PPTAnimation[];\n turningMode?: 'no' | 'fade' | 'slideX' | 'slideY';\n}\n\nexport interface SlideTheme {\n backgroundColor: string;\n themeColor: string;\n fontColor: string;\n fontName: string;\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n // 获取组合元素层级范围(组合成员中的最大层级和最小层级)\n const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {\n const minIndex = elementList.findIndex(_element => _element.id === combineElementList[0].id)\n const maxIndex = elementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id)\n return { minIndex, maxIndex }\n }\n\n // 上移一层,返回移动后新的元素列表(下移一层逻辑类似)\n const moveUpElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n // 被操作的元素是组合元素成员\n if(element.groupId) {\n\n // 获取该组合元素全部成员,以及组合元素层级范围\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex, maxIndex } = getCombineElementIndexRange(elementList, combineElementList)\n\n // 无法移动(已经处在顶层)\n if(maxIndex === elementList.length - 1) return null\n\n // 该组合元素上一层的元素,以下简称为【元素next】\n const nextElement = copyOfElementList[maxIndex + 1]\n\n // 从元素列表中移除该组合元素全部成员\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n\n // 如果【元素next】也是组合元素成员(另一个组合,不是上面被移除的那一组,以下简称为【组合next】)\n // 需要获取【组合next】全部成员的长度,将上面移除的组合元素全部成员添加到【组合next】全部成员的上方\n if(nextElement.groupId) {\n const nextCombineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\n copyOfElementList.splice(minIndex + nextCombineElementList.length, 0, ...movedElementList)\n }\n\n // 如果【元素next】是单独的元素(非组合成员),将上面移除的组合元素全部成员添加到【元素next】上方\n else copyOfElementList.splice(minIndex + 1, 0, ...movedElementList)\n }\n\n // 被操作的元素是单独的元素(非组合成员)\n else {\n\n // 元素在元素列表中的层级\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n\n // 无法移动(已经处在顶层)\n if(elementIndex === elementList.length - 1) return null\n\n // 上一层的元素,以下简称为【元素next】\n const nextElement = copyOfElementList[elementIndex + 1]\n\n // 从元素列表中移除被操作的元素\n const movedElement = copyOfElementList.splice(elementIndex, 1)[0]\n\n // 如果【元素next】是组合元素成员\n // 需要获取该组合全部成员的长度,将上面移除的元素添加到该组合全部成员的上方\n if(nextElement.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\n copyOfElementList.splice(elementIndex + combineElementList.length, 0, movedElement)\n }\n\n // 如果【元素next】是单独的元素(非组合成员),将上面移除的元素添加到【元素next】上方\n else copyOfElementList.splice(elementIndex + 1, 0, movedElement)\n }\n\n return copyOfElementList\n }\n\n // 下移一层\n const moveDownElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n if(element.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex } = getCombineElementIndexRange(elementList, combineElementList)\n if(minIndex === 0) return null\n const prevElement = copyOfElementList[minIndex - 1]\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n if(prevElement.groupId) {\n const prevCombineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\n copyOfElementList.splice(minIndex - prevCombineElementList.length, 0, ...movedElementList)\n }\n else copyOfElementList.splice(minIndex - 1, 0, ...movedElementList)\n }\n\n else {\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n if(elementIndex === 0) return null\n const prevElement = copyOfElementList[elementIndex - 1]\n const movedElement = copyOfElementList.splice(elementIndex, 1)[0]\n if(prevElement.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\n copyOfElementList.splice(elementIndex - combineElementList.length, 0, movedElement)\n }\n else copyOfElementList.splice(elementIndex - 1, 0, movedElement)\n }\n\n return copyOfElementList\n }\n\n // 置顶层,返回移动后新的元素列表(置底层逻辑类似)\n const moveTopElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n // 被操作的元素是组合元素成员\n if(element.groupId) {\n\n // 获取该组合元素全部成员,以及组合元素层级范围\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex, maxIndex } = getCombineElementIndexRange(elementList, combineElementList)\n\n // 无法移动(已经处在顶层)\n if(maxIndex === elementList.length - 1) return null\n\n // 从元素列表中移除该组合元素全部成员,然后添加到元素列表最上方\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n copyOfElementList.push(...movedElementList)\n }\n\n // 被操作的元素是单独的元素(非组合成员)\n else {\n\n // 元素在元素列表中的层级\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n\n // 无法移动(已经处在顶层)\n if(elementIndex === elementList.length - 1) return null\n\n // 从元素列表中移除该元素,然后添加到元素列表最上方\n copyOfElementList.splice(elementIndex, 1)\n copyOfElementList.push(element)\n }\n\n return copyOfElementList\n }\n\n // 置底层\n const moveBottomElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n if(element.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex } = getCombineElementIndexRange(elementList, combineElementList)\n if(minIndex === 0) return null\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n copyOfElementList.unshift(...movedElementList)\n }\n\n else {\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n if(elementIndex === 0) return null\n copyOfElementList.splice(elementIndex, 1)\n copyOfElementList.unshift(element)\n }\n\n return copyOfElementList\n }\n\n const orderElement = (element: PPTElement, command: ElementOrderCommand) => {\n let newElementList = null\n \n if(command === ElementOrderCommands.UP) newElementList = moveUpElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.DOWN) newElementList = moveDownElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.TOP) newElementList = moveTopElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)\n\n if(!newElementList) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n return {\n orderElement,\n }\n}","export const enum ClipPathTypes {\n RECT = 'rect',\n ELLIPSE = 'ellipse',\n POLYGON = 'polygon',\n}\n\nexport const enum ClipPaths {\n RECT = 'rect',\n ROUNDRECT = 'roundRect',\n ELLIPSE = 'ellipse',\n TRIANGLE = 'triangle',\n PENTAGON = 'pentagon',\n RHOMBUS = 'rhombus',\n STAR = 'star',\n}\n\nexport const CLIPPATHS = {\n rect: {\n name: '矩形',\n type: ClipPathTypes.RECT,\n radius: '0',\n style: '',\n },\n rect2: {\n name: '矩形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 0 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L 0 ${height} Z`\n },\n },\n rect3: {\n name: '矩形3',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 20% 100%, 0% 80%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.8} Z`\n },\n },\n roundRect: {\n name: '圆角矩形',\n type: ClipPathTypes.RECT,\n radius: '10%',\n style: 'inset(0 0 0 0 round 10% 10% 10% 10%)',\n },\n ellipse: {\n name: '圆形',\n type: ClipPathTypes.ELLIPSE,\n style: 'ellipse(50% 50% at 50% 50%)',\n },\n triangle: {\n name: '三角形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 0% 100%, 100% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L 0 ${height} L ${width} ${height} Z`\n },\n },\n triangle2: {\n name: '三角形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 100%, 0% 0%, 100% 0%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} ${height} L 0 0 L ${width} 0 Z`\n },\n },\n triangle3: {\n name: '三角形3',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 0% 100%, 100% 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L 0 ${height} L ${width} ${height} Z`\n },\n },\n rhombus: {\n name: '菱形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L ${width} ${height * 0.5} L ${width * 0.5} ${height} L 0 ${height * 0.5} Z`\n },\n },\n hexagon: {\n name: '六边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.2} 0 L ${width * 0.8} 0 L ${width} ${height * 0.5} L ${width * 0.8} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.5} Z`\n },\n },\n pentagon: {\n name: '五边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L ${width} ${0.38 * height} L ${0.82 * width} ${height} L ${0.18 * width} ${height} L 0 ${0.38 * height} Z`\n },\n },\n parallelogram: {\n name: '平行四边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(30% 0%, 100% 0%, 70% 100%, 0% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.3} 0 L ${width} 0 L ${width * 0.7} ${height} L 0 ${height} Z`\n },\n },\n parallelogram2: {\n name: '平行四边形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(30% 100%, 100% 100%, 70% 0%, 0% 0%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.3} ${height} L ${width} ${height} L ${width * 0.7} 0 L 0 0 Z`\n },\n },\n trapezoid: {\n name: '梯形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(25% 0%, 75% 0%, 100% 100%, 0% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.25} 0 L ${width * 0.75} 0 L ${width} ${height} L 0 ${height} Z`\n },\n },\n trapezoid2: {\n name: '梯形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 100% 0%, 75% 100%, 25% 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width} 0 L ${width * 0.75} ${height} L ${width * 0.25} ${height} Z`\n },\n },\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\nimport { getElementListRange } from '@/utils/element'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\n\nexport default () => {\n const store = useStore()\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const alignElementToCanvas = (command: ElementAlignCommand) => {\n const viewportWidth = VIEWPORT_SIZE\n const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\n \n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n for(const element of newElementList) {\n if(!activeElementIdList.value.includes(element.id)) continue\n \n if(command === ElementAlignCommands.TOP) {\n const offsetY = minY - 0\n element.top = element.top - offsetY \n }\n else if(command === ElementAlignCommands.VERTICAL) {\n const offsetY = minY + (maxY - minY) / 2 - viewportHeight / 2\n element.top = element.top - offsetY \n }\n else if(command === ElementAlignCommands.BOTTOM) {\n const offsetY = maxY - viewportHeight\n element.top = element.top - offsetY \n }\n \n else if(command === ElementAlignCommands.LEFT) {\n const offsetX = minX - 0\n element.left = element.left - offsetX \n }\n else if(command === ElementAlignCommands.HORIZONTAL) {\n const offsetX = minX + (maxX - minX) / 2 - viewportWidth / 2\n element.left = element.left - offsetX \n }\n else if(command === ElementAlignCommands.RIGHT) {\n const offsetX = maxX - viewportWidth\n element.left = element.left - offsetX \n }\n }\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n }\n\n return {\n alignElementToCanvas,\n }\n}","\n\n\n\n\n","import { ref, Ref, watchEffect } from 'vue'\nimport { PPTElementShadow } from '@/types/slides'\n\nexport default (shadow: Ref) => {\n const shadowStyle = ref('')\n\n watchEffect(() => {\n if(shadow.value) {\n const { h, v, blur, color } = shadow.value\n shadowStyle.value = `${h}px ${v}px ${blur}px ${color}`\n }\n else shadowStyle.value = ''\n })\n\n return {\n shadowStyle,\n }\n}","\n\n\n\n","import { computed, Ref } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\n\nexport default (outline: Ref) => {\n const outlineWidth = computed(() => (outline.value && outline.value.width !== undefined) ? outline.value.width : 0)\n const outlineStyle = computed(() => (outline.value && outline.value.style !== undefined) ? outline.value.style : 'solid')\n const outlineColor = computed(() => (outline.value && outline.value.color !== undefined) ? outline.value.color : '#d14424')\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n}","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-rect-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n radius: {\n type: String,\n default: '0',\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImageRectOutline.vue?vue&type=template&id=4efc595a&scoped=true\"\nimport script from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageRectOutline.vue?vue&type=style&index=0&id=4efc595a&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4efc595a\"\n\nexport default script","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-ellipse-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImageEllipseOutline.vue?vue&type=template&id=4a286c0d&scoped=true\"\nimport script from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageEllipseOutline.vue?vue&type=style&index=0&id=4a286c0d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4a286c0d\"\n\nexport default script","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-polygon-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n createPath: {\n type: Function,\n required: true,\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImagePolygonOutline.vue?vue&type=template&id=0a37b709&scoped=true\"\nimport script from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImagePolygonOutline.vue?vue&type=style&index=0&id=0a37b709&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0a37b709\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'\nimport { useStore } from '@/store'\nimport { KEYS } from '@/configs/hotkey'\nimport { ImageClipData, ImageClipDataRange, ImageClipedEmitData } from '@/types/edit'\n\ntype ScaleClipRangeType = 't-l' | 't-r' | 'b-l' | 'b-r'\n\nexport default defineComponent({\n name: 'image-clip-handler',\n props: {\n src: {\n type: String,\n required: true,\n },\n clipData: {\n type: Object as PropType,\n },\n clipPath: {\n type: String,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n top: {\n type: Number,\n required: true,\n },\n left: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const topImgWrapperPosition = reactive({\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n })\n const clipWrapperPositionStyle = reactive({\n top: '0',\n left: '0',\n })\n const isSettingClipRange = ref(false)\n const currentRange = ref(null)\n\n const getClipDataTransformInfo = () => {\n const [start, end] = props.clipData ? props.clipData.range : [[0, 0], [100, 100]]\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return { widthScale, heightScale, left, top }\n }\n\n const imgPosition = computed(() => {\n const { widthScale, heightScale, left, top } = getClipDataTransformInfo()\n return {\n left: -left,\n top: -top,\n width: 100 / widthScale,\n height: 100 / heightScale,\n }\n })\n\n const bottomImgPositionStyle = computed(() => {\n return {\n top: imgPosition.value.top + '%',\n left: imgPosition.value.left + '%',\n width: imgPosition.value.width + '%',\n height: imgPosition.value.height + '%',\n }\n })\n\n const topImgWrapperPositionStyle = computed(() => {\n return {\n top: topImgWrapperPosition.top + '%',\n left: topImgWrapperPosition.left + '%',\n width: topImgWrapperPosition.width + '%',\n height: topImgWrapperPosition.height + '%',\n }\n })\n\n const topImgPositionStyle = computed(() => {\n const bottomWidth = imgPosition.value.width\n const bottomHeight = imgPosition.value.height\n \n const topLeft = topImgWrapperPosition.left\n const topTop = topImgWrapperPosition.top\n const topWidth = topImgWrapperPosition.width\n const topHeight = topImgWrapperPosition.height\n \n return {\n left: -topLeft * (100 / topWidth) + '%',\n top: -topTop * (100 / topHeight) + '%',\n width: bottomWidth / topWidth * 100 + '%',\n height: bottomHeight / topHeight * 100 + '%',\n }\n })\n\n const initClipPosition = () => {\n const { left, top } = getClipDataTransformInfo()\n topImgWrapperPosition.left = left\n topImgWrapperPosition.top = top\n topImgWrapperPosition.width = 100\n topImgWrapperPosition.height = 100\n \n clipWrapperPositionStyle.top = -top + '%'\n clipWrapperPositionStyle.left = -left + '%'\n }\n\n const handleClip = () => {\n if(isSettingClipRange.value) return\n\n if(!currentRange.value) {\n emit('clip', null)\n return\n }\n\n const { left, top } = getClipDataTransformInfo()\n\n const position = {\n left: (topImgWrapperPosition.left - left) / 100 * props.width,\n top: (topImgWrapperPosition.top - top) / 100 * props.height,\n width: (topImgWrapperPosition.width - 100) / 100 * props.width,\n height: (topImgWrapperPosition.height - 100) / 100 * props.height,\n }\n\n const clipedEmitData: ImageClipedEmitData = {\n range: currentRange.value,\n position,\n }\n emit('clip', clipedEmitData)\n }\n\n const keyboardClip = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(key === KEYS.ENTER) handleClip()\n }\n\n onMounted(() => {\n initClipPosition()\n document.addEventListener('keydown', keyboardClip)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keyboardClip)\n })\n\n const getRange = () => {\n const retPosition = {\n left: parseInt(topImgPositionStyle.value.left),\n top: parseInt(topImgPositionStyle.value.top),\n width: parseInt(topImgPositionStyle.value.width),\n height: parseInt(topImgPositionStyle.value.height),\n }\n\n const widthScale = 100 / retPosition.width\n const heightScale = 100 / retPosition.height\n\n const start: [number, number] = [\n -retPosition.left * widthScale,\n -retPosition.top * heightScale,\n ]\n const end: [number, number] = [\n widthScale * 100 + start[0],\n heightScale * 100 + start[1],\n ]\n\n currentRange.value = [start, end]\n }\n\n const moveClipRange = (e: MouseEvent) => {\n isSettingClipRange.value = true\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n const bottomPosition = imgPosition.value\n const originPositopn = {\n left: topImgWrapperPosition.left,\n top: topImgWrapperPosition.top,\n width: topImgWrapperPosition.width,\n height: topImgWrapperPosition.height,\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\n const moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\n\n let targetLeft = originPositopn.left + moveX\n let targetTop = originPositopn.top + moveY\n\n // 范围限制\n if(targetLeft < 0) targetLeft = 0\n else if(targetLeft + originPositopn.width > bottomPosition.width) {\n targetLeft = bottomPosition.width - originPositopn.width\n }\n if(targetTop < 0) targetTop = 0\n else if(targetTop + originPositopn.height > bottomPosition.height) {\n targetTop = bottomPosition.height - originPositopn.height\n }\n \n topImgWrapperPosition.left = targetLeft\n topImgWrapperPosition.top = targetTop\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n getRange()\n\n setTimeout(() => {\n isSettingClipRange.value = false\n }, 0)\n }\n }\n\n const scaleClipRange = (e: MouseEvent, type: ScaleClipRangeType) => {\n isSettingClipRange.value = true\n let isMouseDown = true\n\n const minWidth = 50 / props.width * 100\n const minHeight = 50 / props.height * 100\n \n const startPageX = e.pageX\n const startPageY = e.pageY\n const bottomPosition = imgPosition.value\n const originPositopn = {\n left: topImgWrapperPosition.left,\n top: topImgWrapperPosition.top,\n width: topImgWrapperPosition.width,\n height: topImgWrapperPosition.height,\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n let moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\n let moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\n\n let targetLeft, targetTop, targetWidth, targetHeight\n\n // 根据不同缩放点,计算目标大小和位置,同时做大小和范围的限制\n if(type === 't-l') {\n if(originPositopn.left + moveX < 0) {\n moveX = -originPositopn.left\n }\n if(originPositopn.top + moveY < 0) {\n moveY = -originPositopn.top\n }\n if(originPositopn.width - moveX < minWidth) {\n moveX = originPositopn.width - minWidth\n }\n if(originPositopn.height - moveY < minHeight) {\n moveY = originPositopn.height - minHeight\n }\n targetWidth = originPositopn.width - moveX\n targetHeight = originPositopn.height - moveY\n targetLeft = originPositopn.left + moveX\n targetTop = originPositopn.top + moveY\n }\n else if(type === 't-r') {\n if(originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\n }\n if(originPositopn.top + moveY < 0) {\n moveY = -originPositopn.top\n }\n if(originPositopn.width + moveX < minWidth) {\n moveX = minWidth - originPositopn.width\n }\n if(originPositopn.height - moveY < minHeight) {\n moveY = originPositopn.height - minHeight\n }\n targetWidth = originPositopn.width + moveX\n targetHeight = originPositopn.height - moveY\n targetLeft = originPositopn.left\n targetTop = originPositopn.top + moveY\n }\n else if(type === 'b-l') {\n if(originPositopn.left + moveX < 0) {\n moveX = -originPositopn.left\n }\n if(originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\n }\n if(originPositopn.width - moveX < minWidth) {\n moveX = originPositopn.width - minWidth\n }\n if(originPositopn.height + moveY < minHeight) {\n moveY = minHeight - originPositopn.height\n }\n targetWidth = originPositopn.width - moveX\n targetHeight = originPositopn.height + moveY\n targetLeft = originPositopn.left + moveX\n targetTop = originPositopn.top\n }\n else {\n if(originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\n }\n if(originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\n }\n if(originPositopn.width + moveX < minWidth) {\n moveX = minWidth - originPositopn.width\n }\n if(originPositopn.height + moveY < minHeight) {\n moveY = minHeight - originPositopn.height\n }\n targetWidth = originPositopn.width + moveX\n targetHeight = originPositopn.height + moveY\n targetLeft = originPositopn.left\n targetTop = originPositopn.top\n }\n \n topImgWrapperPosition.left = targetLeft\n topImgWrapperPosition.top = targetTop\n topImgWrapperPosition.width = targetWidth\n topImgWrapperPosition.height = targetHeight\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n getRange()\n\n setTimeout(() => isSettingClipRange.value = false, 0)\n }\n }\n\n return {\n clipWrapperPositionStyle,\n bottomImgPositionStyle,\n topImgWrapperPositionStyle,\n topImgPositionStyle,\n handleClip,\n moveClipRange,\n scaleClipRange,\n }\n },\n})\n","import { render } from \"./ImageClipHandler.vue?vue&type=template&id=1e41275c&scoped=true\"\nimport script from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageClipHandler.vue?vue&type=style&index=0&id=1e41275c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1e41275c\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTImageElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport ImageRectOutline from './ImageRectOutline.vue'\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\nimport ImageClipHandler from './ImageClipHandler.vue'\nimport { ImageClipedEmitData } from '@/types/edit'\n\nexport default defineComponent({\n name: 'editable-element-image',\n components: {\n ImageRectOutline,\n ImageEllipseOutline,\n ImagePolygonOutline,\n ImageClipHandler,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\n\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n props.selectElement(e, props.elementInfo)\n }\n const clipShape = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect\n const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT\n\n return CLIPPATHS[shape]\n })\n\n const imgPosition = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) {\n return {\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n }\n }\n\n const [start, end] = props.elementInfo.clip.range\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return {\n left: -left + '%',\n top: -top + '%',\n width: 100 / widthScale + '%',\n height: 100 / heightScale + '%',\n }\n })\n\n const filter = computed(() => {\n if(!props.elementInfo.filters) return ''\n let filter = ''\n for(const key of Object.keys(props.elementInfo.filters)) {\n filter += `${key}(${props.elementInfo.filters[key]}) `\n }\n return filter\n })\n\n const flip = computed(() => {\n if(!props.elementInfo.flip) return ''\n const { x, y } = props.elementInfo.flip\n if(x && y) return `rotateX(${x}deg) rotateY(${y}deg)`\n else if(x) return `rotateX(${x}deg)`\n else if(y) return `rotateY(${y}deg)`\n return ''\n })\n\n const clip = (data: ImageClipedEmitData) => {\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, '')\n \n if(!data) return\n\n const { range, position } = data\n const originClip = props.elementInfo.clip || {}\n \n const _props = {\n clip: { ...originClip, range },\n left: props.elementInfo.left + position.left,\n top: props.elementInfo.top + position.top,\n width: props.elementInfo.width + position.width,\n height: props.elementInfo.height + position.height,\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: props.elementInfo.id, props: _props })\n }\n\n return {\n isCliping,\n clip,\n clipingImageElementId,\n shadowStyle,\n handleSelectElement,\n clipShape,\n imgPosition,\n filter,\n flip,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=c9d8ae3c&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=c9d8ae3c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-c9d8ae3c\"\n\nexport default script","\n\n\n\n\n","import { splitListItem, liftListItem, sinkListItem } from 'prosemirror-schema-list'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { undo, redo } from 'prosemirror-history'\r\nimport { undoInputRule } from 'prosemirror-inputrules'\r\nimport {\r\n toggleMark,\r\n selectParentNode,\r\n joinUp,\r\n joinDown,\r\n Command,\r\n} from 'prosemirror-commands'\r\n\r\nexport const buildKeymap = (schema: Schema) => {\r\n const keys = {}\r\n const bind = (key: string, cmd: Command) => keys[key] = cmd\r\n\r\n bind('Alt-ArrowUp', joinUp)\r\n bind('Alt-ArrowDown', joinDown)\r\n bind('Ctrl-z', undo)\r\n bind('Ctrl-y', redo)\r\n bind('Backspace', undoInputRule)\r\n bind('Escape', selectParentNode)\r\n bind('Ctrl-b', toggleMark(schema.marks.strong))\r\n bind('Ctrl-i', toggleMark(schema.marks.em))\r\n bind('Ctrl-u', toggleMark(schema.marks.underline))\r\n bind('Ctrl-d', toggleMark(schema.marks.strikethrough))\r\n\r\n bind('Enter', splitListItem(schema.nodes.list_item))\r\n bind('Mod-[', liftListItem(schema.nodes.list_item))\r\n bind('Mod-]', sinkListItem(schema.nodes.list_item))\r\n\r\n return keys\r\n}","import { NodeType, Schema } from 'prosemirror-model'\r\nimport {\r\n inputRules,\r\n wrappingInputRule,\r\n textblockTypeInputRule,\r\n smartQuotes,\r\n emDash,\r\n ellipsis,\r\n} from 'prosemirror-inputrules'\r\n\r\nconst blockQuoteRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*>\\s$/, nodeType)\r\n\r\nconst orderedListRule = (nodeType: NodeType) => (\r\n wrappingInputRule(\r\n /^(\\d+)\\.\\s$/, \r\n nodeType, \r\n match => ({order: +match[1]}),\r\n (match, node) => node.childCount + node.attrs.order === +match[1],\r\n )\r\n)\r\n\r\nconst bulletListRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*([-+*])\\s$/, nodeType)\r\n\r\nconst codeBlockRule = (nodeType: NodeType) => textblockTypeInputRule(/^```$/, nodeType)\r\n\r\nexport const buildInputRules = (schema: Schema) => {\r\n const rules = [\r\n ...smartQuotes,\r\n ellipsis,\r\n emDash,\r\n ]\r\n rules.push(blockQuoteRule(schema.nodes.blockquote))\r\n rules.push(orderedListRule(schema.nodes.ordered_list))\r\n rules.push(bulletListRule(schema.nodes.bullet_list))\r\n rules.push(codeBlockRule(schema.nodes.code_block))\r\n\r\n return inputRules({ rules })\r\n}","import { keymap } from 'prosemirror-keymap'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { history } from 'prosemirror-history'\r\nimport { baseKeymap } from 'prosemirror-commands'\r\nimport { dropCursor } from 'prosemirror-dropcursor'\r\nimport { gapCursor } from 'prosemirror-gapcursor'\r\n\r\nimport { buildKeymap } from './keymap'\r\nimport { buildInputRules } from './inputrules'\r\n\r\nexport const buildPlugins = (schema: Schema) => {\r\n return [\r\n buildInputRules(schema),\r\n keymap(buildKeymap(schema)),\r\n keymap(baseKeymap),\r\n dropCursor(),\r\n gapCursor(),\r\n history(),\r\n ]\r\n}","import { nodes } from 'prosemirror-schema-basic'\r\nimport { Node, NodeSpec } from 'prosemirror-model'\r\nimport { orderedList, bulletList, listItem } from 'prosemirror-schema-list'\r\n\r\nconst _orderedList: NodeSpec = {\r\n ...orderedList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _bulletList: NodeSpec = {\r\n ...bulletList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _listItem: NodeSpec = {\r\n ...listItem,\r\n content: 'paragraph block*',\r\n group: 'block',\r\n}\r\n\r\nconst paragraph: NodeSpec = {\r\n attrs: {\r\n align: {\r\n default: '',\r\n },\r\n },\r\n content: 'inline*',\r\n group: 'block',\r\n parseDOM: [\r\n {\r\n tag: 'p',\r\n getAttrs: dom => {\r\n const { textAlign } = (dom as HTMLElement).style\r\n let align = (dom as HTMLElement).getAttribute('align') || textAlign || ''\r\n align = /(left|right|center|justify)/.test(align) ? align : ''\r\n \r\n return { align }\r\n }\r\n }\r\n ],\r\n toDOM: (node: Node) => {\r\n const { align } = node.attrs\r\n let style = ''\r\n if(align && align !== 'left') style += `text-align: ${align};`\r\n\r\n return ['p', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...nodes,\r\n 'ordered_list': _orderedList,\r\n 'bullet_list': _bulletList,\r\n 'list_item': _listItem,\r\n paragraph,\r\n}\r\n","import { marks } from 'prosemirror-schema-basic'\r\nimport { MarkSpec } from 'prosemirror-model'\r\n\r\nconst subscript: MarkSpec = {\r\n excludes: 'subscript',\r\n parseDOM: [\r\n { tag: 'sub' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'sub' && null\r\n },\r\n ],\r\n toDOM: () => ['sub', 0],\r\n}\r\n\r\nconst superscript: MarkSpec = {\r\n excludes: 'superscript',\r\n parseDOM: [\r\n { tag: 'sup' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'super' && null\r\n },\r\n ],\r\n toDOM: () => ['sup', 0],\r\n}\r\n\r\nconst strikethrough: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'strike' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration-line: line-through' }, 0],\r\n}\r\n\r\nconst underline: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'u' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration: underline' }, 0],\r\n}\r\n\r\nconst forecolor: MarkSpec = {\r\n attrs: {\r\n color: {},\r\n },\r\n parseDOM: [\r\n {\r\n style: 'color',\r\n getAttrs: color => color ? { color } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { color } = mark.attrs\r\n let style = ''\r\n if(color) style += `color: ${color};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst backcolor: MarkSpec = {\r\n attrs: {\r\n backcolor: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n tag: 'span[style*=background-color]',\r\n getAttrs: backcolor => backcolor ? { backcolor } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { backcolor } = mark.attrs\r\n let style = ''\r\n if(backcolor) style += `background-color: ${backcolor};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontsize: MarkSpec = {\r\n attrs: {\r\n fontsize: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-size',\r\n getAttrs: fontsize => fontsize ? { fontsize } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontsize } = mark.attrs\r\n let style = ''\r\n if(fontsize) style += `font-size: ${fontsize}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontname: MarkSpec = {\r\n attrs: {\r\n fontname: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-family',\r\n getAttrs: fontname => {\r\n return { fontname: fontname && typeof fontname === 'string' ? fontname.replace(/[\\\"\\']/g, '') : '' }\r\n }\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontname } = mark.attrs\r\n let style = ''\r\n if(fontname) style += `font-family: ${fontname}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...marks,\r\n subscript,\r\n superscript,\r\n strikethrough,\r\n underline,\r\n forecolor,\r\n backcolor,\r\n fontsize,\r\n fontname,\r\n}","import nodes from './nodes'\r\nimport marks from './marks'\r\n\r\nexport const schemaNodes = nodes\r\nexport const schemaMarks = marks\r\n","import { EditorState } from 'prosemirror-state'\nimport { EditorView } from 'prosemirror-view'\nimport { Schema, DOMParser } from 'prosemirror-model'\n\nimport { buildPlugins } from './plugins/index'\nimport { schemaNodes, schemaMarks } from './schema/index'\n\nconst schema = new Schema({\n nodes: schemaNodes,\n marks: schemaMarks,\n})\n\nconst createDocument = (content: string) => {\n const htmlString = `
${content}
`\n const parser = new window.DOMParser()\n const element = parser.parseFromString(htmlString, 'text/html').body.firstElementChild\n return DOMParser.fromSchema(schema).parse(element as Element)\n}\n\nexport const initProsemirrorEditor = (dom: Element, content: string, props = {}) => {\n return new EditorView(dom, {\n state: EditorState.create({\n doc: createDocument(content),\n plugins: buildPlugins(schema),\n }),\n ...props,\n })\n}","import { Node, NodeType, ResolvedPos } from 'prosemirror-model'\nimport { EditorState, Selection } from 'prosemirror-state'\nimport { EditorView } from 'prosemirror-view'\n\nconst equalNodeType = (nodeType: NodeType, node: Node) => {\n return Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1 || node.type === nodeType\n}\n\nconst findParentNodeClosestToPos = ($pos: ResolvedPos, predicate: (node: Node) => boolean) => {\n for(let i = $pos.depth; i > 0; i--) {\n const node = $pos.node(i)\n if(predicate(node)) {\n return {\n pos: i > 0 ? $pos.before(i) : 0,\n start: $pos.start(i),\n depth: i,\n node,\n }\n }\n }\n}\n\nexport const findParentNode = (predicate: (node: Node) => boolean) => {\n return (_ref: Selection) => findParentNodeClosestToPos(_ref.$from, predicate)\n}\n\nexport const findParentNodeOfType = (nodeType: NodeType) => {\n return (selection: Selection) => {\n return findParentNode((node: Node) => {\n return equalNodeType(nodeType, node)\n })(selection)\n }\n}\n\nexport const isActiveOfParentNodeType = (nodeType: string, state: EditorState) => {\n const node = state.schema.nodes[nodeType]\n return !!findParentNodeOfType(node)(state.selection)\n}\n\nexport const getMarkAttrs = (view: EditorView) => {\n const { selection, doc } = view.state\n const { from } = selection\n const node = doc.nodeAt(from)\n return node?.marks || []\n}\n\nexport const getAttrValue = (view: EditorView, markType: string, attr: string) => {\n const marks = getMarkAttrs(view)\n for(const mark of marks) {\n if(mark.type.name === markType && mark.attrs[attr]) return mark.attrs[attr]\n }\n return null\n}\n\nexport const isActiveMark = (view: EditorView, markType: string) => {\n const marks = getMarkAttrs(view)\n for(const mark of marks) {\n if(mark.type.name === markType) return true\n }\n return false\n}\n\nexport const getAttrValueInSelection = (view: EditorView, attr: string) => {\n const { selection, doc } = view.state\n const { from, to } = selection\n\n let keepChecking = true\n let value = ''\n doc.nodesBetween(from, to, node => {\n if(keepChecking && node.attrs[attr]) {\n keepChecking = false\n value = node.attrs[attr]\n }\n return keepChecking\n })\n return value\n}\n\nexport const getTextAttrs = (view: EditorView) => {\n const isBold = isActiveMark(view, 'strong')\n const isEm = isActiveMark(view, 'em')\n const isUnderline = isActiveMark(view, 'underline')\n const isStrikethrough = isActiveMark(view, 'strikethrough')\n const isSuperscript = isActiveMark(view, 'superscript')\n const isSubscript = isActiveMark(view, 'subscript')\n const isCode = isActiveMark(view, 'code')\n const color = getAttrValue(view, 'forecolor', 'color') || '#000'\n const backcolor = getAttrValue(view, 'backcolor', 'backcolor') || '#000'\n const fontsize = getAttrValue(view, 'fontsize', 'fontsize') || '12px'\n const fontname = getAttrValue(view, 'fontname', 'fontname') || '微软雅黑'\n const align = getAttrValueInSelection(view, 'align') || 'left'\n const isBulletList = isActiveOfParentNodeType('bullet_list', view.state)\n const isOrderedList = isActiveOfParentNodeType('ordered_list', view.state)\n const isBlockquote = isActiveOfParentNodeType('blockquote', view.state)\n\n return {\n bold: isBold,\n em: isEm,\n underline: isUnderline,\n strikethrough: isStrikethrough,\n superscript: isSuperscript,\n subscript: isSubscript,\n code: isCode,\n color: color,\n backcolor: backcolor,\n fontsize: fontsize,\n fontname: fontname,\n align: align,\n bulletList: isBulletList,\n orderedList: isOrderedList,\n blockquote: isBlockquote,\n }\n}\n\nexport type TextAttrs = ReturnType","import { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction } from 'prosemirror-state'\r\nimport { EditorView } from 'prosemirror-view'\r\n\r\nexport const setTextAlign = (tr: Transaction, schema: Schema, alignment: string) => {\r\n const { selection, doc } = tr\r\n if(!selection || !doc) return tr\r\n\r\n const { from, to } = selection\r\n const { nodes } = schema\r\n\r\n const blockquote = nodes.blockquote\r\n const listItem = nodes.list_item\r\n const paragraph = nodes.paragraph\r\n\r\n interface Task {\r\n node: Node;\r\n pos: number;\r\n nodeType: NodeType;\r\n }\r\n\r\n const tasks: Task[] = []\r\n alignment = alignment || ''\r\n\r\n const allowedNodeTypes = new Set([blockquote, listItem, paragraph])\r\n\r\n doc.nodesBetween(from, to, (node, pos) => {\r\n const nodeType = node.type\r\n const align = node.attrs.align || ''\r\n if(align !== alignment && allowedNodeTypes.has(nodeType)) {\r\n tasks.push({\r\n node,\r\n pos,\r\n nodeType,\r\n })\r\n }\r\n return true\r\n })\r\n\r\n if(!tasks.length) return tr\r\n\r\n tasks.forEach(task => {\r\n const { node, pos, nodeType } = task\r\n let { attrs } = node\r\n if(alignment) attrs = { ...attrs, align: alignment }\r\n else attrs = { ...attrs, align: null }\r\n tr = tr.setNodeMarkup(pos, nodeType, attrs, node.marks)\r\n })\r\n\r\n return tr\r\n}\r\n\r\nexport const alignmentCommand = (view: EditorView, alignment: string) => {\r\n const { state } = view\r\n const { schema, selection } = state\r\n const tr = setTextAlign(\r\n state.tr.setSelection(selection),\r\n schema,\r\n alignment,\r\n )\r\n view.dispatch(tr)\r\n}","import { wrapInList, liftListItem } from 'prosemirror-schema-list'\r\nimport { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction, EditorState } from 'prosemirror-state'\r\nimport { findParentNode } from '../utils'\r\n\r\nconst isList = (node: Node, schema: Schema) => {\r\n return (\r\n node.type === schema.nodes.bullet_list ||\r\n node.type === schema.nodes.ordered_list\r\n )\r\n}\r\n\r\nexport const toggleList = (listType: NodeType, itemType: NodeType) => {\r\n return (state: EditorState, dispatch: (tr: Transaction) => void) => {\r\n const { schema, selection } = state\r\n const { $from, $to } = selection\r\n const range = $from.blockRange($to)\r\n\r\n if(!range) return false\r\n\r\n const parentList = findParentNode((node: Node) => isList(node, schema))(selection)\r\n\r\n if(range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {\r\n if(parentList.node.type === listType) {\r\n return liftListItem(itemType)(state, dispatch)\r\n }\r\n\r\n if(isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {\r\n const { tr } = state\r\n tr.setNodeMarkup(parentList.pos, listType)\r\n\r\n if(dispatch) dispatch(tr)\r\n\r\n return false\r\n }\r\n }\r\n\r\n return wrapInList(listType)(state, dispatch)\r\n }\r\n}\r\n","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'element-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=59365834&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=59365834&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-59365834\"\n\nexport default script","\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport debounce from 'lodash/debounce'\nimport { MutationTypes, useStore } from '@/store'\nimport { EditorView } from 'prosemirror-view'\nimport { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'\nimport { PPTTextElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { initProsemirrorEditor } from '@/prosemirror/'\nimport { getTextAttrs } from '@/prosemirror/utils'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\nimport { alignmentCommand } from '@/prosemirror/commands/setTextAlign'\nimport { toggleList } from '@/prosemirror/commands/toggleList'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\n\ninterface CommandPayload {\n command: string;\n value?: string;\n}\n\nexport default defineComponent({\n name: 'editable-element-text',\n components: {\n ElementOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const elementRef = ref()\n\n const isScaling = ref(false)\n const realHeightCache = ref(-1)\n\n const scaleElementStateListener = (state: boolean) => {\n isScaling.value = state\n\n if(!state && realHeightCache.value !== -1) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeightCache.value },\n })\n realHeightCache.value = -1\n }\n }\n\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n onUnmounted(() => {\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n })\n\n const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {\n const contentRect = entries[0].contentRect\n if(!elementRef.value) return\n\n const realHeight = contentRect.height\n\n if(props.elementInfo.height !== realHeight) {\n if(!isScaling.value) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeight },\n })\n }\n else realHeightCache.value = realHeight\n }\n }\n const resizeObserver = new ResizeObserver(updateTextElementHeight)\n\n onMounted(() => {\n if(elementRef.value) resizeObserver.observe(elementRef.value)\n })\n onUnmounted(() => {\n if(elementRef.value) resizeObserver.unobserve(elementRef.value)\n })\n \n const editorViewRef = ref()\n let editorView: EditorView\n\n const handleFocus = () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, true)\n }\n const handleBlur = () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, false)\n }\n const handleInput = debounce(function() {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { content: editorView.dom.innerHTML },\n })\n addHistorySnapshot()\n }, 300, { trailing: true })\n\n const handleClick = debounce(function() {\n const attr = getTextAttrs(editorView)\n emitter.emit(EmitterEvents.UPDATE_TEXT_STATE, attr)\n }, 30, { trailing: true })\n\n const handleKeydown = () => {\n handleInput()\n handleClick()\n }\n\n const textContent = computed(() => props.elementInfo.content)\n watch(textContent, () => {\n if(!editorView) return\n if(editorView.hasFocus()) return\n editorView.dom.innerHTML = textContent.value\n })\n\n const editable = computed(() => !props.elementInfo.lock)\n watch(editable, () => {\n editorView.setProps({ editable: () => editable.value })\n })\n\n onMounted(() => {\n editorView = initProsemirrorEditor((editorViewRef.value as Element), textContent.value, {\n handleDOMEvents: {\n focus: handleFocus,\n blur: handleBlur,\n keydown: handleKeydown,\n click: handleClick,\n },\n editable: () => editable.value,\n })\n })\n onUnmounted(() => {\n editorView && editorView.destroy()\n })\n\n const handleSelectElement = (e: MouseEvent, canMove = true) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo, canMove)\n }\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const handleElementId = computed(() => store.state.handleElementId)\n \n const execCommand = (payload: CommandPayload | CommandPayload[]) => {\n if(handleElementId.value !== props.elementInfo.id) return\n\n const commands = ('command' in payload) ? [payload] : payload\n\n for(const item of commands) {\n if(item.command === 'fontname' && item.value) {\n const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'fontsize' && item.value) {\n const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'color' && item.value) {\n const mark = editorView.state.schema.marks.forecolor.create({ color: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'backcolor' && item.value) {\n const mark = editorView.state.schema.marks.backcolor.create({ backcolor: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'bold') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'em') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'underline') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'strikethrough') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'subscript') {\n toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'superscript') {\n toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'blockquote') {\n wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'code') {\n toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'align' && item.value) {\n alignmentCommand(editorView, item.value)\n }\n else if(item.command === 'bulletList') {\n const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes\n toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'orderedList') {\n const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes\n toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'clear') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))\n }\n }\n\n editorView.focus()\n handleInput()\n handleClick()\n }\n\n emitter.on(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\n onUnmounted(() => {\n emitter.off(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\n })\n\n return {\n elementRef,\n editorViewRef,\n handleSelectElement,\n shadowStyle,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=092f3d4e&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=092f3d4e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-092f3d4e\"\n\nexport default script","\n\n\n\n\n","\r\n\r\n","\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'gradient-defs',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'linear' | 'radial'>,\r\n },\r\n color1: {\r\n type: String,\r\n required: true,\r\n },\r\n color2: {\r\n type: String,\r\n required: true,\r\n },\r\n rotate: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n})\r\n","import { render } from \"./GradientDefs.vue?vue&type=template&id=b787d5ea\"\nimport script from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nexport * from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTShapeElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport GradientDefs from './GradientDefs.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n GradientDefs,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n\n const outline = computed(() => props.elementInfo.outline)\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n handleSelectElement,\n shadowStyle,\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=6a9228f2&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=6a9228f2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6a9228f2\"\n\nexport default script","\n\n\n\n\n","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\n\nconst pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z',\n}\nconst rotateMap = {\n 'arrow-start': 180,\n 'arrow-end': 0,\n}\n\nexport default defineComponent({\n name: 'line-point-marker',\n props: {\n id: {\n type: String,\n required: true,\n },\n position: {\n type: String as PropType<'start' | 'end'>,\n required: true,\n },\n type: {\n type: String as PropType<'dot' | 'arrow'>,\n required: true,\n },\n color: {\n type: String,\n },\n baseSize: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const path = computed(() => pathMap[props.type])\n const rotate = computed(() => rotateMap[`${props.type}-${props.position}`] || 0)\n const size = computed(() => props.baseSize < 2 ? 2 : props.baseSize)\n\n return {\n path,\n rotate,\n size,\n }\n },\n})\n","import { render } from \"./LinePointMarker.vue?vue&type=template&id=62085f5a\"\nimport script from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTLineElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport LinePointMarker from './LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n LinePointMarker,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const svgWidth = computed(() => {\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\n return width < 24 ? 24 : width\n })\n const svgHeight = computed(() => {\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\n return height < 24 ? 24 : height\n })\n\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\n const path = computed(() => {\n const start = props.elementInfo.start.join(',')\n const end = props.elementInfo.end.join(',')\n return `M${start} L${end}`\n })\n\n return {\n handleSelectElement,\n shadowStyle,\n svgWidth,\n svgHeight,\n lineDashArray,\n path,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=d93ab0c4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=d93ab0c4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d93ab0c4\"\n\nexport default script","\r\n\r\n\r\n\r\n\r\n","\n\n\n\n\n\n","\nimport { defineComponent, inject, onMounted, PropType, ref, Ref, watch } from 'vue'\nimport upperFirst from 'lodash/upperFirst'\nimport tinycolor from 'tinycolor2'\nimport Chartist, {\n IChartistLineChart,\n IChartistBarChart,\n IChartistPieChart,\n ILineChartOptions,\n IBarChartOptions,\n IPieChartOptions,\n} from 'chartist'\nimport { ChartData, ChartType } from '@/types/slides'\n\nimport 'chartist/dist/scss/chartist.scss'\n\nexport default defineComponent({\n name: 'chart',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n type: {\n type: String as PropType,\n required: true,\n },\n data: {\n type: Object as PropType,\n required: true,\n },\n options: {\n type: Object as PropType,\n },\n themeColor: {\n type: String,\n required: true,\n },\n gridColor: {\n type: String,\n },\n },\n setup(props) {\n const chartRef = ref()\n const slideScale: Ref = inject('slideScale') || ref(1)\n\n let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined\n\n const getDataAndOptions = () => {\n const propsOptopns = props.options || {}\n const options = {\n ...propsOptopns,\n width: props.width * slideScale.value,\n height: props.height * slideScale.value,\n }\n const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data\n return { data, options }\n }\n\n const renderChart = () => {\n if(!chartRef.value) return\n\n const type = upperFirst(props.type)\n const { data, options } = getDataAndOptions()\n chart = new Chartist[type](chartRef.value, data, options)\n }\n\n const updateChart = () => {\n if(!chart) {\n renderChart()\n return\n }\n const { data, options } = getDataAndOptions()\n chart.update(data, options)\n }\n\n watch([\n () => props.width,\n () => props.height,\n () => props.data,\n slideScale,\n ], updateChart)\n\n onMounted(renderChart)\n\n const updateTheme = () => {\n if(!chartRef.value) return\n\n const hsla = tinycolor(props.themeColor).toHsl()\n\n for(let i = 0; i < 10; i++) {\n let h = hsla.h + i * 36\n if(h > 360) h = h - 360\n\n const _hsla = {\n ...hsla,\n h,\n }\n chartRef.value.style.setProperty(`--theme-color-${i + 1}`, tinycolor(_hsla).toRgbString())\n }\n\n if(props.gridColor) chartRef.value.style.setProperty(`--grid-color`, props.gridColor)\n }\n\n watch([\n () => props.themeColor,\n () => props.gridColor,\n ], updateTheme)\n onMounted(updateTheme)\n\n return {\n slideScale,\n chartRef,\n }\n },\n})\n","import { render } from \"./Chart.vue?vue&type=template&id=5f401eca&scoped=true\"\nimport script from \"./Chart.vue?vue&type=script&lang=ts\"\nexport * from \"./Chart.vue?vue&type=script&lang=ts\"\n\nimport \"./Chart.vue?vue&type=style&index=0&id=5f401eca&lang=scss&scoped=true\"\nimport \"./Chart.vue?vue&type=style&index=1&id=5f401eca&lang=scss\"\nscript.render = render\nscript.__scopeId = \"data-v-5f401eca\"\n\nexport default script","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTChartElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if(props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n return {\r\n handleSelectElement,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=7550799e&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=7550799e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7550799e\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\n\n","\nimport { defineComponent, onUnmounted, ref, watch } from 'vue'\n\nexport default defineComponent({\n name: 'custom-textarea',\n props: {\n modelValue: {\n type: String,\n default: '',\n },\n contenteditable: {\n type: [Boolean, String],\n default: false,\n },\n },\n setup(props, { emit }) {\n const textareaRef = ref()\n const text = ref('')\n const isFocus = ref(false)\n\n watch(() => props.modelValue, () => {\n if(isFocus.value) return\n text.value = props.modelValue\n if(textareaRef.value) textareaRef.value.innerHTML = props.modelValue\n }, { immediate: true })\n\n const handleInput = () => {\n if(!textareaRef.value) return\n const text = textareaRef.value.innerHTML\n emit('update:modelValue', text)\n }\n\n const handleFocus = () => {\n isFocus.value = true\n\n if(!textareaRef.value) return\n textareaRef.value.onpaste = (e: ClipboardEvent) => {\n e.preventDefault()\n if(!e.clipboardData) return\n\n const clipboardDataFirstItem = e.clipboardData.items[0]\n\n if(clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\n clipboardDataFirstItem.getAsString(text => emit('update:modelValue', text))\n }\n }\n }\n\n const handleBlur = () => {\n isFocus.value = false\n if(textareaRef.value) textareaRef.value.onpaste = null\n }\n\n onUnmounted(() => {\n if(textareaRef.value) textareaRef.value.onpaste = null\n })\n\n return {\n textareaRef,\n handleFocus,\n handleInput,\n handleBlur,\n text,\n }\n },\n})\n","import { render } from \"./CustomTextarea.vue?vue&type=template&id=ca4394a2\"\nimport script from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nexport * from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport debounce from 'lodash/debounce'\nimport tinycolor from 'tinycolor2'\nimport { useStore } from '@/store'\nimport { PPTElementOutline, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { KEYS } from '@/configs/hotkey'\nimport { createRandomCode } from '@/utils/common'\n\nimport CustomTextarea from './CustomTextarea.vue'\n\nexport default defineComponent({\n name: 'editable-table',\n components: {\n CustomTextarea,\n },\n props: {\n data: {\n type: Array as PropType,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n colWidths: {\n type: Array as PropType,\n required: true,\n },\n outline: {\n type: Object as PropType,\n required: true,\n },\n theme: {\n type: Object as PropType,\n },\n editable: {\n type: Boolean,\n default: true,\n },\n },\n setup(props, { emit }) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const subThemeColor = ref(['', ''])\n watch(() => props.theme, () => {\n if(props.theme) {\n const rgba = tinycolor(props.theme.color).toRgb()\n const subRgba1 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.3 }\n const subRgba2 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.1 }\n subThemeColor.value = [\n `rgba(${[subRgba1.r, subRgba1.g, subRgba1.b, subRgba1.a].join(',')})`,\n `rgba(${[subRgba2.r, subRgba2.g, subRgba2.b, subRgba2.a].join(',')})`,\n ]\n }\n }, { immediate: true })\n\n const tableCells = computed({\n get() {\n return props.data\n },\n set(newData) {\n emit('change', newData)\n },\n })\n\n const colSizeList = ref([])\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\n watch([\n () => props.colWidths,\n () => props.width,\n ], () => {\n colSizeList.value = props.colWidths.map(item => item * props.width)\n }, { immediate: true })\n \n const isStartSelect = ref(false)\n const startCell = ref([])\n const endCell = ref([])\n \n const removeSelectedCells = () => {\n startCell.value = []\n endCell.value = []\n }\n\n watch(() => props.editable, () => {\n if(!props.editable) removeSelectedCells()\n })\n\n const dragLinePosition = computed(() => {\n const dragLinePosition: number[] = []\n for(let i = 1; i < colSizeList.value.length + 1; i++) {\n const pos = colSizeList.value.slice(0, i).reduce((a, b) => (a + b))\n dragLinePosition.push(pos)\n }\n return dragLinePosition\n })\n\n const hideCells = computed(() => {\n const hideCells = []\n \n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n\n for(let j = 0; j < rowCells.length; j++) {\n const cell = rowCells[j]\n \n if(cell.colspan > 1 || cell.rowspan > 1) {\n for(let row = i; row < i + cell.rowspan; row++) {\n for(let col = row === i ? j + 1 : j; col < j + cell.colspan; col++) {\n hideCells.push(`${row}_${col}`)\n }\n }\n }\n }\n }\n return hideCells\n })\n\n const selectedCells = computed(() => {\n if(!startCell.value.length) return []\n const [startX, startY] = startCell.value\n\n if(!endCell.value.length) return [`${startX}_${startY}`]\n const [endX, endY] = endCell.value\n\n if(startX === endX && startY === endY) return [`${startX}_${startY}`]\n\n const selectedCells = []\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n for(let j = 0; j < rowCells.length; j++) {\n if(i >= minX && i <= maxX && j >= minY && j <= maxY) selectedCells.push(`${i}_${j}`)\n }\n }\n return selectedCells\n })\n\n watch(selectedCells, () => {\n emit('changeSelectedCells', selectedCells.value)\n })\n\n const activedCell = computed(() => {\n if(selectedCells.value.length > 1) return null\n return selectedCells.value[0]\n })\n\n const selectedRange = computed(() => {\n if(!startCell.value.length) return null\n const [startX, startY] = startCell.value\n\n if(!endCell.value.length) return { row: [startX, startX], col: [startY, startY] }\n const [endX, endY] = endCell.value\n\n if(startX === endX && startY === endY) return { row: [startX, startX], col: [startY, startY] }\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n return {\n row: [minX, maxX],\n col: [minY, maxY],\n }\n })\n\n const handleMouseup = () => isStartSelect.value = false\n\n const handleCellMousedown = (e: MouseEvent, rowIndex: number, colIndex: number) => {\n if(e.button === 0) {\n endCell.value = []\n isStartSelect.value = true\n startCell.value = [rowIndex, colIndex]\n }\n }\n\n const handleCellMouseenter = (rowIndex: number, colIndex: number) => {\n if(!isStartSelect.value) return\n endCell.value = [rowIndex, colIndex]\n }\n\n onMounted(() => {\n document.addEventListener('mouseup', handleMouseup)\n })\n onUnmounted(() => {\n document.removeEventListener('mouseup', handleMouseup)\n })\n\n const isHideCell = (rowIndex: number, colIndex: number) => hideCells.value.includes(`${rowIndex}_${colIndex}`)\n\n const selectCol = (index: number) => {\n const maxRow = tableCells.value.length - 1\n startCell.value = [0, index]\n endCell.value = [maxRow, index]\n }\n\n const selectRow = (index: number) => {\n const maxCol = tableCells.value[index].length - 1\n startCell.value = [index, 0]\n endCell.value = [index, maxCol]\n }\n\n const selectAll = () => {\n const maxRow = tableCells.value.length - 1\n const maxCol = tableCells.value[maxRow].length - 1\n startCell.value = [0, 0]\n endCell.value = [maxRow, maxCol]\n }\n\n const deleteRow = (rowIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const targetCells = tableCells.value[rowIndex]\n const hideCellsPos = []\n for(let i = 0; i < targetCells.length; i++) {\n if(isHideCell(rowIndex, i)) hideCellsPos.push(i)\n }\n \n for(const pos of hideCellsPos) {\n for(let i = rowIndex; i >= 0; i--) {\n if(!isHideCell(i, pos)) {\n _tableCells[i][pos].rowspan = _tableCells[i][pos].rowspan - 1\n break\n }\n }\n }\n\n _tableCells.splice(rowIndex, 1)\n tableCells.value = _tableCells\n }\n\n const deleteCol = (colIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const hideCellsPos = []\n for(let i = 0; i < tableCells.value.length; i++) {\n if(isHideCell(i, colIndex)) hideCellsPos.push(i)\n }\n\n for(const pos of hideCellsPos) {\n for(let i = colIndex; i >= 0; i--) {\n if(!isHideCell(pos, i)) {\n _tableCells[pos][i].colspan = _tableCells[pos][i].colspan - 1\n break\n }\n }\n }\n\n tableCells.value = _tableCells.map(item => {\n item.splice(colIndex, 1)\n return item\n })\n colSizeList.value.splice(colIndex, 1)\n emit('changeColWidths', colSizeList.value)\n }\n \n const insertRow = (rowIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const rowCells: TableCell[] = []\n for(let i = 0; i < _tableCells[0].length; i++) {\n rowCells.push({\n colspan: 1,\n rowspan: 1,\n text: '',\n id: createRandomCode(),\n })\n }\n\n _tableCells.splice(rowIndex, 0, rowCells)\n tableCells.value = _tableCells\n }\n\n const insertCol = (colIndex: number) => {\n tableCells.value = tableCells.value.map(item => {\n const cell = {\n colspan: 1,\n rowspan: 1,\n text: '',\n id: createRandomCode(),\n }\n item.splice(colIndex, 0, cell)\n return item\n })\n colSizeList.value.splice(colIndex, 0, 100)\n emit('changeColWidths', colSizeList.value)\n }\n \n const mergeCells = () => {\n const [startX, startY] = startCell.value\n const [endX, endY] = endCell.value\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n \n _tableCells[minX][minY].rowspan = maxX - minX + 1\n _tableCells[minX][minY].colspan = maxY - minY + 1\n\n tableCells.value = _tableCells\n removeSelectedCells()\n }\n\n const splitCells = (rowIndex: number, colIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n _tableCells[rowIndex][colIndex].rowspan = 1\n _tableCells[rowIndex][colIndex].colspan = 1\n\n tableCells.value = _tableCells\n removeSelectedCells()\n }\n\n const handleMousedownColHandler = (e: MouseEvent, colIndex: number) => {\n removeSelectedCells()\n let isMouseDown = true\n\n const originWidth = colSizeList.value[colIndex]\n const startPageX = e.pageX\n\n const minWidth = 50\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n const moveX = (e.pageX - startPageX) / canvasScale.value\n const width = originWidth + moveX < minWidth ? minWidth : Math.round(originWidth + moveX)\n\n colSizeList.value[colIndex] = width\n }\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n emit('changeColWidths', colSizeList.value)\n }\n }\n\n const clearSelectedCellText = () => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n for(let i = 0; i < _tableCells.length; i++) {\n for(let j = 0; j < _tableCells[i].length; j++) {\n if(selectedCells.value.includes(`${i}_${j}`)) {\n _tableCells[i][j].text = ''\n }\n }\n }\n tableCells.value = _tableCells\n }\n\n const tabActiveCell = () => {\n const getNextCell = (i: number, j: number): [number, number] | null => {\n if(!tableCells.value[i]) return null\n if(!tableCells.value[i][j]) return getNextCell(i + 1, 0)\n if(isHideCell(i, j)) return getNextCell(i, j + 1)\n return [i, j]\n }\n\n endCell.value = []\n\n const nextRow = startCell.value[0]\n const nextCol = startCell.value[1] + 1\n\n const nextCell = getNextCell(nextRow, nextCol)\n if(!nextCell) {\n insertRow(nextRow + 1)\n startCell.value = [nextRow + 1, 0]\n }\n else startCell.value = nextCell\n\n nextTick(() => {\n const textRef = document.querySelector('.cell-text.active') as HTMLInputElement\n if(textRef) textRef.focus()\n })\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(selectedCells.value.length < 2) {\n if(key === KEYS.TAB) {\n e.preventDefault()\n tabActiveCell()\n }\n }\n else if(key === KEYS.DELETE) {\n clearSelectedCellText()\n }\n }\n\n onMounted(() => {\n document.addEventListener('keydown', keydownListener)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keydownListener)\n })\n\n const getTextStyle = (style?: TableCellStyle) => {\n if(!style) return {}\n const {\n bold,\n em,\n underline,\n strikethrough,\n color,\n backcolor,\n fontsize,\n fontname,\n align,\n } = style\n \n return {\n fontWeight: bold ? 'bold' : 'normal',\n fontStyle: em ? 'italic' : 'normal',\n textDecoration: `${underline ? 'underline' : ''} ${strikethrough ? 'line-through' : ''}`,\n color: color || '#000',\n backgroundColor: backcolor || '',\n fontSize: fontsize || '14px',\n fontFamily: fontname || '微软雅黑',\n textAlign: align || 'left',\n }\n }\n\n const handleInput = debounce(function() {\n emit('change', tableCells.value)\n }, 300, { trailing: true })\n\n const getEffectiveTableCells = () => {\n const effectiveTableCells = []\n\n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n const _rowCells = []\n for(let j = 0; j < rowCells.length; j++) {\n if(!isHideCell(i, j)) _rowCells.push(rowCells[j])\n }\n if(_rowCells.length) effectiveTableCells.push(_rowCells)\n }\n\n return effectiveTableCells\n }\n\n const checkCanDeleteRowOrCol = () => {\n const effectiveTableCells = getEffectiveTableCells()\n const canDeleteRow = effectiveTableCells.length > 1\n const canDeleteCol = effectiveTableCells[0].length > 1\n\n return { canDeleteRow, canDeleteCol }\n }\n\n const checkCanMergeOrSplit = (rowIndex: number, colIndex: number) => {\n const isMultiSelected = selectedCells.value.length > 1\n const targetCell = tableCells.value[rowIndex][colIndex]\n\n const canMerge = isMultiSelected\n const canSplit = !isMultiSelected && (targetCell.rowspan > 1 || targetCell.colspan > 1)\n\n return { canMerge, canSplit }\n }\n\n const contextmenus = (el: HTMLElement): ContextmenuItem[] => {\n const cellIndex = el.dataset.cellIndex as string\n const rowIndex = +cellIndex.split('_')[0]\n const colIndex = +cellIndex.split('_')[1]\n\n if(!selectedCells.value.includes(`${rowIndex}_${colIndex}`)) {\n startCell.value = [rowIndex, colIndex]\n endCell.value = []\n }\n\n const { canMerge, canSplit } = checkCanMergeOrSplit(rowIndex, colIndex)\n const { canDeleteRow, canDeleteCol } = checkCanDeleteRowOrCol()\n\n return [\n {\n text: '插入列',\n children: [\n { text: '到左侧', handler: () => insertCol(colIndex) },\n { text: '到右侧', handler: () => insertCol(colIndex + 1) },\n ],\n },\n {\n text: '插入行',\n children: [\n { text: '到上方', handler: () => insertRow(rowIndex) },\n { text: '到下方', handler: () => insertRow(rowIndex + 1) },\n ],\n },\n {\n text: '删除列',\n disable: !canDeleteCol,\n handler: () => deleteCol(colIndex),\n },\n {\n text: '删除行',\n disable: !canDeleteRow,\n handler: () => deleteRow(rowIndex),\n },\n { divider: true },\n {\n text: '合并单元格',\n disable: !canMerge,\n handler: mergeCells,\n },\n {\n text: '取消合并单元格',\n disable: !canSplit,\n handler: () => splitCells(rowIndex, colIndex),\n },\n { divider: true },\n {\n text: '选中当前列',\n handler: () => selectCol(colIndex),\n },\n {\n text: '选中当前行',\n handler: () => selectRow(rowIndex),\n },\n {\n text: '选中全部单元格',\n handler: selectAll,\n },\n ]\n }\n\n return {\n getTextStyle,\n dragLinePosition,\n tableCells,\n colSizeList,\n totalWidth,\n hideCells,\n selectedCells,\n activedCell,\n selectedRange,\n handleCellMousedown,\n handleCellMouseenter,\n selectCol,\n selectRow,\n handleMousedownColHandler,\n contextmenus,\n handleInput,\n subThemeColor,\n }\n },\n})\n","import { render } from \"./EditableTable.vue?vue&type=template&id=7859e10e&scoped=true\"\nimport script from \"./EditableTable.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableTable.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableTable.vue?vue&type=style&index=0&id=7859e10e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7859e10e\"\n\nexport default script","\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTableElement, TableCell } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport EditableTable from './EditableTable.vue'\n\nexport default defineComponent({\n name: 'editable-element-table',\n components: {\n EditableTable,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n const editable = ref(false)\n const handleElementId = computed(() => store.state.handleElementId)\n\n watch(handleElementId, () => {\n if(handleElementId.value !== props.elementInfo.id) editable.value = false\n })\n\n watch(editable, () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, editable.value)\n })\n \n const elementRef = ref()\n\n const isScaling = ref(false)\n const realHeightCache = ref(-1)\n\n const scaleElementStateListener = (state: boolean) => {\n isScaling.value = state\n\n if(state) editable.value = false\n\n if(!state && realHeightCache.value !== -1) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeightCache.value },\n })\n realHeightCache.value = -1\n }\n }\n\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n onUnmounted(() => {\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n })\n\n const updateTableElementHeight = (entries: ResizeObserverEntry[]) => {\n const contentRect = entries[0].contentRect\n if(!elementRef.value) return\n\n const realHeight = contentRect.height\n\n if(props.elementInfo.height !== realHeight) {\n if(!isScaling.value) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeight },\n })\n }\n else realHeightCache.value = realHeight\n }\n }\n\n const resizeObserver = new ResizeObserver(updateTableElementHeight)\n\n onMounted(() => {\n if(elementRef.value) resizeObserver.observe(elementRef.value)\n })\n onUnmounted(() => {\n if(elementRef.value) resizeObserver.unobserve(elementRef.value)\n })\n\n const updateTableCells = (data: TableCell[][]) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { data },\n })\n addHistorySnapshot()\n }\n const updateColWidths = (widths: number[]) => {\n const width = widths.reduce((a, b) => a + b)\n const colWidths = widths.map(item => item / width)\n\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { width, colWidths },\n })\n addHistorySnapshot()\n }\n\n const updateSelectedCells = (cells: string[]) => {\n nextTick(() => emitter.emit(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells))\n }\n\n const startEdit = () => {\n if(!props.elementInfo.lock) editable.value = true\n }\n\n return {\n elementRef,\n canvasScale,\n handleSelectElement,\n updateTableCells,\n updateColWidths,\n editable,\n startEdit,\n updateSelectedCells,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=045f7664&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=045f7664&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-045f7664\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\n\nimport useLockElement from '@/hooks/useLockElement'\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCombineElement from '@/hooks/useCombineElement'\nimport useOrderElement from '@/hooks/useOrderElement'\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\n\nimport { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'\n\nimport ImageElement from '@/views/components/element/ImageElement/index.vue'\nimport TextElement from '@/views/components/element/TextElement/index.vue'\nimport ShapeElement from '@/views/components/element/ShapeElement/index.vue'\nimport LineElement from '@/views/components/element/LineElement/index.vue'\nimport ChartElement from '@/views/components/element/ChartElement/index.vue'\nimport TableElement from '@/views/components/element/TableElement/index.vue'\n\nexport default defineComponent({\n name: 'editable-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTElement, canMove?: boolean) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const theme = computed(() => store.state.theme)\n\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: ImageElement,\n [ElementTypes.TEXT]: TextElement,\n [ElementTypes.SHAPE]: ShapeElement,\n [ElementTypes.LINE]: LineElement,\n [ElementTypes.CHART]: ChartElement,\n [ElementTypes.TABLE]: TableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n const { orderElement } = useOrderElement()\n const { alignElementToCanvas } = useAlignElementToCanvas()\n const { combineElements, uncombineElements } = useCombineElement()\n const { deleteElement } = useDeleteElement()\n const { lockElement, unlockElement } = useLockElement()\n const { copyElement, cutElement } = useCopyAndPasteElement()\n\n const contextmenus = (): ContextmenuItem[] => {\n if(props.elementInfo.lock) {\n return [{\n text: '解锁', \n handler: () => unlockElement(props.elementInfo),\n }]\n }\n\n return [\n {\n text: '剪切',\n subText: 'Ctrl + X',\n handler: cutElement,\n },\n {\n text: '复制',\n subText: 'Ctrl + C',\n handler: copyElement,\n },\n { divider: true },\n {\n text: '层级排序',\n disable: props.isMultiSelect && !props.elementInfo.groupId,\n children: [\n { text: '置顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },\n { text: '置底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },\n { divider: true },\n { text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },\n { text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },\n ],\n },\n {\n text: '水平对齐',\n children: [\n { text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },\n { text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },\n { text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },\n ],\n },\n {\n text: '垂直对齐',\n children: [\n { text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },\n { text: '上对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },\n { text: '下对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },\n ],\n },\n { divider: true },\n {\n text: props.elementInfo.groupId ? '取消组合' : '组合',\n subText: 'Ctrl + G',\n handler: props.elementInfo.groupId ? uncombineElements : combineElements,\n hide: !props.isMultiSelect,\n },\n {\n text: '锁定',\n subText: 'Ctrl + L',\n handler: lockElement,\n },\n {\n text: '删除',\n subText: 'Delete',\n handler: deleteElement,\n },\n ]\n }\n\n return {\n currentElementComponent,\n contextmenus,\n theme,\n }\n },\n})\n","import { render } from \"./EditableElement.vue?vue&type=template&id=0d0be614\"\nimport script from \"./EditableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n\n\n","\nexport default {\n name: 'mouse-selection',\n props: {\n top: {\n type: Number,\n required: true,\n },\n left: {\n type: Number,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n quadrant: {\n type: Number,\n required: true,\n validator(value: number) {\n return [1, 2, 3, 4].includes(value)\n },\n },\n }\n}\n","import { render } from \"./MouseSelection.vue?vue&type=template&id=1619c258&scoped=true\"\nimport script from \"./MouseSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./MouseSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./MouseSelection.vue?vue&type=style&index=0&id=1619c258&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1619c258\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\nimport { defineComponent, computed } from 'vue'\nimport tinycolor from 'tinycolor2'\nimport { useStore } from '@/store'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { SlideBackground } from '@/types/slides'\n\nexport default defineComponent({\n name: 'grid-lines',\n setup() {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const background = computed(() => store.getters.currentSlide.background)\n\n const gridColor = computed(() => {\n if(!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'\n const color = background.value.color\n const rgba = tinycolor(color).toRgb()\n const newRgba = {\n r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,\n g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,\n b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,\n a: 0.5\n }\n return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`\n })\n\n const gridSize = 50\n\n const getPath = () => {\n const maxX = VIEWPORT_SIZE\n const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n\n let path = ''\n for(let i = 0; i <= Math.floor(maxY / gridSize); i++) {\n path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`\n }\n for(let i = 0; i <= Math.floor(maxX / gridSize); i++) {\n path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`\n }\n return path\n }\n\n return {\n canvasScale,\n gridColor,\n width: VIEWPORT_SIZE,\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\n path: getPath(),\n }\n },\n})\n","import { render } from \"./GridLines.vue?vue&type=template&id=6515bb1c&scoped=true\"\nimport script from \"./GridLines.vue?vue&type=script&lang=ts\"\nexport * from \"./GridLines.vue?vue&type=script&lang=ts\"\n\nimport \"./GridLines.vue?vue&type=style&index=0&id=6515bb1c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6515bb1c\"\n\nexport default script","import { Ref, computed } from 'vue'\nimport { SlideBackground } from '@/types/slides'\n\nexport default (background: Ref) => {\n const backgroundStyle = computed(() => {\n if(!background.value) return { backgroundColor: '#fff' }\n\n const {\n type,\n color,\n image,\n imageSize,\n gradientColor,\n gradientRotate,\n gradientType,\n } = background.value\n\n if(type === 'solid') return { backgroundColor: color }\n else if(type === 'image') {\n if(!image) return { backgroundColor: '#fff' }\n if(imageSize === 'repeat') {\n return {\n backgroundImage: `url(${image}`,\n backgroundRepeat: 'repeat',\n backgroundSize: 'initial',\n }\n }\n return {\n backgroundImage: `url(${image}`,\n backgroundRepeat: 'no-repeat',\n backgroundSize: imageSize || 'cover',\n }\n }\n else if(type === 'gradient') {\n const rotate = gradientRotate || 0\n const color1 = gradientColor ? gradientColor[0] : '#fff'\n const color2 = gradientColor ? gradientColor[1] : '#fff'\n \n if(gradientType === 'radial') return { backgroundImage: `radial-gradient(${color1}, ${color2}` }\n return { backgroundImage: `linear-gradient(${rotate}deg, ${color1}, ${color2}` }\n }\n\n return { backgroundColor: '#fff' }\n })\n\n return {\n backgroundStyle,\n }\n}","\nimport { computed, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { SlideBackground } from '@/types/slides'\nimport GridLines from './GridLines.vue'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nexport default defineComponent({\n name: 'slide-background',\n components: {\n GridLines,\n },\n setup() {\n const store = useStore()\n const showGridLines = computed(() => store.state.showGridLines)\n const background = computed(() => store.getters.currentSlide.background)\n\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n return {\n showGridLines,\n backgroundStyle,\n }\n },\n})\n","import { render } from \"./SlideBackground.vue?vue&type=template&id=774174ab&scoped=true\"\nimport script from \"./SlideBackground.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideBackground.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideBackground.vue?vue&type=style&index=0&id=774174ab&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-774174ab\"\n\nexport default script","\n\n\n\n","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { AlignmentLineAxis } from '@/types/edit'\n\nexport default defineComponent({\n name: 'alignment-line',\n props: {\n type: {\n type: String as PropType<'vertical' | 'horizontal'>,\n required: true,\n },\n axis: {\n type: Object as PropType,\n required: true,\n },\n length: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const left = computed(() => props.axis.x * canvasScale.value + 'px')\n const top = computed(() => props.axis.y * canvasScale.value + 'px')\n\n const sizeStyle = computed(() => {\n if(props.type === 'vertical') return { height: props.length * canvasScale.value + 'px' }\n return { width: props.length * canvasScale.value + 'px' }\n })\n\n return {\n left,\n top,\n sizeStyle,\n }\n },\n})\n","import { render } from \"./AlignmentLine.vue?vue&type=template&id=520a7023&scoped=true\"\nimport script from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\nexport * from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\n\nimport \"./AlignmentLine.vue?vue&type=style&index=0&id=520a7023&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-520a7023\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onMounted, reactive, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\n\nexport default defineComponent({\n name: 'element-create-selection',\n setup(props, { emit }) {\n const store = useStore()\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n const creatingElement = computed(() => store.state.creatingElement)\n\n const start = ref<[number, number] | null>(null)\n const end = ref<[number, number] | null>(null)\n\n const selectionRef = ref()\n const offset = reactive({\n x: 0,\n y: 0,\n })\n onMounted(() => {\n if(!selectionRef.value) return\n const { x, y } = selectionRef.value.getBoundingClientRect()\n offset.x = x\n offset.y = y\n })\n\n const createSelection = (e: MouseEvent) => {\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n start.value = [startPageX, startPageY]\n\n document.onmousemove = e => {\n if(!creatingElement.value || !isMouseDown) return\n\n let currentPageX = e.pageX\n let currentPageY = e.pageY\n\n if(ctrlOrShiftKeyActive.value) {\n const moveX = currentPageX - startPageX\n const moveY = currentPageY - startPageY\n\n const absX = Math.abs(moveX)\n const absY = Math.abs(moveY)\n\n if(creatingElement.value.type === 'shape') {\n // moveX和moveY一正一负\n const isOpposite = (moveY > 0 && moveX < 0) || (moveY < 0 && moveX > 0)\n\n if(absX > absY) {\n currentPageY = isOpposite ? startPageY - moveX : startPageY + moveX\n }\n else {\n currentPageX = isOpposite ? startPageX - moveY : startPageX + moveY\n }\n }\n\n else if(creatingElement.value.type === 'line') {\n if(absX > absY) currentPageY = startPageY\n else currentPageX = startPageX\n }\n }\n\n end.value = [currentPageX, currentPageY]\n }\n\n document.onmouseup = e => {\n document.onmousemove = null\n document.onmouseup = null\n isMouseDown = false\n\n const endPageX = e.pageX\n const endPageY = e.pageY\n\n const minSize = 30\n\n if(Math.abs(endPageX - startPageX) >= minSize || Math.abs(endPageY - startPageY) >= minSize) {\n emit('created', {\n start: start.value,\n end: end.value,\n })\n }\n else store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\n }\n }\n\n const lineData = computed(() => {\n if(!start.value || !end.value) return null\n if(!creatingElement.value || creatingElement.value.type !== 'line') return null\n\n const [_startX, _startY] = start.value\n const [_endX, _endY] = end.value\n const minX = Math.min(_startX, _endX)\n const maxX = Math.max(_startX, _endX)\n const minY = Math.min(_startY, _endY)\n const maxY = Math.max(_startY, _endY)\n\n const svgWidth = maxX - minX >= 24 ? maxX - minX : 24\n const svgHeight = maxY - minY >= 24 ? maxY - minY : 24\n\n const startX = _startX === minX ? 0 : maxX - minX\n const startY = _startY === minY ? 0 : maxY - minY\n const endX = _endX === minX ? 0 : maxX - minX\n const endY = _endY === minY ? 0 : maxY - minY\n\n const path = `M${startX}, ${startY} L${endX}, ${endY}`\n\n return {\n svgWidth,\n svgHeight,\n startX,\n startY,\n endX,\n endY,\n path,\n }\n })\n\n const position = computed(() => {\n if(!start.value || !end.value) return {}\n\n const [startX, startY] = start.value\n const [endX, endY] = end.value\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n left: minX - offset.x + 'px',\n top: minY - offset.y + 'px',\n width: width + 'px',\n height: height + 'px',\n }\n })\n\n return {\n selectionRef,\n start,\n end,\n creatingElement,\n createSelection,\n lineData,\n position,\n }\n },\n})\n","import { render } from \"./ElementCreateSelection.vue?vue&type=template&id=eea668f4&scoped=true\"\nimport script from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementCreateSelection.vue?vue&type=style&index=0&id=eea668f4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-eea668f4\"\n\nexport default script","\n\n\n\n","import { computed, Ref } from 'vue'\nimport { OperateResizeHandlers, OperateBorderLines } from '@/types/edit'\n\nexport default (width: Ref, height: Ref) => {\n const resizeHandlers = computed(() => {\n return [\n { direction: OperateResizeHandlers.LEFT_TOP, style: {} },\n { direction: OperateResizeHandlers.TOP, style: {left: width.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT_TOP, style: {left: width.value + 'px'} },\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.LEFT_BOTTOM, style: {top: height.value + 'px'} },\n { direction: OperateResizeHandlers.BOTTOM, style: {left: width.value / 2 + 'px', top: height.value + 'px'} },\n { direction: OperateResizeHandlers.RIGHT_BOTTOM, style: {left: width.value + 'px', top: height.value + 'px'} },\n ]\n }\n )\n const textElementResizeHandlers = computed(() => {\n return [\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\n ]\n })\n\n const borderLines = computed(() => {\n return [\n { type: OperateBorderLines.T, style: {width: width.value + 'px'} },\n { type: OperateBorderLines.B, style: {top: height.value + 'px', width: width.value + 'px'} },\n { type: OperateBorderLines.L, style: {height: height.value + 'px'} },\n { type: OperateBorderLines.R, style: {left: width.value + 'px', height: height.value + 'px'} },\n ]\n })\n\n return {\n resizeHandlers,\n textElementResizeHandlers,\n borderLines,\n }\n}","\n\n\n\n","\nimport { PropType } from 'vue'\nimport { OperateResizeHandler } from '@/types/edit'\n\nexport default {\n name: 'resize-handler',\n props: {\n type: {\n type: String as PropType,\n default: '',\n },\n },\n}\n","import { render } from \"./ResizeHandler.vue?vue&type=template&id=1c2a68d0&scoped=true\"\nimport script from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ResizeHandler.vue?vue&type=style&index=0&id=1c2a68d0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1c2a68d0\"\n\nexport default script","\n\n\n\n","\nimport { PropType } from 'vue'\nimport { OperateBorderLine } from '@/types/edit'\n\nexport default {\n name: 'border-line',\n props: {\n type: {\n type: String as PropType,\n required: true,\n },\n isWide: {\n type: Boolean,\n default: false,\n },\n },\n}\n","import { render } from \"./BorderLine.vue?vue&type=template&id=630e246b&scoped=true\"\nimport script from \"./BorderLine.vue?vue&type=script&lang=ts\"\nexport * from \"./BorderLine.vue?vue&type=script&lang=ts\"\n\nimport \"./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-630e246b\"\n\nexport default script","\nimport { computed, defineComponent, reactive, PropType, watchEffect, toRefs } from 'vue'\nimport { useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { getElementListRange } from '@/utils/element'\nimport { OperateResizeHandler, MultiSelectRange } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'multi-select-operate',\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementList: {\n type: Array as PropType,\n required: true,\n },\n scaleMultiElement: {\n type: Function as PropType<(e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const canvasScale = computed(() => store.state.canvasScale)\n const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))\n\n const range = reactive({\n minX: 0,\n maxX: 0,\n minY: 0,\n maxY: 0,\n })\n\n const width = computed(() => (range.maxX - range.minX) * canvasScale.value)\n const height = computed(() => (range.maxY - range.minY) * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(width, height)\n\n const disableResize = computed(() => {\n return localActiveElementList.value.some(item => {\n if(\n (item.type === 'image' || item.type === 'shape') && \n !item.rotate\n ) return false\n return true\n })\n })\n\n const setRange = () => {\n const { minX, maxX, minY, maxY } = getElementListRange(localActiveElementList.value)\n range.minX = minX\n range.maxX = maxX\n range.minY = minY\n range.maxY = maxY\n }\n\n watchEffect(setRange)\n\n return {\n ...toRefs(range),\n canvasScale,\n borderLines,\n disableResize,\n resizeHandlers,\n }\n },\n})\n","import { render } from \"./MultiSelectOperate.vue?vue&type=template&id=66dfa39d&scoped=true\"\nimport script from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiSelectOperate.vue?vue&type=style&index=0&id=66dfa39d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-66dfa39d\"\n\nexport default script","\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n","\n\n\n\n","\nexport default {\n name: 'rotate-handler',\n}\n","import { render } from \"./RotateHandler.vue?vue&type=template&id=9a549510&scoped=true\"\nimport script from \"./RotateHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./RotateHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./RotateHandler.vue?vue&type=style&index=0&id=9a549510&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-9a549510\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTImageElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n isCliping,\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageElementOperate.vue?vue&type=template&id=5b0628aa&scoped=true\"\nimport script from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageElementOperate.vue?vue&type=style&index=0&id=5b0628aa&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b0628aa\"\n\nexport default script","\r\n\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTTextElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TextElementOperate.vue?vue&type=template&id=1f730982\"\nimport script from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport RotateHandler from './RotateHandler.vue'\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'shape-element-operate',\n inheritAttrs: false,\n components: {\n RotateHandler,\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n rotateElement: {\n type: Function as PropType<(element: PPTShapeElement) => void>,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n resizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./ShapeElementOperate.vue?vue&type=template&id=bfcf602e\"\nimport script from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTLineElement } from '@/types/slides'\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\n\nimport ResizeHandler from './ResizeHandler.vue'\n\nexport default defineComponent({\n name: 'text-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n dragLineElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const resizeHandlers = computed(() => {\n return [\n {\n handler: OperateLineHandlers.START,\n style: {\n left: props.elementInfo.start[0] * canvasScale.value + 'px',\n top: props.elementInfo.start[1] * canvasScale.value + 'px',\n }\n },\n {\n handler: OperateLineHandlers.END,\n style: {\n left: props.elementInfo.end[0] * canvasScale.value + 'px',\n top: props.elementInfo.end[1] * canvasScale.value + 'px',\n }\n },\n ]\n })\n\n return {\n resizeHandlers,\n }\n },\n})\n","import { render } from \"./LineElementOperate.vue?vue&type=template&id=670e07f8\"\nimport script from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'chart-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n resizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./ChartElementOperate.vue?vue&type=template&id=4218643e\"\nimport script from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTTableElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'table-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const outlineWidth = computed(() => props.elementInfo.outline.width || 1)\n\n const scaleWidth = computed(() => (props.elementInfo.width + outlineWidth.value) * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n textElementResizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./TableElementOperate.vue?vue&type=template&id=459ab724\"\nimport script from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\nimport { OperateLineHandler, OperateResizeHandler } from '@/types/edit'\r\n\r\nimport ImageElementOperate from './ImageElementOperate.vue'\r\nimport TextElementOperate from './TextElementOperate.vue'\r\nimport ShapeElementOperate from './ShapeElementOperate.vue'\r\nimport LineElementOperate from './LineElementOperate.vue'\r\nimport ChartElementOperate from './ChartElementOperate.vue'\r\nimport TableElementOperate from './TableElementOperate.vue'\r\n\r\nexport default defineComponent({\r\n name: 'operate',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isSelected: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActive: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const currentOperateComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElementOperate,\r\n [ElementTypes.TEXT]: TextElementOperate,\r\n [ElementTypes.SHAPE]: ShapeElementOperate,\r\n [ElementTypes.LINE]: LineElementOperate,\r\n [ElementTypes.CHART]: ChartElementOperate,\r\n [ElementTypes.TABLE]: TableElementOperate,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const elementIndexInAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n return animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n })\r\n\r\n return {\r\n currentOperateComponent,\r\n canvasScale,\r\n toolbarState,\r\n elementIndexInAnimation,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=558a94fe&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=558a94fe&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-558a94fe\"\n\nexport default script","\nimport { computed, defineComponent, provide, ref, watch, watchEffect } from 'vue'\nimport throttle from 'lodash/throttle'\nimport { MutationTypes, useStore } from '@/store'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { AlignmentLineProps } from '@/types/edit'\nimport { removeAllRanges } from '@/utils/selection'\n\nimport useViewportSize from './hooks/useViewportSize'\nimport useMouseSelection from './hooks/useMouseSelection'\nimport useDropImageOrText from './hooks/useDropImageOrText'\nimport useRotateElement from './hooks/useRotateElement'\nimport useScaleElement from './hooks/useScaleElement'\nimport useSelectElement from './hooks/useSelectElement'\nimport useDragElement from './hooks/useDragElement'\nimport useDragLineElement from './hooks/useDragLineElement'\nimport useInsertFromCreateSelection from './hooks/useInsertFromCreateSelection'\n\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\n\nimport EditableElement from './EditableElement.vue'\nimport MouseSelection from './MouseSelection.vue'\nimport SlideBackground from './SlideBackground.vue'\nimport AlignmentLine from './AlignmentLine.vue'\nimport ElementCreateSelection from './ElementCreateSelection.vue'\nimport MultiSelectOperate from './Operate/MultiSelectOperate.vue'\nimport Operate from './Operate/index.vue'\n\nexport default defineComponent({\n name: 'editor-canvas',\n components: {\n EditableElement,\n MouseSelection,\n SlideBackground,\n AlignmentLine,\n ElementCreateSelection,\n MultiSelectOperate,\n Operate,\n },\n setup() {\n const store = useStore()\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const handleElementId = computed(() => store.state.handleElementId)\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const ctrlKeyState = computed(() => store.state.ctrlKeyState)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n\n const viewportRef = ref()\n const alignmentLines = ref([])\n\n const activeGroupElementId = ref('')\n watch(handleElementId, () => activeGroupElementId.value = '')\n\n const currentSlide = computed(() => store.getters.currentSlide)\n const elementList = ref([])\n const setLocalElementList = () => {\n elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []\n }\n watchEffect(setLocalElementList)\n\n const canvasRef = ref()\n const canvasScale = computed(() => store.state.canvasScale)\n const { viewportStyles } = useViewportSize(canvasRef)\n\n useDropImageOrText(canvasRef)\n\n const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef)\n\n const { dragElement } = useDragElement(elementList, activeGroupElementId, alignmentLines)\n const { dragLineElement } = useDragLineElement(elementList)\n const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)\n const { scaleElement, scaleMultiElement } = useScaleElement(elementList, activeGroupElementId, alignmentLines)\n const { rotateElement } = useRotateElement(elementList, viewportRef)\n\n const { selectAllElement } = useSelectAllElement()\n const { deleteAllElements } = useDeleteElement()\n const { pasteElement } = useCopyAndPasteElement()\n\n const handleClickBlankArea = (e: MouseEvent) => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n if(!ctrlOrShiftKeyActive.value) updateMouseSelection(e)\n if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n removeAllRanges()\n }\n\n const removeEditorAreaFocus = () => {\n if(editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)\n }\n\n const { scaleCanvas } = useScaleCanvas()\n const throttleScaleCanvas = throttle(scaleCanvas, 100, { leading: true, trailing: false })\n\n const mousewheelScaleCanvas = (e: WheelEvent) => {\n if(!ctrlKeyState.value) return\n\n e.preventDefault()\n if(e.deltaY > 0) throttleScaleCanvas('-')\n else if(e.deltaY < 0) throttleScaleCanvas('+')\n }\n\n const showGridLines = computed(() => store.state.showGridLines)\n const toggleGridLines = () => {\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\n }\n\n const creatingElement = computed(() => store.state.creatingElement)\n const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '全选',\n subText: 'Ctrl + A',\n handler: selectAllElement,\n },\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteElement,\n },\n {\n text: showGridLines.value ? '关闭网格线' : '打开网格线',\n handler: toggleGridLines,\n },\n {\n text: '清空本页',\n handler: deleteAllElements,\n },\n ]\n }\n\n provide('slideScale', canvasScale)\n\n return {\n elementList,\n activeElementIdList,\n handleElementId,\n activeGroupElementId,\n canvasRef,\n viewportRef,\n viewportStyles,\n canvasScale,\n mouseSelectionState,\n handleClickBlankArea,\n removeEditorAreaFocus,\n currentSlide,\n creatingElement,\n insertElementFromCreateSelection,\n alignmentLines,\n selectElement,\n rotateElement,\n scaleElement,\n dragLineElement,\n scaleMultiElement,\n mousewheelScaleCanvas,\n contextmenus,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=75c486b2&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=75c486b2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-75c486b2\"\n\nexport default script","\n\n\n\n","\n\n\n\n","export interface ShapePoolItem {\n viewBox: number;\n path: string;\n}\n\nexport const SHAPE_LIST = [\n {\n type: '矩形',\n children: [\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200'\n },\n {\n viewBox: 200,\n path: 'M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z'\n },\n ]\n },\n\n {\n type: '常用形状',\n children: [\n {\n viewBox: 200,\n path: 'M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 200 0 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 Q 200 200 0 200 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 200 L 200 200 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 0 200 L 200 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 200 0 L 150 200 L 0 200 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 150 0 L 200 200 L 0 200 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 100 L 100 200 L 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 90 L 50 200 L 150 200 L 200 90 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 60 L 0 140 L 100 200 L 200 140 L 200 60 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 60 0 L 140 0 L 200 60 L 200 140 L 140 200 L 60 200 L 0 140 L 0 60 L 60 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 50 L 0 200 L 200 200 L 200 50 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 L 0 0 L 150 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 A 50 100 0 0 0 0 0 L 150 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 150 0 L 0 0 L 50 100 L 0 200 L 150 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 0 L 200 200 L 0 200 L 0 100 L 200 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 150 0 L 150 50 L 200 50 L 200 150 L 150 150 L 150 200 L 50 200 L 50 150 L 0 150 L 0 50 L 50 50 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 0 200 L 200 200 L 200 140 L 60 140 L 60 0 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M0 0 L200 0 L200 200 L0 200 L0 0 Z M50 50 L50 150 L150 150 L150 50 Z'\n },\n {\n viewBox: 200,\n path: 'M0 100 A100 100 0 1 1 0 101 Z M150 100 A50 50 0 1 0 150 101 Z'\n },\n {\n viewBox: 200,\n path: 'M 70 0 L 70 70 L 0 70 L 0 130 L 70 130 L 70 200 L 130 200 L 130 130 L 200 130 L 200 70 L 130 70 L 130 0 L 70 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 40 0 L 0 40 L 60 100 L 0 160 L 40 200 L 100 140 L 160 200 L 200 160 L 140 100 L 200 40 L 160 0 L 100 60 L 40 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 L 200 160 L 100 160 L 60 200 L 60 160 L 0 160 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 40 Q 0 0 40 0 L 160 0 Q 200 0 200 40 L 200 120 Q 200 160 160 160 L 100 160 L 60 200 L 60 160 L 40 160 Q 0 160 0 120 L 0 40 Z'\n },\n ],\n },\n \n {\n type: '箭头',\n children: [\n {\n viewBox: 200,\n path: 'M 100 0 L 0 100 L 50 100 L 50 200 L 150 200 L 150 100 L 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 200 L 200 100 L 150 100 L 150 0 L 50 0 L 50 100 L 0 100 L 100 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 200 150 L 100 150 L 100 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 0 150 L 100 150 L 100 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 60 L 60 60 L 60 140 L 0 140 L 100 200 L 200 140 L 140 140 L 140 60 L 200 60 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 60 0 L 60 60 L 140 60 L 140 0 L 200 100 L 140 200 L 140 140 L 60 140 L 60 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 60 40 L 80 40 L 80 80 L 40 80 L 40 60 L 0 100 L 40 140 L 40 120 L 80 120 L 80 160 L 60 160 L 100 200 L 140 160 L 120 160 L 120 120 L 160 120 L 160 140 L 200 100 L 160 60 L 160 80 L 120 80 L 120 40 L 140 40 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 150 100 L 200 150 L 100 150 L 100 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 50 100 L 0 150 L 100 150 L 100 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 80 20 L 80 80 L 120 80 L 120 0 L 200 0 L 200 200 L 120 200 L 120 120 L 80 120 L 80 180 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 120 20 L 120 80 L 80 80 L 80 0 L 0 0 L 0 200 L 80 200 L 80 120 L 120 120 L 120 180 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 120 0 L 200 100 L 120 200 L 0 200 L 80 100 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 80 0 L 200 0 L 120 100 L 200 200 L 80 200 L 0 100 L 80 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 L 200 100 L 140 200 L 0 200 L 0 100 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 60 0 L 200 0 L 200 100 L 200 200 L 60 200 L 0 100 L 60 0 Z'\n },\n ],\n },\n\n {\n type: '其他形状',\n children: [\n {\n viewBox: 1024,\n path: 'M995.336 243.4016c-15.7584-36.5736-38.3376-69.26639999-66.91440001-97.37280001-28.5768-27.98879999-61.73999999-49.8624-98.78399999-65.26799998-38.22-15.876-78.6744-23.8728-120.4224-23.87280001-57.97680001 0-114.5424 15.876-163.69919999 45.864-11.76 7.17360001-22.932 15.05279999-33.51600001 23.63760001-10.584-8.5848-21.75600001-16.46400001-33.51600001-23.63760001-49.1568-29.98799999-105.7224-45.86399999-163.69919999-45.864-41.74799999 0-82.2024 7.9968-120.4224 23.87280001-36.9264 15.28799999-70.2072 37.27919999-98.78399999 65.26799998-28.6944 28.10640001-51.156 60.79919999-66.91440001 97.37280001-16.34639999 37.9848-24.696 78.3216-24.696 119.83439999 0 39.1608 7.9968 79.96800001 23.8728 121.48080001 13.28880001 34.692 32.34000001 70.67760001 56.6832 107.016 38.57279999 57.5064 91.61040001 117.4824 157.4664 178.28160001 109.1328 100.78319999 217.2072 170.4024 221.79359999 173.22479998l27.87120001 17.8752c12.348 7.8792 28.224 7.8792 40.572 0l27.87119999-17.8752c4.58639999-2.94 112.54319999-72.44159999 221.79360001-173.22479998 65.85599999-60.79919999 118.89359999-120.7752 157.4664-178.28160001 24.3432-36.33839999 43.512-72.324 56.68319999-107.016 15.876-41.5128 23.8728-82.32 23.87280001-121.48080001 0.1176-41.5128-8.232-81.8496-24.5784-119.83439999z',\n },\n {\n viewBox: 1024,\n path: 'M985.20746667 343.50079998l-303.32586667-44.08319999L546.28693333 24.5248c-3.70346666-7.5264-9.79626667-13.6192-17.32266665-17.32266668-18.87573334-9.3184-41.81333333-1.55306667-51.25120001 17.32266668L342.1184 299.41759999l-303.32586667 44.08319999c-8.36266667 1.19466667-16.00853333 5.13706667-21.8624 11.11040001-14.69440001 15.17226667-14.45546667 39.30453334 0.71679999 54.1184l219.46026668 213.9648-51.84853333 302.1312c-1.43359999 8.24320001-0.11946667 16.8448 3.82293333 24.25173333 9.79626667 18.6368 32.9728 25.92426667 51.6096 16.00853334L512 822.44266665l271.3088 142.64320001c7.40693333 3.9424 16.00853333 5.25653333 24.25173333 3.82293333 20.78719999-3.584 34.7648-23.296 31.1808-44.0832l-51.84853333-302.1312 219.46026668-213.9648c5.97333334-5.85386666 9.91573333-13.49973334 11.11039999-21.8624 3.2256-20.90666667-11.34933333-40.26026667-32.256-43.36640001z',\n },\n {\n viewBox: 1024,\n path: 'M852.65066667 405.84533333C800.54044445 268.40177778 667.76177778 170.66666667 512.22755555 170.66666667S223.91466667 268.288 171.80444445 405.73155555C74.29688889 431.33155555 2.27555555 520.07822222 2.27555555 625.77777778c0 125.72444445 101.83111111 227.55555555 227.44177778 227.55555555h564.56533334C919.89333333 853.33333333 1021.72444445 751.50222222 1021.72444445 625.77777778c0-105.472-71.79377778-194.21866667-169.07377778-219.93244445z',\n },\n {\n viewBox: 1024,\n path: 'M926.25224691 323.7371485H654.6457886L898.88200917 15.14388241c5.05486373-6.53433603 0.49315743-16.02761669-7.76722963-16.02761668H418.30008701c-3.45210206 0-6.78091476 1.84934039-8.50696579 4.93157436L90.35039154 555.76772251c-3.82197013 6.53433603 0.86302552 14.7947231 8.50696578 14.79472311h215.01664245l-110.22068713 440.88274851c-2.34249783 9.61657002 9.24670194 16.39748478 16.39748477 9.49328065L933.03316167 340.62779071c6.41104668-6.0411786 2.09591911-16.8906422-6.78091476-16.89064221z',\n },\n {\n viewBox: 1024,\n path: 'M878.47822222 463.30311111c-22.18666667-49.83466667-53.93066667-93.98044445-94.32177777-131.072l-33.10933334-30.37866666c-4.89244445-4.32355555-12.62933333-2.38933333-14.79111111 3.75466666l-14.79111111 42.43911111c-9.216 26.624-26.16888889 53.81688889-50.176 80.55466667-1.59288889 1.70666667-3.41333333 2.16177778-4.66488889 2.27555556-1.25155555 0.11377778-3.18577778-0.11377778-4.89244445-1.70666667-1.59288889-1.36533333-2.38933333-3.41333333-2.27555555-5.46133333 4.20977778-68.49422222-16.27022222-145.74933333-61.09866667-229.83111112C561.26577778 124.01777778 509.72444445 69.51822222 445.32622222 31.51644445l-46.99022222-27.648c-6.144-3.64088889-13.99466667 1.13777778-13.65333333 8.30577777l2.50311111 54.61333333c1.70666667 37.31911111-2.61688889 70.31466667-12.85688889 97.73511112-12.51555555 33.56444445-30.49244445 64.73955555-53.47555556 92.72888888-16.15644445 19.56977778-34.24711111 37.20533333-54.04444444 52.45155556-47.90044445 36.75022222-87.38133333 84.65066667-114.11911111 138.24C125.72444445 502.10133333 111.50222222 562.74488889 111.50222222 623.50222222c0 53.70311111 10.58133333 105.69955555 31.51644445 154.73777778 20.25244445 47.21777778 49.152 89.77066667 85.90222222 126.17955555 36.864 36.40888889 79.64444445 65.08088889 127.31733333 84.992C405.61777778 1010.11911111 457.95555555 1020.58666667 512 1020.58666667s106.38222222-10.46755555 155.76177778-31.06133334c47.67288889-19.91111111 90.56711111-48.46933333 127.31733333-84.992 36.864-36.40888889 65.76355555-78.96177778 85.90222222-126.17955555 20.93511111-49.03822222 31.51644445-101.03466667 31.51644445-154.73777778 0-55.52355555-11.37777778-109.45422222-34.01955556-160.31288889z',\n },\n {\n viewBox: 1024,\n path: 'M968.20337778 20.11591112H705.44042667c-22.17301333 0-41.92483556 15.16430222-47.14951111 37.33731555C642.36202666 124.73685332 582.08711111 173.03324444 512 173.03324444s-130.36202666-48.29639112-146.29091556-115.58001777c-5.22467555-22.17301333-24.84906667-37.33731556-47.14951111-37.33731555H55.79662222c-30.96576 0-56.06968889 25.10392889-56.06968888 56.06968888v321.12639999c0 30.96576 25.10392889 56.06968889 56.06968888 56.06968889h95.57333334v494.43271112c0 30.96576 25.10392889 56.06968889 56.06968889 56.06968888h609.1207111c30.96576 0 56.06968889-25.10392889 56.06968889-56.06968888V453.38168888h95.57333334c30.96576 0 56.06968889-25.10392889 56.06968888-56.06968889V76.1856c0-30.96576-25.10392889-56.06968889-56.06968888-56.06968888z',\n },\n {\n viewBox: 1024,\n path: 'M980.94648889 239.80714666H523.46880001L373.99210666 96.82944c-1.91146667-1.78403556-4.46008889-2.80348444-7.00871111-2.80348445H43.05351111c-22.55530667 0-40.77795555 18.22264888-40.77795555 40.77795557v754.39217776c0 22.55530667 18.22264888 40.77795555 40.77795555 40.77795557h937.89297778c22.55530667 0 40.77795555-18.22264888 40.77795555-40.77795557V280.58510222c0-22.55530667-18.22264888-40.77795555-40.77795555-40.77795556z',\n },\n {\n viewBox: 1024,\n path: 'M972.60904597 164.57058577L841.30587843 33.39070759c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480282-29.3428675-26.75379095 0-51.90482023 10.47959553-70.76809219 29.3428675L558.60337778 174.68031322c-18.86327195 18.86327195-29.34286748 44.1375906-29.34286749 70.64480283 0 26.75379095 10.47959553 51.90482023 29.34286749 70.76809218l103.31648301 103.31648302c-24.28800376 53.50758189-57.69942011 101.59043198-99.24793416 143.13894603-41.42522469 41.67180341-89.63136414 75.08321976-143.13894603 99.61780223L316.21649759 558.84995649c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480283-29.34286747-26.75379095 0-51.90482023 10.47959553-70.76809217 29.34286747L33.39070759 700.01627278c-18.86327195 18.86327195-29.34286748 44.1375906-29.3428675 70.76809217 0 26.75379095 10.47959553 51.90482023 29.3428675 70.76809219l131.05658883 131.05658883c30.08260365 30.205893 71.63111769 47.34311394 114.28923598 47.34311394 9.00012323 0 17.63037836-0.73973616 26.13734414-2.21920846 166.19405621-27.37023774 331.03192945-115.76870829 464.06114804-248.67463751C901.84095379 636.27567408 990.11613498 471.56109018 1017.85624079 304.87387654c8.38367642-50.91850535-8.50696579-103.31648302-45.24719482-140.30329077z',\n },\n {\n viewBox: 1024,\n path: 'M910.60451556 640.96028445c-20.38897778-65.49959112-43.83630221-120.54983112-79.89930667-210.64362666C836.31217778 193.67708444 737.93535999 2.27555556 511.36284444 2.27555556 282.24170667 2.27555556 186.03121778 197.50001778 192.14791111 430.31665779c-36.19043555 90.22122667-59.51032888 144.88917333-79.89930667 210.64362666-43.32657778 139.53706668-29.30915556 197.26336001-18.60494222 198.53767111 22.9376 2.80348444 89.32920888-105.00323556 89.32920889-105.00323556 0 62.44124445 32.11264001 143.86972444 101.69002667 202.61546667-33.64181333 10.32192-109.20846222 38.10190221-91.24067556 68.55793777 14.52714667 24.59420444 250.01984 15.67402668 317.94062222 8.02816 67.92078222 7.64586667 303.41347556 16.56604444 317.94062223-8.02816 17.96778667-30.32860444-57.72629333-58.23601779-91.24067555-68.55793777 69.57738667-58.87317334 101.69002667-140.30165333 101.69002667-202.61546667 0 0 66.39160889 107.80672 89.32920888 105.00323556 10.83164445-1.40174222 24.84906667-59.12803556-18.47751111-198.53767111z',\n },\n {\n viewBox: 1024,\n path: 'M1016.86992592 199.24764445c-37.13706667 16.01991111-77.55093333 27.54939259-119.17842962 32.03982222 42.96248889-25.60758518 75.60912592-66.02145185 91.02222222-114.08118519-39.68568889 23.66577778-84.58998518 41.02068148-131.31472593 50.00154074C819.53374815 126.79395555 765.76995555 101.79318518 706.18074075 101.79318518c-114.688 0-206.92385185 92.96402963-206.92385186 207.04521482 0 16.01991111 1.94180741 32.03982222 5.09724444 47.45291852-171.72859259-8.98085925-324.88865185-91.02222222-426.71217778-216.63288889-17.96171852 30.82619259-28.15620741 66.02145185-28.1562074 104.49351112 0 71.84687408 36.53025185 135.19834075 92.23585185 172.45677036-33.98162963-1.33499259-66.02145185-10.92266667-93.57084445-26.33576296v2.54862222c0 100.6098963 71.1186963 183.98625185 165.90317037 203.1616-17.3549037 4.49042963-35.92343703 7.03905185-54.49197037 7.03905185-13.47128889 0-26.2144-1.33499259-39.07887407-3.15543704C146.69748148 681.90814815 223.03478518 741.49736297 313.93564445 743.43917037c-71.1186963 55.7056-160.19911111 88.4736-256.9253926 88.4736-17.3549037 0-33.37481482-0.60681482-50.00154074-2.54862222C98.75911111 888.22518518 207.62168889 922.20681482 324.85831111 922.20681482 705.45256297 922.20681482 913.71140741 606.90583703 913.71140741 333.23235555c0-8.98085925 0-17.96171852-0.60681482-26.94257777 40.2925037-29.4912 75.60912592-66.02145185 103.76533333-107.04213333z',\n },\n ],\n },\n]","\nimport { defineComponent } from 'vue'\nimport { SHAPE_LIST, ShapePoolItem } from '@/configs/shapes'\n\nexport default defineComponent({\n name: 'shape-pool',\n setup(props, { emit }) {\n const shapeList = SHAPE_LIST\n\n const selectShape = (shape: ShapePoolItem) => {\n emit('select', shape)\n }\n\n return {\n shapeList,\n selectShape,\n }\n },\n})\n","import { render } from \"./ShapePool.vue?vue&type=template&id=e95c032e&scoped=true\"\nimport script from \"./ShapePool.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapePool.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapePool.vue?vue&type=style&index=0&id=e95c032e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-e95c032e\"\n\nexport default script","\n\n\n\n","export interface LinePoolItem {\n path: string;\n style: string;\n points: [string, string];\n}\n\nexport const LINE_LIST = [\n { path: 'M0,0 L20,20', style: 'solid', points: ['', ''] },\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', ''] },\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'arrow'] },\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', 'arrow'] },\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'dot'] },\n]","\nimport { defineComponent } from 'vue'\nimport { LINE_LIST, LinePoolItem } from '@/configs/lines'\n\nimport LinePointMarker from '@/views/components/element/LineElement/LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'line-pool',\n components: {\n LinePointMarker,\n },\n setup(props, { emit }) {\n const lineList = LINE_LIST\n\n const selectLine = (line: LinePoolItem) => {\n emit('select', line)\n }\n\n return {\n lineList,\n selectLine,\n }\n },\n})\n","import { render } from \"./LinePool.vue?vue&type=template&id=a0f5af54&scoped=true\"\nimport script from \"./LinePool.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePool.vue?vue&type=script&lang=ts\"\n\nimport \"./LinePool.vue?vue&type=style&index=0&id=a0f5af54&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a0f5af54\"\n\nexport default script","\n\n\n\n","\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n name: 'chart-pool',\n setup(props, { emit }) {\n const chartList = ['bar', 'line', 'pie']\n\n const selectChart = (chart: string) => {\n emit('select', chart)\n }\n\n return {\n chartList,\n selectChart,\n }\n },\n})\n","import { render } from \"./ChartPool.vue?vue&type=template&id=28a1a821&scoped=true\"\nimport script from \"./ChartPool.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartPool.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartPool.vue?vue&type=style&index=0&id=28a1a821&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-28a1a821\"\n\nexport default script","\n\n\n\n","\nimport { defineComponent, ref } from 'vue'\n\nimport { message } from 'ant-design-vue'\n\nexport default defineComponent({\n name: 'table-generator',\n setup(props, { emit }) {\n const endCell = ref([])\n const customRow = ref(3)\n const customCol = ref(3)\n const isCustom = ref(false)\n\n const handleClickTable = () => {\n if(!endCell.value.length) return\n const [row, col] = endCell.value\n emit('insert', { row, col })\n }\n\n const insertCustomTable = () => {\n if(customRow.value < 1 || customRow.value > 20) return message.warning('行数/列数必须在0~20之间!')\n if(customCol.value < 1 || customCol.value > 20) return message.warning('行数/列数必须在0~20之间!')\n emit('insert', { row: customRow.value, col: customCol.value })\n isCustom.value = false\n }\n\n const close = () => {\n emit('close')\n isCustom.value = false\n }\n\n return {\n endCell,\n customRow,\n customCol,\n handleClickTable,\n insertCustomTable,\n isCustom,\n close,\n }\n },\n})\n","import { render } from \"./TableGenerator.vue?vue&type=template&id=0239b43b&scoped=true\"\nimport script from \"./TableGenerator.vue?vue&type=script&lang=ts\"\nexport * from \"./TableGenerator.vue?vue&type=script&lang=ts\"\n\nimport \"./TableGenerator.vue?vue&type=style&index=0&id=0239b43b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0239b43b\"\n\nexport default script","\nimport { defineComponent, computed, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport { ShapePoolItem } from '@/configs/shapes'\nimport { LinePoolItem } from '@/configs/lines'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nimport ShapePool from './ShapePool.vue'\nimport LinePool from './LinePool.vue'\nimport ChartPool from './ChartPool.vue'\nimport TableGenerator from './TableGenerator.vue'\n\nexport default defineComponent({\n name: 'canvas-tool',\n components: {\n ShapePool,\n LinePool,\n ChartPool,\n TableGenerator,\n },\n setup() {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const canUndo = computed(() => store.getters.canUndo)\n const canRedo = computed(() => store.getters.canRedo)\n\n const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')\n\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\n const { redo, undo } = useHistorySnapshot()\n\n const { createImageElement, createChartElement, createTableElement } = useCreateElement()\n\n const insertImageElement = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n\n const shapePoolVisible = ref(false)\n const linePoolVisible = ref(false)\n const chartPoolVisible = ref(false)\n const tableGeneratorVisible = ref(false)\n\n const drawText = () => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'text',\n data: null,\n })\n }\n const drawShape = (shape: ShapePoolItem) => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'shape',\n data: shape,\n })\n shapePoolVisible.value = false\n }\n const drawLine = (line: LinePoolItem) => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'line',\n data: line,\n })\n linePoolVisible.value = false\n }\n\n return {\n scaleCanvas,\n setCanvasPercentage,\n canvasScalePercentage,\n canUndo,\n canRedo,\n redo,\n undo,\n insertImageElement,\n shapePoolVisible,\n linePoolVisible,\n chartPoolVisible,\n tableGeneratorVisible,\n drawText,\n drawShape,\n drawLine,\n createChartElement,\n createTableElement,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=1a2df855&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=1a2df855&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1a2df855\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\n\nimport { PPTImageElement } from '@/types/slides'\nimport { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'\n\nimport ImageRectOutline from './ImageRectOutline.vue'\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\n\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nexport default defineComponent({\n name: 'base-element-image',\n components: {\n ImageRectOutline,\n ImageEllipseOutline,\n ImagePolygonOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const imgPosition = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) {\n return {\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n }\n }\n\n const [start, end] = props.elementInfo.clip.range\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return {\n left: -left + '%',\n top: -top + '%',\n width: 100 / widthScale + '%',\n height: 100 / heightScale + '%',\n }\n })\n\n const clipShape = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect\n const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT\n\n return CLIPPATHS[shape]\n })\n\n const filter = computed(() => {\n if(!props.elementInfo.filters) return ''\n let filter = ''\n for(const key of Object.keys(props.elementInfo.filters)) {\n filter += `${key}(${props.elementInfo.filters[key]}) `\n }\n return filter\n })\n\n const flip = computed(() => {\n if(!props.elementInfo.flip) return ''\n const { x, y } = props.elementInfo.flip\n if(x && y) return `rotateX(${x}deg) rotateY(${y}deg)`\n else if(x) return `rotateX(${x}deg)`\n else if(y) return `rotateY(${y}deg)`\n return ''\n })\n\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n imgPosition,\n clipShape,\n filter,\n flip,\n shadowStyle,\n }\n },\n})\n","import { render } from \"./BaseImageElement.vue?vue&type=template&id=008489be&scoped=true\"\nimport script from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseImageElement.vue?vue&type=style&index=0&id=008489be&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-008489be\"\n\nexport default script","\n\n\n\n\n","\nimport { defineComponent, PropType, computed } from 'vue'\nimport { PPTTextElement } from '@/types/slides'\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\n\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nexport default defineComponent({\n name: 'base-element-text',\n components: {\n ElementOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n shadowStyle,\n }\n },\n})\n","import { render } from \"./BaseTextElement.vue?vue&type=template&id=fc2d45e0&scoped=true\"\nimport script from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTextElement.vue?vue&type=style&index=0&id=fc2d45e0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-fc2d45e0\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTShapeElement } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport GradientDefs from './GradientDefs.vue'\n\nexport default defineComponent({\n name: 'base-element-shape',\n components: {\n GradientDefs,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const outline = computed(() => props.elementInfo.outline)\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n shadowStyle,\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./BaseShapeElement.vue?vue&type=template&id=a34ea4ec&scoped=true\"\nimport script from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseShapeElement.vue?vue&type=style&index=0&id=a34ea4ec&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a34ea4ec\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTLineElement } from '@/types/slides'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport LinePointMarker from './LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n LinePointMarker,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const svgWidth = computed(() => {\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\n return width < 24 ? 24 : width\n })\n const svgHeight = computed(() => {\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\n return height < 24 ? 24 : height\n })\n\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\n const path = computed(() => {\n const start = props.elementInfo.start.join(',')\n const end = props.elementInfo.end.join(',')\n return `M${start} L${end}`\n })\n\n return {\n shadowStyle,\n svgWidth,\n svgHeight,\n lineDashArray,\n path,\n }\n },\n})\n","import { render } from \"./BaseLineElement.vue?vue&type=template&id=103a3e59&scoped=true\"\nimport script from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseLineElement.vue?vue&type=style&index=0&id=103a3e59&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-103a3e59\"\n\nexport default script","\r\n\r\n\r\n\r\n\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-chart',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const size = computed(() => Math.min(props.elementInfo.width, props.elementInfo.height))\r\n\r\n return {\r\n size,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseChartElement.vue?vue&type=template&id=b4562eca&scoped=true\"\nimport script from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseChartElement.vue?vue&type=style&index=0&id=b4562eca&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b4562eca\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent, PropType, ref, watch } from 'vue'\nimport tinycolor from 'tinycolor2'\nimport { PPTElementOutline, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\n\nexport default defineComponent({\n name: 'static-table',\n props: {\n data: {\n type: Array as PropType,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n colWidths: {\n type: Array as PropType,\n required: true,\n },\n outline: {\n type: Object as PropType,\n required: true,\n },\n theme: {\n type: Object as PropType,\n },\n editable: {\n type: Boolean,\n default: true,\n },\n },\n setup(props) {\n const colSizeList = ref([])\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\n\n watch([\n () => props.colWidths,\n () => props.width,\n ], () => {\n colSizeList.value = props.colWidths.map(item => item * props.width)\n }, { immediate: true })\n\n const hideCells = computed(() => {\n const hideCells = []\n \n for(let i = 0; i < props.data.length; i++) {\n const rowCells = props.data[i]\n\n for(let j = 0; j < rowCells.length; j++) {\n const cell = rowCells[j]\n \n if(cell.colspan > 1 || cell.rowspan > 1) {\n for(let row = i; row < i + cell.rowspan; row++) {\n for(let col = row === i ? j + 1 : j; col < j + cell.colspan; col++) {\n hideCells.push(`${row}_${col}`)\n }\n }\n }\n }\n }\n return hideCells\n })\n\n const subThemeColor = ref(['', ''])\n watch(() => props.theme, () => {\n if(props.theme) {\n const rgba = tinycolor(props.theme.color).toRgb()\n const subRgba1 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.3 }\n const subRgba2 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.1 }\n subThemeColor.value = [\n `rgba(${[subRgba1.r, subRgba1.g, subRgba1.b, subRgba1.a].join(',')})`,\n `rgba(${[subRgba2.r, subRgba2.g, subRgba2.b, subRgba2.a].join(',')})`,\n ]\n }\n }, { immediate: true })\n\n const getTextStyle = (style?: TableCellStyle) => {\n if(!style) return {}\n const {\n bold,\n em,\n underline,\n strikethrough,\n color,\n backcolor,\n fontsize,\n fontname,\n align,\n } = style\n \n return {\n fontWeight: bold ? 'bold' : 'normal',\n fontStyle: em ? 'italic' : 'normal',\n textDecoration: `${underline ? 'underline' : ''} ${strikethrough ? 'line-through' : ''}`,\n color: color || '#000',\n backgroundColor: backcolor || '',\n fontSize: fontsize || '14px',\n fontFamily: fontname || '微软雅黑',\n textAlign: align || 'left',\n }\n }\n\n return {\n colSizeList,\n totalWidth,\n hideCells,\n getTextStyle,\n subThemeColor,\n }\n },\n})\n","import { render } from \"./StaticTable.vue?vue&type=template&id=12bfa92e&scoped=true\"\nimport script from \"./StaticTable.vue?vue&type=script&lang=ts\"\nexport * from \"./StaticTable.vue?vue&type=script&lang=ts\"\n\nimport \"./StaticTable.vue?vue&type=style&index=0&id=12bfa92e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-12bfa92e\"\n\nexport default script","\nimport { defineComponent, PropType } from 'vue'\nimport { PPTTableElement } from '@/types/slides'\n\nimport StaticTable from './StaticTable.vue'\n\nexport default defineComponent({\n name: 'base-element-table',\n components: {\n StaticTable,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n})\n","import { render } from \"./BaseTableElement.vue?vue&type=template&id=dea016ac&scoped=true\"\nimport script from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTableElement.vue?vue&type=style&index=0&id=dea016ac&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dea016ac\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\n\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\nimport BaseChartElement from '@/views/components/element/ChartElement/BaseChartElement.vue'\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\n\nexport default defineComponent({\n name: 'base-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const theme = computed(() => store.state.theme)\n\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: BaseImageElement,\n [ElementTypes.TEXT]: BaseTextElement,\n [ElementTypes.SHAPE]: BaseShapeElement,\n [ElementTypes.LINE]: BaseLineElement,\n [ElementTypes.CHART]: BaseChartElement,\n [ElementTypes.TABLE]: BaseTableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n return {\n currentElementComponent,\n theme,\n }\n },\n})\n","import { render } from \"./ThumbnailElement.vue?vue&type=template&id=43292aca\"\nimport script from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nimport ThumbnailElement from './ThumbnailElement.vue'\n\nexport default defineComponent({\n name: 'thumbnail-slide',\n components: {\n ThumbnailElement,\n },\n props: {\n slide: {\n type: Object as PropType,\n required: true,\n },\n size: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const background = computed(() => props.slide.background)\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n const scale = computed(() => props.size / VIEWPORT_SIZE)\n\n return {\n scale,\n backgroundStyle,\n VIEWPORT_SIZE,\n VIEWPORT_ASPECT_RATIO,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=1debfb1c&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=1debfb1c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1debfb1c\"\n\nexport default script","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { fillDigit } from '@/utils/common'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useScreening from '@/hooks/useScreening'\n\nimport Draggable from 'vuedraggable'\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\n\nexport default defineComponent({\n name: 'thumbnails',\n components: {\n Draggable,\n ThumbnailSlide,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n\n const {\n copySlide,\n pasteSlide,\n createSlide,\n copyAndPasteSlide,\n deleteSlide,\n cutSlide,\n } = useSlideHandler()\n\n const changSlideIndex = (index: number) => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n\n if(slideIndex.value === index) return\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n }\n\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n\n const setThumbnailsFocus = (focus: boolean) => {\n if(thumbnailsFocus.value === focus) return\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, focus)\n }\n\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\n const { newIndex, oldIndex } = eventData\n if(oldIndex === newIndex) return\n\n const _slides = JSON.parse(JSON.stringify(slides.value))\n const _slide = _slides[oldIndex]\n _slides.splice(oldIndex, 1)\n _slides.splice(newIndex, 0, _slide)\n store.commit(MutationTypes.SET_SLIDES, _slides)\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)\n }\n\n const { enterScreening } = useScreening()\n\n const contextmenusThumbnails = (): ContextmenuItem[] => {\n return [\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteSlide,\n },\n {\n text: '新建页面',\n subText: 'Enter',\n handler: createSlide,\n },\n ]\n }\n\n const contextmenusThumbnailItem = (): ContextmenuItem[] => {\n return [\n {\n text: '剪切',\n subText: 'Ctrl + X',\n handler: cutSlide,\n },\n {\n text: '复制',\n subText: 'Ctrl + C',\n handler: copySlide,\n },\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteSlide,\n },\n { divider: true },\n {\n text: '新建页面',\n subText: 'Enter',\n handler: createSlide,\n },\n {\n text: '复制页面',\n handler: copyAndPasteSlide,\n },\n {\n text: '删除页面',\n subText: 'Delete',\n handler: deleteSlide,\n },\n { divider: true },\n {\n text: '从本页演示',\n subText: 'Ctrl+F',\n handler: enterScreening,\n },\n ]\n }\n\n return {\n setThumbnailsFocus,\n slides,\n slideIndex,\n createSlide,\n changSlideIndex,\n contextmenusThumbnails,\n contextmenusThumbnailItem,\n fillDigit,\n handleDragEnd,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=6821a1b4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=6821a1b4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6821a1b4\"\n\nexport default script","\n\n\n\n","export type ToolbarState = 'elAnimation' | 'elStyle' | 'elPosition' | 'slideStyle' | 'slideAnimation' | 'multiPosition'\n\nexport const ToolbarStates = {\n EL_ANIMATION: 'elAnimation',\n EL_STYLE: 'elStyle',\n EL_POSITION: 'elPosition',\n SLIDE_STYLE: 'slideStyle',\n SLIDE_ANIMATION: 'slideAnimation',\n MULTI_POSITION: 'multiPosition',\n}","\n\n","\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'element-opacity',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const opacity = ref()\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n opacity.value = 'opacity' in handleElement.value && handleElement.value.opacity !== undefined ? handleElement.value.opacity : 1\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateOpacity = (value: number) => {\n const props = { opacity: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n opacity,\n updateOpacity,\n }\n },\n})\n","import { render } from \"./ElementOpacity.vue?vue&type=template&id=4b901be6&scoped=true\"\nimport script from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOpacity.vue?vue&type=style&index=0&id=4b901be6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4b901be6\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\nexport default {\n name: 'color-button',\n props: {\n color: {\n type: String,\n required: true,\n },\n },\n}\n","import { render } from \"./ColorButton.vue?vue&type=template&id=39016b60&scoped=true\"\nimport script from \"./ColorButton.vue?vue&type=script&lang=ts\"\nexport * from \"./ColorButton.vue?vue&type=script&lang=ts\"\n\nimport \"./ColorButton.vue?vue&type=style&index=0&id=39016b60&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-39016b60\"\n\nexport default script","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTElementOutline } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './ColorButton.vue'\n\nexport default defineComponent({\n name: 'element-outline',\n components: {\n ColorButton,\n },\n props: {\n fixed: {\n type: Boolean,\n default: false,\n },\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const outline = ref()\n const hasOutline = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n outline.value = 'outline' in handleElement.value ? handleElement.value.outline : undefined\n hasOutline.value = !!outline.value\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateOutline = (outlineProps: Partial) => {\n const props = { outline: { ...outline.value, ...outlineProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleOutline = (checked: boolean) => {\n if(checked) {\n const props = { outline: { width: 2, color: '#000', style: 'solid' } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'outline' })\n }\n addHistorySnapshot()\n }\n\n return {\n outline,\n hasOutline,\n toggleOutline,\n updateOutline,\n }\n },\n})\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=38e2f880&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=38e2f880&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-38e2f880\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTElementShadow } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './ColorButton.vue'\n\nexport default defineComponent({\n name: 'element-shadow',\n components: {\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const shadow = ref()\n const hasShadow = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n shadow.value = 'shadow' in handleElement.value ? handleElement.value.shadow : undefined\n hasShadow.value = !!shadow.value\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateShadow = (shadowProps: Partial) => {\n const props = { shadow: { ...shadow.value, ...shadowProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleShadow = (checked: boolean) => {\n if(checked) {\n const props = { shadow: { h: 1, v: 1, blur: 2, color: '#000' } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'shadow' })\n }\n addHistorySnapshot()\n }\n\n return {\n shadow,\n hasShadow,\n toggleShadow,\n updateShadow,\n }\n },\n})\n","import { render } from \"./ElementShadow.vue?vue&type=template&id=02448be4&scoped=true\"\nimport script from \"./ElementShadow.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementShadow.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementShadow.vue?vue&type=style&index=0&id=02448be4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-02448be4\"\n\nexport default script","\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTextElement } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { TextAttrs } from '@/prosemirror/utils'\nimport { WEB_FONTS } from '@/configs/font'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOpacity from '../common/ElementOpacity.vue'\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\n\nconst presetStyles = [\n {\n label: '大标题',\n style: {\n fontSize: '26px',\n fontWeight: 700,\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '48px' },\n { command: 'align', value: 'center' },\n { command: 'bold' },\n ],\n },\n {\n label: '小标题',\n style: {\n fontSize: '22px',\n fontWeight: 700,\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '36px' },\n { command: 'align', value: 'center' },\n { command: 'bold' },\n ],\n },\n {\n label: '正文',\n style: {\n fontSize: '20px',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '20px' },\n ],\n },\n {\n label: '正文[小]',\n style: {\n fontSize: '18px',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '18px' },\n ],\n },\n {\n label: '注释 1',\n style: {\n fontSize: '16px',\n fontStyle: 'italic',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '16px' },\n { command: 'em' },\n ],\n },\n {\n label: '注释 2',\n style: {\n fontSize: '16px',\n textDecoration: 'underline',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '16px' },\n { command: 'underline' },\n ],\n },\n]\n\nconst webFonts = WEB_FONTS\n\ninterface CommandPayload {\n command: string;\n value?: string;\n}\n\nexport default defineComponent({\n name: 'text-style-panel',\n components: {\n ElementOpacity,\n ElementOutline,\n ElementShadow,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const fill = ref()\n const lineHeight = ref()\n const wordSpace = ref()\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'text') return\n\n fill.value = handleElement.value.fill || '#000'\n lineHeight.value = handleElement.value.lineHeight || 1.5\n wordSpace.value = handleElement.value.wordSpace || 0\n }, { deep: true, immediate: true })\n\n const richTextAttrs = ref({\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n superscript: false,\n subscript: false,\n code: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n bulletList: false,\n orderedList: false,\n blockquote: false,\n })\n\n const availableFonts = computed(() => store.state.availableFonts)\n const fontSizeOptions = [\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\n '36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '80px',\n ]\n const lineHeightOptions = [0.5, 1.0, 1.2, 1.5, 1.8, 2.0, 3.0]\n const wordSpaceOptions = [0, 1, 2, 3, 4, 5, 8]\n\n const updateRichTextAttrs = (attr: TextAttrs) => richTextAttrs.value = attr\n\n emitter.on(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\n onUnmounted(() => {\n emitter.off(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\n })\n\n const emitRichTextCommand = (command: string, value?: string) => {\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value })\n }\n\n const emitBatchRichTextCommand = (payload: CommandPayload[]) => {\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, payload)\n }\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLineHeight = (value: number) => {\n const props = { lineHeight: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateWordSpace = (value: number) => {\n const props = { wordSpace: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n fill,\n lineHeight,\n wordSpace,\n richTextAttrs,\n availableFonts,\n webFonts,\n fontSizeOptions,\n lineHeightOptions,\n wordSpaceOptions,\n updateLineHeight,\n updateWordSpace,\n updateFill,\n emitRichTextCommand,\n emitBatchRichTextCommand,\n presetStyles,\n }\n },\n})\n","import { render } from \"./TextStylePanel.vue?vue&type=template&id=382a7e56&scoped=true\"\nimport script from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TextStylePanel.vue?vue&type=style&index=0&id=382a7e56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-382a7e56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTImageElement, Slide } from '@/types/slides'\nimport { CLIPPATHS } from '@/configs/imageClip'\nimport { getImageDataURL } from '@/utils/image'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\n\ninterface FilterOption {\n label: string;\n key: string;\n default: number;\n value: number;\n unit: string;\n max: number;\n step: number;\n}\n\nconst defaultFilters: FilterOption[] = [\n { label: '模糊', key: 'blur', default: 0, value: 0, unit: 'px', max: 10, step: 1 },\n { label: '亮度', key: 'brightness', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '对比度', key: 'contrast', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '灰度', key: 'grayscale', default: 0, value: 0, unit: '%', max: 100, step: 5 },\n { label: '饱和度', key: 'saturate', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '色相', key: 'hue-rotate', default: 0, value: 0, unit: 'deg', max: 360, step: 10 },\n { label: '不透明度', key: 'opacity', default: 100, value: 100, unit: '%', max: 100, step: 5 },\n]\n\nconst shapeClipPathOptions = CLIPPATHS\nconst ratioClipOptions = [\n {\n label: '纵横比(方形)',\n children: [\n { key: '1:1', ratio: 1 / 1 },\n ],\n },\n {\n label: '纵横比(纵向)',\n children: [\n { key: '2:3', ratio: 3 / 2 },\n { key: '3:4', ratio: 4 / 3 },\n { key: '3:5', ratio: 5 / 3 },\n { key: '4:5', ratio: 5 / 4 },\n ],\n },\n {\n label: '纵横比(横向)',\n children: [\n { key: '3:2', ratio: 2 / 3 },\n { key: '4:3', ratio: 3 / 4 },\n { key: '5:3', ratio: 3 / 5 },\n { key: '5:4', ratio: 4 / 5 },\n ],\n },\n {\n children: [\n { key: '16:9', ratio: 9 / 16 },\n { key: '16:10', ratio: 10 / 16 },\n ],\n },\n]\n\nexport default defineComponent({\n name: 'image-style-panel',\n components: {\n ElementOutline,\n ElementShadow,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const clipPanelVisible = ref(false)\n\n const flip = ref({\n x: 0,\n y: 0,\n })\n\n const filterOptions = ref(JSON.parse(JSON.stringify(defaultFilters)))\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'image') return\n\n if(handleElement.value.flip) {\n flip.value = {\n x: handleElement.value.flip.x || 0,\n y: handleElement.value.flip.y || 0,\n }\n }\n else flip.value = { x: 0, y: 0 }\n\n const filters = handleElement.value.filters\n if(filters) {\n filterOptions.value = defaultFilters.map(item => {\n if(filters[item.key] !== undefined) return { ...item, value: parseInt(filters[item.key]) }\n return item\n })\n }\n else filterOptions.value = JSON.parse(JSON.stringify(defaultFilters))\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateImage = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFilter = (filter: FilterOption, value: number) => {\n const originFilters = handleElement.value.filters || {}\n const filters = { ...originFilters, [filter.key]: `${value}${filter.unit}` }\n const props = { filters }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const clipImage = () => {\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, handleElement.value.id)\n clipPanelVisible.value = false\n }\n\n const getImageElementDataBeforeClip = () => {\n // 图片当前宽高位置、裁剪范围\n const imgWidth = handleElement.value.width\n const imgHeight = handleElement.value.height\n const imgLeft = handleElement.value.left\n const imgTop = handleElement.value.top\n const originClipRange = handleElement.value.clip ? handleElement.value.clip.range : [[0, 0], [100, 100]]\n\n // 图片原本未裁剪过时的宽高位置\n const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)\n const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)\n const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100)\n const originTop = imgTop - originHeight * (originClipRange[0][1] / 100)\n\n return {\n originClipRange,\n originWidth,\n originHeight,\n originLeft,\n originTop,\n }\n }\n\n const presetImageClip = (shape: string, ratio = 0) => {\n const {\n originClipRange,\n originWidth,\n originHeight,\n originLeft,\n originTop,\n } = getImageElementDataBeforeClip()\n \n // 设置形状和纵横比\n if(ratio) {\n const imageRatio = originHeight / originWidth\n\n const min = 0\n const max = 100\n let range\n\n if(imageRatio > ratio) {\n const distance = ((1 - ratio / imageRatio) / 2) * 100\n range = [[min, distance], [max, max - distance]]\n }\n else {\n const distance = ((1 - imageRatio / ratio) / 2) * 100\n range = [[distance, min], [max - distance, max]]\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n clip: { ...handleElement.value.clip, shape, range },\n left: originLeft + originWidth * (range[0][0] / 100),\n top: originTop + originHeight * (range[0][1] / 100),\n width: originWidth * (range[1][0] - range[0][0]) / 100,\n height: originHeight * (range[1][1] - range[0][1]) / 100,\n },\n })\n }\n // 仅设置形状(维持目前的裁剪范围)\n else {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n clip: { ...handleElement.value.clip, shape, range: originClipRange }\n },\n })\n }\n clipImage()\n addHistorySnapshot()\n }\n\n const replaceImage = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => {\n const props = { src: dataURL }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n })\n addHistorySnapshot()\n }\n\n const resetImage = () => {\n if(handleElement.value.clip) {\n const {\n originWidth,\n originHeight,\n originLeft,\n originTop,\n } = getImageElementDataBeforeClip()\n\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n left: originLeft,\n top: originTop,\n width: originWidth,\n height: originHeight,\n },\n })\n }\n\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\n id: handleElement.value.id,\n propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],\n })\n addHistorySnapshot()\n }\n\n const setBackgroundImage = () => {\n const background = {\n ...currentSlide.value.background,\n type: 'image',\n image: handleElement.value.src,\n imageSize: 'cover',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background })\n addHistorySnapshot()\n }\n\n return {\n clipPanelVisible,\n shapeClipPathOptions,\n ratioClipOptions,\n filterOptions,\n flip,\n handleElement,\n updateImage,\n updateFilter,\n clipImage,\n presetImageClip,\n replaceImage,\n resetImage,\n setBackgroundImage,\n }\n },\n})\n","import { render } from \"./ImageStylePanel.vue?vue&type=template&id=af9fc43e&scoped=true\"\nimport script from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageStylePanel.vue?vue&type=style&index=0&id=af9fc43e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-af9fc43e\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTShapeElement, ShapeGradient } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOpacity from '../common/ElementOpacity.vue'\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'shape-style-panel',\n components: {\n ElementOpacity,\n ElementOutline,\n ElementShadow,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const fill = ref()\n const gradient = ref()\n const fillType = ref('fill')\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'shape') return\n fill.value = handleElement.value.fill || '#000'\n\n gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }\n\n fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateFillType = (type: 'gradient' | 'fill') => {\n if(type === 'fill') {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\n id: handleElement.value.id,\n propName: 'gradient',\n })\n }\n else {\n const props = { gradient: gradient.value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n addHistorySnapshot()\n }\n\n const updateGradient = (gradientProps: Partial) => {\n const props = { gradient: { ...gradient.value, ...gradientProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n fill,\n gradient,\n fillType,\n updateFillType,\n updateFill,\n updateGradient,\n }\n },\n})\n","import { render } from \"./ShapeStylePanel.vue?vue&type=template&id=d415c6bc&scoped=true\"\nimport script from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapeStylePanel.vue?vue&type=style&index=0&id=d415c6bc&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d415c6bc\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTLineElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementShadow from '../common/ElementShadow.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'line-style-panel',\n components: {\n ElementShadow,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLine = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n updateLine,\n }\n }\n})\n","import { render } from \"./LineStylePanel.vue?vue&type=template&id=65b24fb3&scoped=true\"\nimport script from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./LineStylePanel.vue?vue&type=style&index=0&id=65b24fb3&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-65b24fb3\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\nimport { ChartData } from '@/types/slides'\nimport { computed, defineComponent, onMounted, PropType, ref } from 'vue'\n\nconst CELL_WIDTH = 100\nconst CELL_HEIGHT = 32\n\nexport default defineComponent({\n name: 'chart-data-editor',\n props: {\n data: {\n type: Object as PropType,\n required: true,\n }\n },\n setup(props, { emit }) {\n const selectedRange = ref([0, 0])\n const tempRangeSize = ref({ width: 0, height: 0 })\n\n const rangeLines = computed(() => {\n const width = selectedRange.value[0] * CELL_WIDTH\n const height = selectedRange.value[1] * CELL_HEIGHT\n return [\n { type: 't', style: {width: width + 'px'} },\n { type: 'b', style: {top: height + 'px', width: width + 'px'} },\n { type: 'l', style: {height: height + 'px'} },\n { type: 'r', style: {left: width + 'px', height: height + 'px'} },\n ]\n })\n\n const resizablePointStyle = computed(() => {\n const width = selectedRange.value[0] * CELL_WIDTH\n const height = selectedRange.value[1] * CELL_HEIGHT\n return { left: width + 'px', top: height + 'px' }\n })\n\n const initData = () => {\n const _data: string[][] = []\n\n const { labels, series } = props.data\n const rowCount = labels.length\n const colCount = series.length\n\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row = [labels[rowIndex]]\n for(let colIndex = 0; colIndex < colCount; colIndex++) {\n row.push(series[colIndex][rowIndex] + '')\n }\n _data.push(row)\n }\n\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n for(let colIndex = 0; colIndex < colCount + 1; colIndex++) {\n const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\n if(!inputRef) continue\n inputRef.value = _data[rowIndex][colIndex] + ''\n }\n }\n\n selectedRange.value = [colCount + 1, rowCount]\n }\n\n onMounted(initData)\n\n const getTableData = () => {\n const [col, row] = selectedRange.value\n\n const labels: string[] = []\n const series: number[][] = []\n\n for(let rowIndex = 0; rowIndex < row; rowIndex++) {\n let labelsItem = `类别${rowIndex + 1}`\n const labelInputRef = document.querySelector(`#cell-${rowIndex}-0`) as HTMLInputElement\n if(labelInputRef && labelInputRef.value) labelsItem = labelInputRef.value\n labels.push(labelsItem)\n }\n\n for(let colIndex = 1; colIndex < col; colIndex++) {\n const seriesItem = []\n for(let rowIndex = 0; rowIndex < row; rowIndex++) {\n const valueInputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\n let value = 0\n if(valueInputRef && valueInputRef.value && !!(+valueInputRef.value)) {\n value = +valueInputRef.value\n }\n seriesItem.push(value)\n }\n series.push(seriesItem)\n }\n const data = { labels, series }\n emit('save', data)\n }\n\n const closeEditor = () => emit('close')\n\n const changeSelectRange = (e: MouseEvent) => {\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const originWidth = selectedRange.value[0] * CELL_WIDTH\n const originHeight = selectedRange.value[1] * CELL_HEIGHT\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const x = currentPageX - startPageX\n const y = currentPageY - startPageY\n\n const width = originWidth + x\n const height = originHeight + y\n\n tempRangeSize.value = { width, height }\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n const endPageX = e.pageX\n const endPageY = e.pageY\n\n if(startPageX === endPageX && startPageY === endPageY) return\n\n let width = tempRangeSize.value.width\n let height = tempRangeSize.value.height\n if(width % CELL_WIDTH > CELL_WIDTH * 0.5) width = width + (CELL_WIDTH - width % CELL_WIDTH)\n if(height % CELL_HEIGHT > CELL_HEIGHT * 0.5) height = height + (CELL_HEIGHT - height % CELL_HEIGHT)\n\n let row = Math.round(height / CELL_HEIGHT)\n let col = Math.round(width / CELL_WIDTH)\n\n if(row < 3) row = 3\n if(col < 2) col = 2\n\n selectedRange.value = [col, row]\n tempRangeSize.value = { width: 0, height: 0 }\n }\n }\n\n return {\n tempRangeSize,\n rangeLines,\n resizablePointStyle,\n changeSelectRange,\n selectedRange,\n getTableData,\n closeEditor,\n }\n },\n})\n","import { render } from \"./ChartDataEditor.vue?vue&type=template&id=73892bc6&scoped=true\"\nimport script from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartDataEditor.vue?vue&type=style&index=0&id=73892bc6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-73892bc6\"\n\nexport default script","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\nimport { MutationTypes, useStore } from '@/store'\nimport { ChartData, PPTChartElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '../../common/ElementOutline.vue'\nimport ColorButton from '../../common/ColorButton.vue'\nimport ChartDataEditor from './ChartDataEditor.vue'\n\nexport default defineComponent({\n name: 'chart-style-panel',\n components: {\n ElementOutline,\n ChartDataEditor,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const chartDataEditorVisible = ref(false)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const fill = ref()\n\n const themeColor = ref('')\n const gridColor = ref('')\n\n const lineSmooth = ref(true)\n const showLine = ref(true)\n const showArea = ref(false)\n const horizontalBars = ref(false)\n const donut = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'chart') return\n fill.value = handleElement.value.fill || '#000'\n\n if(handleElement.value.options) {\n const {\n lineSmooth: _lineSmooth,\n showLine: _showLine,\n showArea: _showArea,\n horizontalBars: _horizontalBars,\n donut: _donut,\n } = handleElement.value.options\n\n if(_lineSmooth !== undefined) lineSmooth.value = _lineSmooth\n if(_showLine !== undefined) showLine.value = _showLine\n if(_showArea !== undefined) showArea.value = _showArea\n if(_horizontalBars !== undefined) horizontalBars.value = _horizontalBars\n if(_donut !== undefined) donut.value = _donut\n }\n\n themeColor.value = handleElement.value.themeColor\n gridColor.value = handleElement.value.gridColor || 'rgba(0, 0, 0, 0.4)'\n }, { deep: true, immediate: true })\n\n const updateData = (data: ChartData) => {\n chartDataEditorVisible.value = false\n const props = { data }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => {\n const options = handleElement.value.options || {}\n const newOptions = { ...options, ...optionProps }\n const props = { options: newOptions }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateTheme = (themeColor: string) => {\n const props = { themeColor }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateGridColor = (gridColor: string) => {\n const props = { gridColor }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n chartDataEditorVisible,\n handleElement,\n updateData,\n fill,\n updateFill,\n lineSmooth,\n showLine,\n showArea,\n horizontalBars,\n donut,\n updateOptions,\n themeColor,\n gridColor,\n updateTheme,\n updateGridColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=0bd1ca02&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0bd1ca02&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0bd1ca02\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTableElement, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport { message } from 'ant-design-vue'\n\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'table-style-panel',\n components: {\n ElementOutline,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const textAttrs = ref({\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n })\n\n const theme = ref()\n const hasTheme = ref(false)\n const rowCount = ref(0)\n const colCount = ref(0)\n const minRowCount = ref(0)\n const minColCount = ref(0)\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'table') return\n \n theme.value = handleElement.value.theme\n hasTheme.value = !!theme.value\n\n rowCount.value = handleElement.value.data.length\n colCount.value = handleElement.value.data[0].length\n\n minRowCount.value = handleElement.value.data.length\n minColCount.value = handleElement.value.data[0].length\n }, { deep: true, immediate: true })\n\n const selectedCells = ref([])\n\n const updateTextAttrState = () => {\n if(!handleElement.value) return\n\n let rowIndex = 0\n let colIndex = 0\n if(selectedCells.value.length) {\n const selectedCell = selectedCells.value[0]\n rowIndex = +selectedCell.split('_')[0]\n colIndex = +selectedCell.split('_')[1]\n }\n const style = handleElement.value.data[rowIndex][colIndex].style\n\n if(!style) {\n textAttrs.value = {\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n }\n }\n else {\n textAttrs.value = {\n bold: !!style.bold,\n em: !!style.em,\n underline: !!style.underline,\n strikethrough: !!style.strikethrough,\n color: style.color || '#000',\n backcolor: style.backcolor || '#000',\n fontsize: style.fontsize || '12px',\n fontname: style.fontname || '微软雅黑',\n align: style.align || 'left',\n }\n }\n }\n\n const updateSelectedCells = (cells: string[]) => {\n selectedCells.value = cells\n updateTextAttrState()\n }\n\n emitter.on(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\n onUnmounted(() => {\n emitter.off(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\n })\n\n const availableFonts = computed(() => store.state.availableFonts)\n const fontSizeOptions = [\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\n ]\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateTextAttrs = (textAttrProp: Partial) => {\n const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\n\n for(let i = 0; i < data.length; i++) {\n for(let j = 0; j < data[i].length; j++) {\n if(!selectedCells.value.length || selectedCells.value.includes(`${i}_${j}`)) {\n const style = data[i][j].style || {}\n data[i][j].style = { ...style, ...textAttrProp }\n }\n }\n }\n const props = { data }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n\n addHistorySnapshot()\n updateTextAttrState()\n }\n\n const updateTheme = (themeProp: Partial) => {\n const currentTheme = theme.value || {}\n const props = { theme: { ...currentTheme, ...themeProp } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleTheme = (checked: boolean) => {\n if(checked) {\n const props = {\n theme: {\n color: '#d14424',\n rowHeader: true,\n rowFooter: false,\n colHeader: false,\n colFooter: false,\n }\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'theme' })\n }\n addHistorySnapshot()\n }\n\n const setTableRow = (e: KeyboardEvent) => {\n const value = +(e.target as HTMLInputElement).value\n const rowCount = handleElement.value.data.length\n\n if(value === rowCount) return\n if(value < rowCount) return message.warning('设置行数不能少于当前值')\n\n const rowCells: TableCell[] = new Array(colCount.value).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n const newTableCells: TableCell[][] = new Array(value - rowCount).fill(rowCells)\n\n const tableCells: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\n tableCells.push(...newTableCells)\n\n const props = { data: tableCells }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const setTableCol = (e: KeyboardEvent) => {\n const value = +(e.target as HTMLInputElement).value\n const colCount = handleElement.value.data[0].length\n\n if(value === colCount) return\n if(value < colCount) return message.warning('设置列数不能少于当前值')\n\n const tableCells = handleElement.value.data.map(item => {\n const cells: TableCell[] = new Array(value - colCount).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n item.push(...cells)\n return item\n })\n\n const colSizeList = handleElement.value.colWidths.map(item => item * handleElement.value.width)\n const newColSizeList = new Array(value - colCount).fill(100)\n colSizeList.push(...newColSizeList)\n\n const width = handleElement.value.width + 100 * (value - colCount)\n const colWidths = colSizeList.map(item => item / width)\n\n const props = {\n width,\n data: tableCells,\n colWidths,\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n availableFonts,\n fontSizeOptions,\n textAttrs,\n updateTextAttrs,\n theme,\n rowCount,\n colCount,\n minRowCount,\n minColCount,\n hasTheme,\n toggleTheme,\n updateTheme,\n setTableRow,\n setTableCol,\n }\n },\n})\n","import { render } from \"./TableStylePanel.vue?vue&type=template&id=63aedd01&scoped=true\"\nimport script from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TableStylePanel.vue?vue&type=style&index=0&id=63aedd01&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-63aedd01\"\n\nexport default script","\nimport { computed, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\n\nimport TextStylePanel from './TextStylePanel.vue'\nimport ImageStylePanel from './ImageStylePanel.vue'\nimport ShapeStylePanel from './ShapeStylePanel.vue'\nimport LineStylePanel from './LineStylePanel.vue'\nimport ChartStylePanel from './ChartStylePanel/index.vue'\nimport TableStylePanel from './TableStylePanel.vue'\n\nexport default defineComponent({\n name: 'element-style-panel',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const currentPanelComponent = computed(() => {\n if(!handleElement.value) return null\n \n const panelMap = {\n [ElementTypes.TEXT]: TextStylePanel,\n [ElementTypes.IMAGE]: ImageStylePanel,\n [ElementTypes.SHAPE]: ShapeStylePanel,\n [ElementTypes.LINE]: LineStylePanel,\n [ElementTypes.CHART]: ChartStylePanel,\n [ElementTypes.TABLE]: TableStylePanel,\n }\n return panelMap[handleElement.value.type] || null\n })\n\n return {\n handleElement,\n currentPanelComponent,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=459125fc\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport round from 'lodash/round'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { MIN_SIZE } from '@/configs/element'\nimport useOrderElement from '@/hooks/useOrderElement'\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'element-positopn-panel',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const left = ref(0)\n const top = ref(0)\n const width = ref(0)\n const height = ref(0)\n const rotate = ref(0)\n const fixedRatio = ref(false)\n\n const minSize = computed(() => {\n if(!handleElement.value) return 20\n return MIN_SIZE[handleElement.value.type] || 20\n })\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n\n left.value = round(handleElement.value.left, 1)\n top.value = round(handleElement.value.top, 1)\n\n fixedRatio.value = 'fixedRatio' in handleElement.value && !!handleElement.value.fixedRatio\n\n if(handleElement.value.type !== 'line') {\n width.value = round(handleElement.value.width, 1)\n height.value = round(handleElement.value.height, 1)\n rotate.value = 'rotate' in handleElement.value && handleElement.value.rotate !== undefined ? round(handleElement.value.rotate, 1) : 0\n }\n }, { deep: true, immediate: true })\n\n const { orderElement } = useOrderElement()\n const { alignElementToCanvas } = useAlignElementToCanvas()\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLeft = (value: number) => {\n const props = { left: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateTop = (value: number) => {\n const props = { top: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateWidth = (value: number) => {\n const props = { width: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateHeight = (value: number) => {\n const props = { height: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateRotate = (value: number) => {\n const props = { rotate: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateFixedRatio = (value: boolean) => {\n const props = { fixedRatio: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateRotate45 = (command: '+' | '-') => {\n let _rotate = Math.floor(rotate.value / 45) * 45\n if(command === '+') _rotate = _rotate + 45\n else if(command === '-') _rotate = _rotate - 45\n\n if(_rotate < -180) _rotate = -180\n if(_rotate > 180) _rotate = 180\n\n const props = { rotate: _rotate }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n orderElement,\n alignElementToCanvas,\n left,\n top,\n width,\n height,\n rotate,\n fixedRatio,\n minSize,\n updateLeft,\n updateTop,\n updateWidth,\n updateHeight,\n updateRotate,\n updateFixedRatio,\n updateRotate45,\n }\n },\n})\n","import { render } from \"./ElementPositionPanel.vue?vue&type=template&id=1a79147f&scoped=true\"\nimport script from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementPositionPanel.vue?vue&type=style&index=0&id=1a79147f&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1a79147f\"\n\nexport default script","\n\n\n\n","export const ANIMATIONS = [\r\n {\r\n type: 'bounce',\r\n name: '弹跳',\r\n children: [\r\n { name: '弹入', value: 'bounceIn' },\r\n { name: '向右弹入', value: 'bounceInLeft' },\r\n { name: '向左弹入', value: 'bounceInRight' },\r\n { name: '向上弹入', value: 'bounceInUp' },\r\n { name: '向下弹入', value: 'bounceInDown' },\r\n ],\r\n },\r\n {\r\n type: 'fade',\r\n name: '浮现',\r\n children: [\r\n { name: '浮入', value: 'fadeIn' },\r\n { name: '向下浮入', value: 'fadeInDown' },\r\n { name: '向下长距浮入', value: 'fadeInDownBig' },\r\n { name: '向右浮入', value: 'fadeInLeft' },\r\n { name: '向右长距浮入', value: 'fadeInLeftBig' },\r\n { name: '向左浮入', value: 'fadeInRight' },\r\n { name: '向左长距浮入', value: 'fadeInRightBig' },\r\n { name: '向上浮入', value: 'fadeInUp' },\r\n { name: '向上长距浮入', value: 'fadeInUpBig' },\r\n { name: '从左上浮入', value: 'fadeInTopLeft' },\r\n { name: '从右上浮入', value: 'fadeInTopRight' },\r\n { name: '从左下浮入', value: 'fadeInBottomLeft' },\r\n { name: '从右下浮入', value: 'fadeInBottomRight' },\r\n ],\r\n },\r\n {\r\n type: 'rotate',\r\n name: '旋转',\r\n children: [\r\n { name: '旋转进入', value: 'rotateIn' },\r\n { name: '绕左下旋转进入', value: 'rotateInDownLeft' },\r\n { name: '绕右下旋转进入', value: 'rotateInDownRight' },\r\n { name: '绕左上旋转进入', value: 'rotateInUpLeft' },\r\n { name: '绕右上旋转进入', value: 'rotateInUpRight' },\r\n ],\r\n },\r\n {\r\n type: 'zoom',\r\n name: '缩放',\r\n children: [\r\n { name: '放大进入', value: 'zoomIn' },\r\n { name: '向下放大进入', value: 'zoomInDown' },\r\n { name: '从左放大进入', value: 'zoomInLeft' },\r\n { name: '从右放大进入', value: 'zoomInRight' },\r\n { name: '向上放大进入', value: 'zoomInUp' },\r\n ],\r\n },\r\n {\r\n type: 'slide',\r\n name: '滑入',\r\n children: [\r\n { name: '向下滑入', value: 'slideInDown' },\r\n { name: '从右滑入', value: 'slideInLeft' },\r\n { name: '从左滑入', value: 'slideInRight' },\r\n { name: '向上滑入', value: 'slideInUp' },\r\n ],\r\n },\r\n {\r\n type: 'flip',\r\n name: '翻转',\r\n children: [\r\n { name: 'X轴翻转进入', value: 'flipInX' },\r\n { name: 'Y轴翻转进入', value: 'flipInY' },\r\n ],\r\n },\r\n {\r\n type: 'back',\r\n name: '放大滑入',\r\n children: [\r\n { name: '向下放大滑入', value: 'backInDown' },\r\n { name: '从左放大滑入', value: 'backInLeft' },\r\n { name: '从右放大滑入', value: 'backInRight' },\r\n { name: '向上放大滑入', value: 'backInUp' },\r\n ],\r\n },\r\n {\r\n type: 'lightSpeed',\r\n name: '飞入',\r\n children: [\r\n { name: '从右飞入', value: 'lightSpeedInRight' },\r\n { name: '从左飞入', value: 'lightSpeedInLeft' },\r\n ],\r\n },\r\n]","\nimport { computed, defineComponent, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTAnimation, PPTElement, Slide } from '@/types/slides'\nimport { ANIMATIONS } from '@/configs/animation'\nimport { ELEMENT_TYPE_ZH } from '@/configs/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport Draggable from 'vuedraggable'\n\nconst animationTypes: { [key: string]: string } = {}\nfor(const type of ANIMATIONS) {\n for(const animation of type.children) {\n animationTypes[animation.value] = animation.name\n }\n}\n\nexport default defineComponent({\n name: 'element-animation-panel',\n components: {\n Draggable,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n const currentSlideAnimations = computed(() => store.getters.currentSlideAnimations)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const hoverPreviewAnimation = ref('')\n const animationPoolVisible = ref(false)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const animations = ANIMATIONS\n\n const animationSequence = computed(() => {\n if(!currentSlideAnimations.value) return []\n const animationSequence = []\n for(const animation of currentSlideAnimations.value) {\n const el = currentSlide.value.elements.find(el => el.id === animation.elId)\n if(!el) continue\n const elType = ELEMENT_TYPE_ZH[el.type]\n const animationType = animationTypes[animation.type]\n\n animationSequence.push({\n ...animation,\n elType,\n animationType,\n })\n }\n return animationSequence\n })\n\n const handleElementAnimation = computed(() => {\n if(!handleElement.value) return null\n const animations = currentSlideAnimations.value || []\n const animation = animations.find(item => item.elId === handleElement.value.id)\n if(!animation) return null\n return animationTypes[animation.type]\n })\n\n const updateElementAnimation = (type: string) => {\n const animations = (currentSlideAnimations.value as PPTAnimation[]).map(item => {\n if(item.elId === handleElement.value.id) return { ...item, type }\n return item\n })\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n animationPoolVisible.value = false\n addHistorySnapshot()\n }\n\n const addAnimation = (type: string) => {\n if(handleElementAnimation.value) {\n updateElementAnimation(type)\n return\n }\n const animations: PPTAnimation[] = currentSlideAnimations.value ? JSON.parse(JSON.stringify(currentSlideAnimations.value)) : []\n animations.push({\n elId: handleElement.value.id,\n type,\n duration: 1000,\n })\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n animationPoolVisible.value = false\n addHistorySnapshot()\n }\n\n const deleteAnimation = (elId: string) => {\n const animations = (currentSlideAnimations.value as PPTAnimation[]).filter(item => item.elId !== elId)\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n addHistorySnapshot()\n }\n\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\n const { newIndex, oldIndex } = eventData\n if(oldIndex === newIndex) return\n\n const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value))\n const animation = animations[oldIndex]\n animations.splice(oldIndex, 1)\n animations.splice(newIndex, 0, animation)\n \n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n addHistorySnapshot()\n }\n\n const runAnimation = (elId: string, animationType: string) => {\n const prefix = 'animate__'\n const elRef = document.querySelector(`#editable-element-${elId} [class^=editable-element-]`)\n if(elRef) {\n const animationName = `${prefix}${animationType}`\n elRef.classList.add(`${prefix}animated`, animationName)\n\n const handleAnimationEnd = () => {\n elRef.classList.remove(`${prefix}animated`, animationName)\n }\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\n }\n }\n\n return {\n handleElement,\n animationPoolVisible,\n animations,\n animationSequence,\n hoverPreviewAnimation,\n handleElementAnimation,\n addAnimation,\n deleteAnimation,\n handleDragEnd,\n runAnimation,\n }\n },\n})\n","import { render } from \"./ElementAnimationPanel.vue?vue&type=template&id=3483fbf2&scoped=true\"\nimport script from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementAnimationPanel.vue?vue&type=style&index=0&id=3483fbf2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3483fbf2\"\n\nexport default script","\n\n\n\n","export const PRESET_THEMES = [\r\n { color: '#d14424', background: '#ffffff', text: '#333' },\r\n { color: '#42464b', background: '#ffffff', text: '#333' },\r\n { color: '#5d82ba', background: '#ffffff', text: '#333' },\r\n { color: '#005a6f', background: '#ffffff', text: '#333' },\r\n { color: '#d0614c', background: '#dfb044', text: '#333' },\r\n { color: '#86a1ad', background: '#dfdbd4', text: '#333' },\r\n { color: '#697586', background: '#d5c4a4', text: '#333' },\r\n { color: '#333333', background: '#7acfa6', text: '#333' },\r\n { color: '#42464b', background: '#415065', text: '#fff' },\r\n { color: '#0c5999', background: '#35a2cd', text: '#fff' },\r\n { color: '#c49a41', background: '#8c4357', text: '#fff' },\r\n { color: '#dfaa00', background: '#2e4e7d', text: '#fff' },\r\n { color: '#d1ad88', background: '#f99070', text: '#fff' },\r\n { color: '#464d52', background: '#657984', text: '#fff' },\r\n { color: '#ffcfb6', background: '#1e4c6f', text: '#fff' },\r\n { color: '#c3a043', background: '#43292a', text: '#fff' },\r\n { color: '#ffffff', background: '#171925', text: '#fff' },\r\n { color: '#df9636', background: '#5b89a0', text: '#fff' },\r\n { color: '#b898a4', background: '#93716b', text: '#fff' },\r\n { color: '#c47a11', background: '#187db1', text: '#fff' },\r\n { color: '#333333', background: '#759564', text: '#fff' },\r\n { color: '#355b5e', background: '#424b50', text: '#fff' },\r\n { color: '#d29090', background: '#942a32', text: '#fff' },\r\n { color: '#00cfdf', background: '#3b434d', text: '#fff' },\r\n { color: '#424246', background: '#c70042', text: '#fff' },\r\n { color: '#2e4155', background: '#b35d44', text: '#fff' },\r\n { color: '#11bfce', background: '#8f98aa', text: '#fff' },\r\n { color: '#333333', background: '#549688', text: '#fff' },\r\n]","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide, SlideBackground, SlideTheme } from '@/types/slides'\nimport { PRESET_THEMES } from '@/configs/theme'\nimport { WEB_FONTS } from '@/configs/font'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './common/ColorButton.vue'\nimport { getImageDataURL } from '@/utils/image'\n\nconst themes = PRESET_THEMES\nconst webFonts = WEB_FONTS\n\nexport default defineComponent({\n name: 'slide-style-panel',\n components: {\n ColorButton,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const theme = computed(() => store.state.theme)\n const currentSlide = computed(() => store.getters.currentSlide)\n const availableFonts = computed(() => store.state.availableFonts)\n\n const background = computed(() => {\n if(!currentSlide.value.background) {\n return {\n type: 'solid',\n value: '#fff',\n } as SlideBackground\n }\n return currentSlide.value.background\n })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateBackgroundType = (type: 'solid' | 'image' | 'gradient') => {\n if(type === 'solid') {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'solid',\n color: background.value.color || '#fff',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n else if(type === 'image') {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'image',\n image: background.value.image || '',\n imageSize: background.value.imageSize || 'cover',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n else {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'gradient',\n gradientType: background.value.gradientType || 'linear',\n gradientColor: background.value.gradientColor || ['#fff', '#fff'],\n gradientRotate: background.value.gradientRotate || 0,\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n addHistorySnapshot()\n }\n\n const updateBackground = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })\n addHistorySnapshot()\n }\n\n const uploadBackgroundImage = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => updateBackground({ image: dataURL }))\n }\n\n const applyBackgroundAllSlide = () => {\n const newSlides = slides.value.map(slide => {\n return {\n ...slide,\n background: currentSlide.value.background,\n }\n })\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n const updateTheme = (themeProps: Partial) => {\n store.commit(MutationTypes.SET_THEME, themeProps)\n }\n\n const applyThemeAllSlide = () => {\n const newSlides: Slide[] = JSON.parse(JSON.stringify(slides.value))\n const { themeColor, backgroundColor, fontColor } = theme.value\n\n for(const slide of newSlides) {\n if(!slide.background || slide.background.type !== 'image') {\n slide.background = {\n ...slide.background,\n type: 'solid',\n color: backgroundColor\n }\n }\n\n const elements = slide.elements\n for(const el of elements) {\n if(el.type === 'shape') el.fill = themeColor\n else if(el.type === 'line') el.color = themeColor\n else if(el.type === 'text') {\n if(el.fill) el.fill = themeColor\n }\n else if(el.type === 'table') {\n if(el.theme) el.theme.color = themeColor\n }\n else if(el.type === 'chart') {\n el.themeColor = themeColor\n el.gridColor = fontColor\n }\n }\n }\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n return {\n availableFonts,\n background,\n updateBackgroundType,\n updateBackground,\n uploadBackgroundImage,\n applyBackgroundAllSlide,\n themes,\n theme,\n webFonts,\n updateTheme,\n applyThemeAllSlide,\n }\n },\n})\n","import { render } from \"./SlideStylePanel.vue?vue&type=template&id=52253a56&scoped=true\"\nimport script from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideStylePanel.vue?vue&type=style&index=0&id=52253a56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-52253a56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'slide-animation-panel',\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')\n\n const animations = [\n { label: '无', value: 'no' },\n { label: '淡入淡出', value: 'fade' },\n { label: '左右推移', value: 'slideX' },\n { label: '上下推移', value: 'slideY' },\n ]\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateTurningMode = (mode: string) => {\n if(mode === currentTurningMode.value) return\n store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })\n addHistorySnapshot()\n }\n\n const applyAllSlide = () => {\n const newSlides = slides.value.map(slide => {\n return {\n ...slide,\n turningMode: currentSlide.value.turningMode,\n }\n })\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n return {\n currentTurningMode,\n animations,\n updateTurningMode,\n applyAllSlide,\n }\n },\n})\n","import { render } from \"./SlideAnimationPanel.vue?vue&type=template&id=a3bc22da&scoped=true\"\nimport script from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideAnimationPanel.vue?vue&type=style&index=0&id=a3bc22da&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a3bc22da\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\nimport { getElementListRange } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCombineElement from '@/hooks/useCombineElement'\n\nexport default defineComponent({\n name: 'multi-position-panel',\n setup() {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n const { combineElements, uncombineElements } = useCombineElement()\n\n const canCombine = computed(() => {\n const firstGroupId = activeElementList.value[0].groupId\n if(!firstGroupId) return true\n\n const inSameGroup = activeElementList.value.every(el => (el.groupId && el.groupId) === firstGroupId)\n return !inSameGroup\n })\n\n const alignActiveElement = (command: ElementAlignCommand) => {\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\n const elementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n\n // 获取每一个组合的宽高位置\n const groupElementRangeMap = {}\n for(const activeElement of activeElementList.value) {\n if(activeElement.groupId && !groupElementRangeMap[activeElement.groupId]) {\n const groupElements = activeElementList.value.filter(item => item.groupId === activeElement.groupId)\n groupElementRangeMap[activeElement.groupId] = getElementListRange(groupElements)\n }\n }\n\n if(command === ElementAlignCommands.LEFT) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) element.left = minX\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.minX - minX\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.RIGHT) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\n element.left = maxX - elWidth\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.maxX - maxX\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.TOP) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) element.top = minY\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.minY - minY\n element.top = element.top - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.BOTTOM) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\n element.top = maxY - elHeight\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.maxY - maxY\n element.top = element.top - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.HORIZONTAL) {\n const horizontalCenter = (minX + maxX) / 2\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\n element.left = horizontalCenter - elWidth / 2\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const center = (range.maxX + range.minX) / 2\n const offset = center - horizontalCenter\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.VERTICAL) {\n const verticalCenter = (minY + maxY) / 2\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\n element.top = verticalCenter - elHeight / 2\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const center = (range.maxY + range.minY) / 2\n const offset = center - verticalCenter\n element.top = element.top - offset\n }\n }\n })\n }\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })\n addHistorySnapshot()\n }\n\n return {\n canCombine,\n combineElements,\n uncombineElements,\n alignActiveElement,\n }\n },\n})\n","import { render } from \"./MultiPositionPanel.vue?vue&type=template&id=1040b5b1&scoped=true\"\nimport script from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiPositionPanel.vue?vue&type=style&index=0&id=1040b5b1&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1040b5b1\"\n\nexport default script","\nimport { computed, defineComponent, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { ToolbarState, ToolbarStates } from '@/types/toolbar'\n\nimport ElementStylePanel from './ElementStylePanel/index.vue'\nimport ElementPositionPanel from './ElementPositionPanel.vue'\nimport ElementAnimationPanel from './ElementAnimationPanel.vue'\nimport SlideStylePanel from './SlideStylePanel.vue'\nimport SlideAnimationPanel from './SlideAnimationPanel.vue'\nimport MultiPositionPanel from './MultiPositionPanel.vue'\n\nexport default defineComponent({\n name: 'toolbar',\n setup() {\n const store = useStore()\n const toolbarState = computed(() => store.state.toolbarState)\n\n const elementTabs = [\n { label: '样式', value: ToolbarStates.EL_STYLE },\n { label: '位置', value: ToolbarStates.EL_POSITION },\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\n ]\n const slideTabs = [\n { label: '页面样式', value: ToolbarStates.SLIDE_STYLE },\n { label: '切换', value: ToolbarStates.SLIDE_ANIMATION },\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\n ]\n const multiSelectTabs = [\n { label: '位置', value: ToolbarStates.MULTI_POSITION },\n { label: '样式', value: ToolbarStates.EL_STYLE },\n ]\n\n const setToolbarState = (value: ToolbarState) => {\n store.commit(MutationTypes.SET_TOOLBAR_STATE, value)\n }\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentTabs = computed(() => {\n if(!activeElementIdList.value.length) return slideTabs\n else if(activeElementIdList.value.length > 1) return multiSelectTabs\n return elementTabs\n })\n\n watch(currentTabs, () => {\n const currentTabsValue = currentTabs.value.map(tab => tab.value)\n if(!currentTabsValue.includes(toolbarState.value)) {\n store.commit(MutationTypes.SET_TOOLBAR_STATE, currentTabsValue[0])\n }\n })\n\n const currentPanelComponent = computed(() => {\n const panelMap = {\n [ToolbarStates.EL_STYLE]: ElementStylePanel,\n [ToolbarStates.EL_POSITION]: ElementPositionPanel,\n [ToolbarStates.EL_ANIMATION]: ElementAnimationPanel,\n [ToolbarStates.SLIDE_STYLE]: SlideStylePanel,\n [ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,\n [ToolbarStates.MULTI_POSITION]: MultiPositionPanel,\n }\n return panelMap[toolbarState.value] || null\n })\n\n return {\n toolbarState,\n currentTabs,\n setToolbarState,\n currentPanelComponent,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=8468ba32&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=8468ba32&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-8468ba32\"\n\nexport default script","\nimport { defineComponent } from 'vue'\n\nimport useHotkey from './useHotkey'\nimport usePasteEvent from './usePasteEvent'\n\nimport EditorHeader from './EditorHeader/index.vue'\nimport Canvas from './Canvas/index.vue'\nimport CanvasTool from './CanvasTool/index.vue'\nimport Thumbnails from './Thumbnails/index.vue'\nimport Toolbar from './Toolbar/index.vue'\n\nexport default defineComponent({\n name: 'editor',\n components: {\n EditorHeader,\n Canvas,\n CanvasTool,\n Thumbnails,\n Toolbar,\n },\n setup() {\n useHotkey()\n usePasteEvent()\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=d5c6b448&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=d5c6b448&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d5c6b448\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue'\nimport { PPTChartElement } from '@/types/slides'\n\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\nimport Chart from './Chart.vue'\n\nexport default defineComponent({\n name: 'screen-element-chart',\n components: {\n ElementOutline,\n Chart,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n})\n","import { render } from \"./ScreenChartElement.vue?vue&type=template&id=1423f8c2&scoped=true\"\nimport script from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenChartElement.vue?vue&type=style&index=0&id=1423f8c2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1423f8c2\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\n\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\nimport ScreenChartElement from '@/views/components/element/ChartElement/ScreenChartElement.vue'\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\n\nexport default defineComponent({\n name: 'screen-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n animationIndex: {\n type: Number,\n default: -1,\n },\n },\n setup(props) {\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: BaseImageElement,\n [ElementTypes.TEXT]: BaseTextElement,\n [ElementTypes.SHAPE]: BaseShapeElement,\n [ElementTypes.LINE]: BaseLineElement,\n [ElementTypes.CHART]: ScreenChartElement,\n [ElementTypes.TABLE]: BaseTableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n const store = useStore()\n const theme = computed(() => store.state.theme)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const needWaitAnimation = computed(() => {\n const animations = currentSlide.value.animations || []\n const elementIndexInAnimation = animations.findIndex(animation => animation.elId === props.elementInfo.id)\n if(elementIndexInAnimation !== -1 && elementIndexInAnimation >= props.animationIndex) return true\n return false \n })\n\n return {\n currentElementComponent,\n needWaitAnimation,\n theme,\n }\n },\n})\n","import { render } from \"./ScreenElement.vue?vue&type=template&id=68c19726\"\nimport script from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nimport ScreenElement from './ScreenElement.vue'\n\nexport default defineComponent({\n name: 'screen-slide',\n components: {\n ScreenElement,\n },\n props: {\n slide: {\n type: Object as PropType,\n required: true,\n },\n scale: {\n type: Number,\n required: true,\n },\n animationIndex: {\n type: Number,\n default: -1,\n },\n },\n setup(props) {\n const background = computed(() => props.slide.background)\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n return {\n backgroundStyle,\n VIEWPORT_SIZE,\n VIEWPORT_ASPECT_RATIO,\n }\n },\n})\n","import { render } from \"./ScreenSlide.vue?vue&type=template&id=5e193d56&scoped=true\"\nimport script from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenSlide.vue?vue&type=style&index=0&id=5e193d56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5e193d56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\n\nexport default defineComponent({\n name: 'slide-thumbnails',\n components: {\n ThumbnailSlide,\n },\n props: {\n turnSlideToIndex: {\n type: Function as PropType<(index: number) => void>,\n },\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n\n return {\n slides,\n slideIndex,\n }\n },\n})\n","import { render } from \"./SlideThumbnails.vue?vue&type=template&id=5b8ebe1d&scoped=true\"\nimport script from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideThumbnails.vue?vue&type=style&index=0&id=5b8ebe1d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b8ebe1d\"\n\nexport default script","\n\n\n\n","\r\n\r\n\r\n\r\n","\r\nimport { defineComponent, onMounted, PropType, reactive, ref } from 'vue'\r\n\r\nconst penSize = 6\r\nconst rubberSize = 80\r\n\r\nexport default defineComponent({\r\n name: 'writing-board',\r\n props: {\r\n color: {\r\n type: String,\r\n default: '#ffcc00',\r\n },\r\n model: {\r\n type: String as PropType<'pen' | 'eraser'>,\r\n default: 'pen',\r\n },\r\n },\r\n setup(props) {\r\n let ctx: CanvasRenderingContext2D | null = null\r\n const writingBoardRef = ref()\r\n const canvasRef = ref()\r\n let lastPos = {\r\n x: 0,\r\n y: 0,\r\n }\r\n let isMouseDown = false\r\n let lastTime = 0\r\n let lastLineWidth = -1\r\n\r\n const mouse = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n const mouseInCanvas = ref(false)\r\n\r\n const initCanvas = () => {\r\n if(!canvasRef.value || !writingBoardRef.value) return\r\n\r\n ctx = canvasRef.value.getContext('2d')\r\n if(!ctx) return\r\n\r\n canvasRef.value.width = writingBoardRef.value.clientWidth\r\n canvasRef.value.height = writingBoardRef.value.clientHeight\r\n\r\n canvasRef.value.style.width = writingBoardRef.value.clientWidth + 'px'\r\n canvasRef.value.style.height = writingBoardRef.value.clientHeight + 'px'\r\n\r\n ctx.lineCap = 'round'\r\n ctx.lineJoin = 'round'\r\n }\r\n\r\n const getDistance = (posX: number, posY: number) => {\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n return Math.sqrt((posX - lastPosX) * (posX - lastPosX) + (posY - lastPosY) * (posY - lastPosY))\r\n }\r\n\r\n const getLineWidth = (s: number, t: number) => {\r\n const maxV = 10\r\n const minV = 0.1\r\n const maxWidth = penSize\r\n const minWidth = 3\r\n const v = s / t\r\n let lineWidth\r\n\r\n if(v <= minV) lineWidth = maxWidth\r\n else if(v >= maxV) lineWidth = minWidth\r\n else lineWidth = maxWidth - v / maxV * maxWidth\r\n\r\n if(lastLineWidth === -1) return lineWidth\r\n return lineWidth * 1 / 3 + lastLineWidth * 2 / 3\r\n }\r\n\r\n // 画笔绘制方法\r\n const draw = (posX: number, posY: number, lineWidth: number) => {\r\n if(!ctx) return\r\n\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n ctx.lineWidth = lineWidth\r\n ctx.strokeStyle = props.color\r\n ctx.beginPath()\r\n ctx.moveTo(lastPosX, lastPosY)\r\n ctx.lineTo(posX, posY)\r\n ctx.stroke()\r\n ctx.closePath()\r\n }\r\n\r\n // 橡皮擦除方法\r\n const erase = (posX: number, posY: number) => {\r\n if(!ctx || !canvasRef.value) return\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n const radius = rubberSize / 2\r\n\r\n const sinRadius = radius * Math.sin(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const cosRadius = radius * Math.cos(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const rectPoint1: [number, number] = [lastPosX + sinRadius, lastPosY - cosRadius]\r\n const rectPoint2: [number, number] = [lastPosX - sinRadius, lastPosY + cosRadius]\r\n const rectPoint3: [number, number] = [posX + sinRadius, posY - cosRadius]\r\n const rectPoint4: [number, number] = [posX - sinRadius, posY + cosRadius]\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.arc(posX, posY, radius, 0, Math.PI * 2)\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.moveTo(...rectPoint1)\r\n ctx.lineTo(...rectPoint3)\r\n ctx.lineTo(...rectPoint4)\r\n ctx.lineTo(...rectPoint2)\r\n ctx.closePath()\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n }\r\n\r\n const startDraw = (posX: number, posY: number) => {\r\n lastPos = { x: posX, y: posY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n const startMove = (posX: number, posY: number) => {\r\n const time = new Date().getTime()\r\n\r\n // 画笔模式(这里通过绘制速度调节画笔的粗细)\r\n if(props.model === 'pen') {\r\n const s = getDistance(posX, posY)\r\n const t = time - lastTime\r\n const lineWidth = getLineWidth(s, t)\r\n \r\n draw(posX, posY, lineWidth)\r\n lastLineWidth = lineWidth\r\n }\r\n // 橡皮模式\r\n else erase(posX, posY)\r\n\r\n lastPos = { x: posX, y: posY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n const handleMousedown = (e: MouseEvent) => {\r\n isMouseDown = true\r\n startDraw(e.offsetX, e.offsetY)\r\n }\r\n\r\n const updateMousePosition = (e: MouseEvent) => {\r\n mouse.x = e.pageX\r\n mouse.y = e.pageY\r\n }\r\n\r\n const handleMousemove = (e: MouseEvent) => {\r\n updateMousePosition(e)\r\n\r\n if(!isMouseDown) return\r\n startMove(e.offsetX, e.offsetY)\r\n }\r\n\r\n const handleMouseup = () => {\r\n if(!isMouseDown) return\r\n isMouseDown = false\r\n }\r\n\r\n // 清空画布\r\n const clearCanvas = () => {\r\n if(!ctx || !canvasRef.value) return\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n }\r\n\r\n onMounted(initCanvas)\r\n\r\n return {\r\n mouse,\r\n mouseInCanvas,\r\n penSize,\r\n rubberSize,\r\n writingBoardRef,\r\n canvasRef,\r\n handleMousedown,\r\n handleMousemove,\r\n handleMouseup,\r\n clearCanvas,\r\n }\r\n },\r\n})\r\n","import { render } from \"./WritingBoard.vue?vue&type=template&id=5b8a1ac6&scoped=true\"\nimport script from \"./WritingBoard.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoard.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoard.vue?vue&type=style&index=0&id=5b8a1ac6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b8a1ac6\"\n\nexport default script","\nimport { defineComponent, ref } from 'vue'\nimport WritingBoard from '@/components/WritingBoard.vue'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\n\nconst writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\n\nexport default defineComponent({\n name: 'writing-board-tool',\n components: {\n WritingBoard,\n },\n setup(props, { emit }) {\n const writingBoardRef = ref()\n const writingBoardVisible = ref(false)\n const writingBoardColor = ref('#e2534d')\n const writingBoardModel = ref('pen')\n\n const changePen = () => {\n if(!writingBoardVisible.value) writingBoardVisible.value = true\n writingBoardModel.value = 'pen'\n emit('close')\n }\n\n const changeEraser = () => {\n writingBoardModel.value = 'eraser'\n emit('close')\n }\n\n const clearCanvas = () => {\n writingBoardRef.value.clearCanvas()\n emit('close')\n }\n\n const changeColor = (color: string) => {\n if(writingBoardModel.value !== 'pen') writingBoardModel.value = 'pen'\n writingBoardColor.value = color\n emit('close')\n }\n\n const closeWritingBoard = () => {\n writingBoardVisible.value = false\n emit('close')\n }\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '画笔',\n handler: changePen,\n disable: writingBoardModel.value === 'pen',\n },\n {\n text: '橡皮擦',\n handler: changeEraser,\n disable: writingBoardModel.value === 'eraser',\n },\n {\n text: '擦除所有墨迹',\n handler: clearCanvas,\n },\n {\n text: '退出画笔',\n handler: closeWritingBoard,\n },\n ]\n }\n\n return {\n writingBoardRef,\n writingBoardVisible,\n writingBoardColors,\n writingBoardColor,\n writingBoardModel,\n changePen,\n changeEraser,\n clearCanvas,\n changeColor,\n closeWritingBoard,\n contextmenus,\n }\n },\n})\n","import { render } from \"./WritingBoardTool.vue?vue&type=template&id=0ecab351&scoped=true\"\nimport script from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoardTool.vue?vue&type=style&index=0&id=0ecab351&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0ecab351\"\n\nexport default script","\nimport { computed, defineComponent, onMounted, onUnmounted, provide, ref } from 'vue'\nimport throttle from 'lodash/throttle'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas'\nimport { KEYS } from '@/configs/hotkey'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { isFullscreen } from '@/utils/fullscreen'\nimport useScreening from '@/hooks/useScreening'\n\nimport ScreenSlide from './ScreenSlide.vue'\nimport SlideThumbnails from './SlideThumbnails.vue'\nimport WritingBoardTool from './WritingBoardTool.vue'\n\nexport default defineComponent({\n name: 'screen',\n components: {\n ScreenSlide,\n SlideThumbnails,\n WritingBoardTool,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const slideWidth = ref(0)\n const slideHeight = ref(0)\n\n const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)\n\n const slideThumbnailModelVisible = ref(false)\n\n const writingBoardToolVisible = ref(false)\n\n const setSlideContentSize = () => {\n const winWidth = document.body.clientWidth\n const winHeight = document.body.clientHeight\n let width, height\n\n if(winHeight / winWidth === VIEWPORT_ASPECT_RATIO) {\n width = winWidth\n height = winHeight\n }\n else if(winHeight / winWidth > VIEWPORT_ASPECT_RATIO) {\n width = winWidth\n height = winWidth * VIEWPORT_ASPECT_RATIO\n }\n else {\n width = winHeight / VIEWPORT_ASPECT_RATIO\n height = winHeight\n }\n slideWidth.value = width\n slideHeight.value = height\n }\n\n const { exitScreening } = useScreening()\n\n const windowResizeListener = () => {\n setSlideContentSize()\n if(!isFullscreen()) exitScreening()\n }\n\n const animationIndex = ref(0)\n const animations = computed(() => currentSlide.value.animations || [])\n\n const runAnimation = () => {\n const prefix = 'animate__'\n const animation = animations.value[animationIndex.value]\n animationIndex.value += 1\n\n const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`)\n if(elRef) {\n const animationName = `${prefix}${animation.type}`\n elRef.classList.add(`${prefix}animated`, animationName)\n\n const handleAnimationEnd = () => {\n elRef.classList.remove(`${prefix}animated`, animationName)\n }\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\n }\n }\n\n const execPrev = () => {\n if(animations.value.length && animationIndex.value > 0) {\n animationIndex.value -= 1\n }\n else if(slideIndex.value > 0) {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\n const lastIndex = animations.value ? animations.value.length : 0\n animationIndex.value = lastIndex\n }\n }\n const execNext = () => {\n if(animations.value.length && animationIndex.value < animations.value.length) {\n runAnimation()\n }\n else if(slideIndex.value < slides.value.length - 1) {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\n animationIndex.value = 0\n }\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(key === KEYS.UP || key === KEYS.LEFT) execPrev()\n else if(\n key === KEYS.DOWN || \n key === KEYS.RIGHT ||\n key === KEYS.SPACE || \n key === KEYS.ENTER\n ) execNext()\n }\n\n const mousewheelListener = throttle(function(e: WheelEvent) {\n if(e.deltaY < 0) execPrev()\n else if(e.deltaY > 0) execNext()\n }, 500, { leading: true, trailing: false })\n\n onMounted(() => {\n window.addEventListener('resize', windowResizeListener)\n document.addEventListener('keydown', keydownListener)\n })\n onUnmounted(() => {\n window.removeEventListener('resize', windowResizeListener)\n document.removeEventListener('keydown', keydownListener)\n })\n\n const turnPrevSlide = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\n animationIndex.value = 0\n }\n const turnNextSlide = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\n animationIndex.value = 0\n }\n\n const turnSlideToIndex = (index: number) => {\n slideThumbnailModelVisible.value = false\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n animationIndex.value = 0\n }\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '上一页',\n disable: slideIndex.value <= 0,\n handler: () => turnPrevSlide(),\n },\n {\n text: '下一页',\n disable: slideIndex.value >= slides.value.length - 1,\n handler: () => turnNextSlide(),\n },\n {\n text: '结束放映',\n subText: 'ESC',\n handler: exitScreening,\n },\n ]\n }\n \n provide('slideScale', scale)\n\n return {\n slides,\n slideIndex,\n currentSlide,\n slideWidth,\n slideHeight,\n scale,\n mousewheelListener,\n animationIndex,\n contextmenus,\n execPrev,\n execNext,\n slideThumbnailModelVisible,\n turnSlideToIndex,\n writingBoardToolVisible,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=048f6280&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=048f6280&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-048f6280\"\n\nexport default script","\nimport { computed, defineComponent, onMounted } from 'vue'\nimport { MutationTypes, ActionTypes, useStore } from '@/store'\n\nimport Editor from './views/Editor/index.vue'\nimport Screen from './views/Screen/index.vue'\n\nexport default defineComponent({\n name: 'app',\n components: {\n Editor,\n Screen,\n },\n setup() {\n const store = useStore()\n const screening = computed(() => store.state.screening)\n\n onMounted(() => {\n store.commit(MutationTypes.SET_AVAILABLE_FONTS)\n store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)\n })\n\n return {\n screening,\n }\n },\n})\n","import { render } from \"./App.vue?vue&type=template&id=7fa1c35b\"\nimport script from \"./App.vue?vue&type=script&lang=ts\"\nexport * from \"./App.vue?vue&type=script&lang=ts\"\n\nimport \"./App.vue?vue&type=style&index=0&id=7fa1c35b&lang=scss\"\nscript.render = render\n\nexport default script","\n\n\n\n","\n\n\n\n","\nimport { PropType, defineComponent } from 'vue'\nimport { ContextmenuItem } from './types'\n\nexport default defineComponent({\n name: 'menu-content',\n props: {\n menus: {\n type: Array as PropType,\n required: true,\n },\n subMenuPosition: {\n type: String,\n default: 'left',\n },\n handleClickMenuItem: {\n type: Function,\n required: true,\n },\n },\n})\n","import { render } from \"./MenuContent.vue?vue&type=template&id=3cad6828&scoped=true\"\nimport script from \"./MenuContent.vue?vue&type=script&lang=ts\"\nexport * from \"./MenuContent.vue?vue&type=script&lang=ts\"\n\nimport \"./MenuContent.vue?vue&type=style&index=0&id=3cad6828&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3cad6828\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { ContextmenuItem, Axis } from './types'\n\nimport MenuContent from './MenuContent.vue'\n\nconst MENU_WIDTH = 160\nconst MENU_HEIGHT = 30\nconst DIVIDER_HEIGHT = 11\nconst SUB_MENU_WIDTH = 120\n\nexport default defineComponent({\n name: 'contextmenu',\n components: {\n MenuContent,\n },\n props: {\n axis: {\n type: Object as PropType,\n required: true,\n },\n el: {\n type: Object as PropType,\n required: true,\n },\n menus: {\n type: Array as PropType,\n required: true,\n },\n removeContextMenu: {\n type: Function,\n required: true,\n },\n },\n setup(props) {\n const style = computed(() => {\n const { x, y } = props.axis\n const normalMenuCount = props.menus.filter(menu => !menu.divider && !menu.hide).length\n const dividerMenuCount = props.menus.filter(menu => menu.divider).length\n const padding = 10\n\n const menuWidth = MENU_WIDTH\n const menuHeight = normalMenuCount * MENU_HEIGHT + dividerMenuCount * DIVIDER_HEIGHT + padding\n\n const maxMenuWidth = MENU_WIDTH + SUB_MENU_WIDTH - 10\n\n const screenWidth = document.body.clientWidth\n const screenHeight = document.body.clientHeight\n\n const left = (screenWidth <= x + menuWidth ? x - menuWidth : x)\n const top = (screenHeight <= y + menuHeight ? y - menuHeight : y)\n\n const subMenuPosition = screenWidth <= left + maxMenuWidth ? 'right' : 'left'\n\n return {\n left: left + 'px',\n top: top + 'px',\n subMenuPosition,\n }\n })\n\n const handleClickMenuItem = (item: ContextmenuItem) => {\n if(item.disable || item.children) return\n if(item.handler) item.handler(props.el)\n props.removeContextMenu()\n }\n\n return {\n style,\n handleClickMenuItem,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=0fa561b9\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0fa561b9&lang=scss\"\nscript.render = render\n\nexport default script","import { Directive, createVNode, render, DirectiveBinding } from 'vue'\nimport ContextmenuComponent from '@/components/Contextmenu/index.vue'\n\nconst CTX_CONTEXTMENU_HANDLER = 'CTX_CONTEXTMENU_HANDLER'\n\nconst contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\n event.stopPropagation()\n event.preventDefault()\n\n const menus = binding.value(el)\n if(!menus) return\n\n let container: HTMLDivElement | null = null\n\n const removeContextMenu = () => {\n if(container) {\n document.body.removeChild(container)\n container = null\n }\n el.classList.remove('contextmenu-active')\n document.body.removeEventListener('scroll', removeContextMenu) \n window.removeEventListener('resize', removeContextMenu)\n }\n\n const options = {\n axis: { x: event.x, y: event.y },\n el,\n menus,\n removeContextMenu,\n }\n container = document.createElement('div')\n const vm = createVNode(ContextmenuComponent, options, null)\n render(vm, container)\n document.body.appendChild(container)\n\n el.classList.add('contextmenu-active')\n\n document.body.addEventListener('scroll', removeContextMenu)\n window.addEventListener('resize', removeContextMenu)\n}\n\nconst ContextmenuDirective: Directive = {\n mounted(el: HTMLElement, binding) {\n el[CTX_CONTEXTMENU_HANDLER] = (event: MouseEvent) => contextmenuListener(el, event, binding)\n el.addEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\n },\n\n unmounted(el: HTMLElement) {\n if(el && el[CTX_CONTEXTMENU_HANDLER]) {\n el.removeEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\n delete el[CTX_CONTEXTMENU_HANDLER]\n }\n },\n}\n\nexport default ContextmenuDirective","import { Directive, DirectiveBinding } from 'vue'\n\nconst CTX_CLICK_OUTSIDE_HANDLER = 'CTX_CLICK_OUTSIDE_HANDLER'\n\nconst clickListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\n const handler = binding.value\n\n const path = event.composedPath()\n const isClickOutside = path ? path.indexOf(el) < 0 : !el.contains(event.target as HTMLElement)\n\n if(!isClickOutside) return\n handler(event)\n}\n\nconst ClickOutsideDirective: Directive = {\n mounted(el: HTMLElement, binding) {\n el[CTX_CLICK_OUTSIDE_HANDLER] = (event: MouseEvent) => clickListener(el, event, binding)\n setTimeout(() => {\n document.addEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\n }, 0)\n },\n \n unmounted(el: HTMLElement) {\n if(el[CTX_CLICK_OUTSIDE_HANDLER]) {\n document.removeEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\n delete el[CTX_CLICK_OUTSIDE_HANDLER]\n }\n },\n}\n\nexport default ClickOutsideDirective","import { App } from 'vue'\nimport {\n Home,\n PlayOne,\n Lock,\n Unlock,\n Search,\n Delete,\n Ppt,\n SettingOne,\n Clear,\n Format,\n Picture,\n FullScreen,\n OffScreen,\n LinkOne,\n List,\n OrderedList,\n Drag,\n Helpcenter,\n SplitCells,\n MergeCells,\n FlipVertically,\n FlipHorizontally,\n FontSize,\n Code,\n TextBold,\n TextItalic,\n TextUnderline,\n Strikethrough,\n Edit,\n Quote,\n EnterTheKeyboard,\n Copy,\n Clipboard,\n Find,\n BackgroundColor,\n Group,\n Ungroup,\n FullSelection,\n ClearFormat,\n Back,\n Next,\n Fullwidth,\n GridFour,\n AlignTop,\n AlignLeft,\n AlignRight,\n AlignBottom,\n AlignVertically,\n AlignHorizontally,\n BringToFront,\n SendToBack,\n AlignTextLeft,\n AlignTextRight,\n AlignTextCenter,\n RowHeight,\n More,\n Write,\n InsertTable,\n CuttingOne,\n AddThree,\n AddText,\n Fill,\n Tailoring,\n Newlybuild,\n Effects,\n ColorFilter,\n Up,\n Down,\n Left,\n Right,\n Plus,\n Minus,\n Check,\n Close,\n Connection,\n BringToFrontOne,\n SentToBack,\n Github,\n ChartRing,\n ChartLine,\n ChartHistogramOne,\n ChartHistogram,\n ChartProportion,\n ChartScatter,\n PentagonOne,\n PageTemplate,\n Text,\n Rotate,\n LeftC,\n RightC,\n Platte,\n UpOne,\n DownOne,\n SeoFolder,\n CloseSmall,\n Undo,\n Transform,\n Click,\n Theme,\n Symbol,\n} from '@icon-park/vue-next'\n\nexport default {\n install(app: App) {\n // 插入元素\n app.component('IconFontSize', FontSize)\n app.component('IconPicture', Picture)\n app.component('IconPentagonOne', PentagonOne)\n app.component('IconConnection', Connection)\n app.component('IconInsertTable', InsertTable)\n app.component('IconSymbol', Symbol)\n\n // 剪贴板\n app.component('IconCopy', Copy)\n app.component('IconClipboard', Clipboard)\n app.component('IconCuttingOne', CuttingOne)\n\n // 锁定与解锁\n app.component('IconLock', Lock)\n app.component('IconUnlock', Unlock)\n\n // 全屏\n app.component('IconFullScreen', FullScreen)\n app.component('IconOffScreen', OffScreen)\n\n // 撤销重做\n app.component('IconBack', Back)\n app.component('IconNext', Next) \n \n // 对齐\n app.component('IconAlignTop', AlignTop)\n app.component('IconAlignLeft', AlignLeft)\n app.component('IconAlignRight', AlignRight)\n app.component('IconAlignBottom', AlignBottom)\n app.component('IconAlignVertically', AlignVertically)\n app.component('IconAlignHorizontally', AlignHorizontally)\n\n // 层级\n app.component('IconBringToFront', BringToFront)\n app.component('IconSentToBack', SentToBack)\n app.component('IconBringToFrontOne', BringToFrontOne)\n app.component('IconSendToBack', SendToBack)\n\n // 组合\n app.component('IconGroup', Group)\n app.component('IconUngroup', Ungroup)\n\n // 通用元素编辑\n app.component('IconFill', Fill)\n app.component('IconBackgroundColor', BackgroundColor)\n app.component('IconPlatte', Platte)\n\n // 表格编辑\n app.component('IconSplitCells', SplitCells)\n app.component('IconMergeCells', MergeCells)\n \n // 图片编辑\n app.component('IconTailoring', Tailoring)\n app.component('IconColorFilter', ColorFilter)\n app.component('IconFlipVertically', FlipVertically)\n app.component('IconFlipHorizontally', FlipHorizontally)\n\n // 文字编辑\n app.component('IconText', Text)\n app.component('IconAddText', AddText)\n app.component('IconAlignTextLeft', AlignTextLeft)\n app.component('IconAlignTextRight', AlignTextRight)\n app.component('IconAlignTextCenter', AlignTextCenter)\n app.component('IconRowHeight', RowHeight)\n app.component('IconFullwidth', Fullwidth)\n app.component('IconCode', Code)\n app.component('IconTextBold', TextBold)\n app.component('IconTextItalic', TextItalic)\n app.component('IconTextUnderline', TextUnderline)\n app.component('IconStrikethrough', Strikethrough)\n app.component('IconQuote', Quote)\n app.component('IconList', List)\n app.component('IconOrderedList', OrderedList)\n app.component('IconUpOne', UpOne)\n app.component('IconDownOne', DownOne)\n app.component('IconFormat', Format)\n\n // 箭头与符号\n app.component('IconUp', Up)\n app.component('IconDown', Down)\n app.component('IconLeft', Left)\n app.component('IconRight', Right)\n app.component('IconLeftC', LeftC)\n app.component('IconRightC', RightC)\n app.component('IconPlus', Plus)\n app.component('IconMinus', Minus)\n app.component('IconCheck', Check)\n app.component('IconClose', Close)\n app.component('IconCloseSmall', CloseSmall)\n \n // 图表\n app.component('IconChartRing', ChartRing)\n app.component('IconChartLine', ChartLine)\n app.component('IconChartHistogramOne', ChartHistogramOne)\n app.component('IconChartHistogram', ChartHistogram)\n app.component('IconChartProportion', ChartProportion)\n app.component('IconChartScatter', ChartScatter)\n\n // 其他\n app.component('IconHome', Home)\n app.component('IconPlayOne', PlayOne)\n app.component('IconSearch', Search)\n app.component('IconDelete', Delete)\n app.component('IconPpt', Ppt)\n app.component('IconSettingOne', SettingOne)\n app.component('IconClear', Clear)\n app.component('IconLinkOne', LinkOne)\n app.component('IconDrag', Drag)\n app.component('IconHelpcenter', Helpcenter)\n app.component('IconEnterTheKeyboard', EnterTheKeyboard)\n app.component('IconFind', Find)\n app.component('IconFullSelection', FullSelection)\n app.component('IconClearFormat', ClearFormat)\n app.component('IconGridFour', GridFour)\n app.component('IconPageTemplate', PageTemplate)\n app.component('IconGithub', Github)\n app.component('IconMore', More)\n app.component('IconWrite', Write)\n app.component('IconAddThree', AddThree)\n app.component('IconNewlybuild', Newlybuild)\n app.component('IconEffects', Effects)\n app.component('IconRotate', Rotate)\n app.component('IconEdit', Edit)\n app.component('IconSeoFolder', SeoFolder)\n app.component('IconUndo', Undo)\n app.component('IconTransform', Transform)\n app.component('IconClick', Click)\n app.component('IconTheme', Theme)\n }\n}","\n\n\n\n","\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n name: 'file-input',\n props: {\n accept: {\n type: String,\n default: 'image/*',\n },\n },\n setup(props, { emit }) {\n const inputRef = ref()\n\n const handleClick = () => {\n if(!inputRef.value) return\n inputRef.value.value = ''\n inputRef.value.click()\n }\n const handleChange = (e: InputEvent) => {\n const files = (e.target as HTMLInputElement).files\n if(files) emit('change', files)\n }\n\n return {\n handleClick,\n handleChange,\n inputRef,\n }\n },\n})\n","import { render } from \"./FileInput.vue?vue&type=template&id=59732924&scoped=true\"\nimport script from \"./FileInput.vue?vue&type=script&lang=ts\"\nexport * from \"./FileInput.vue?vue&type=script&lang=ts\"\n\nimport \"./FileInput.vue?vue&type=style&index=0&id=59732924&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-59732924\"\n\nexport default script","\n\n","\nexport default {\n name: 'svg-wrapper',\n}\n","import { render } from \"./SvgWrapper.vue?vue&type=template&id=07215504\"\nimport script from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nexport * from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\n\r\n\r\n\r\n","\r\nexport default {\r\n name: 'checkbox-button',\r\n props: {\r\n checked: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n","import { render } from \"./CheckboxButton.vue?vue&type=template&id=7cae2b90&scoped=true\"\nimport script from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButton.vue?vue&type=style&index=0&id=7cae2b90&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7cae2b90\"\n\nexport default script","\r\n\r\n\r\n\r\n","\r\nexport default {\r\n name: 'checkbox-button-group',\r\n}\r\n","import { render } from \"./CheckboxButtonGroup.vue?vue&type=template&id=7dafd0a9&scoped=true\"\nimport script from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButtonGroup.vue?vue&type=style&index=0&id=7dafd0a9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7dafd0a9\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\n\nconst checkboardCache = {}\nconst renderCheckboard = (white: string, grey: string, size: number) => {\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = size * 2\n const ctx = canvas.getContext('2d')\n \n if(!ctx) return null\n\n ctx.fillStyle = white\n ctx.fillRect(0, 0, canvas.width, canvas.height)\n ctx.fillStyle = grey\n ctx.fillRect(0, 0, size, size)\n ctx.translate(size, size)\n ctx.fillRect(0, 0, size, size)\n return canvas.toDataURL()\n}\n\nconst getCheckboard = (white: string, grey: string, size: number) => {\n const key = white + ',' + grey + ',' + size\n if(checkboardCache[key]) return checkboardCache[key]\n \n const checkboard = renderCheckboard(white, grey, size)\n checkboardCache[key] = checkboard\n return checkboard\n}\n\nexport default defineComponent({\n name: 'checkboard',\n props: {\n size: {\n type: Number,\n default: 8,\n },\n white: {\n type: String,\n default: '#fff',\n },\n grey: {\n type: String,\n default: '#e6e6e6',\n },\n },\n setup(props) {\n const bgStyle = computed(() => {\n const checkboard = getCheckboard(props.white, props.grey, props.size)\n return { backgroundImage: `url(${checkboard})` }\n })\n\n return {\n bgStyle,\n }\n },\n})\n","import { render } from \"./Checkboard.vue?vue&type=template&id=2352ea60&scoped=true\"\nimport script from \"./Checkboard.vue?vue&type=script&lang=ts\"\nexport * from \"./Checkboard.vue?vue&type=script&lang=ts\"\n\nimport \"./Checkboard.vue?vue&type=style&index=0&id=2352ea60&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2352ea60\"\n\nexport default script","\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\n\nimport Checkboard from './Checkboard.vue'\nimport { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'alpha',\n components: {\n Checkboard,\n },\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props, { emit }) {\n const color = computed(() => props.value)\n const gradientColor = computed(() => {\n const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')\n return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`\n })\n\n const alphaRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!alphaRef.value) return\n const containerWidth = alphaRef.value.clientWidth\n const xOffset = alphaRef.value.getBoundingClientRect().left + window.pageXOffset\n const left = e.pageX - xOffset\n let a\n\n if(left < 0) a = 0\n else if(left > containerWidth) a = 1\n else a = Math.round(left * 100 / containerWidth) / 100\n\n if(color.value.a !== a) {\n emit('colorChange', {\n r: color.value.r,\n g: color.value.g,\n b: color.value.b,\n a: a,\n })\n }\n }\n\n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n alphaRef,\n gradientColor,\n handleMouseDown,\n color,\n }\n },\n})\n","import { render } from \"./Alpha.vue?vue&type=template&id=40ed15f5&scoped=true\"\nimport script from \"./Alpha.vue?vue&type=script&lang=ts\"\nexport * from \"./Alpha.vue?vue&type=script&lang=ts\"\n\nimport \"./Alpha.vue?vue&type=style&index=0&id=40ed15f5&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-40ed15f5\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, PropType, ref, watch } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'hue',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n hue: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const oldHue = ref(0)\n const pullDirection = ref('')\n \n const color = computed(() => {\n const hsla = tinycolor(props.value).toHsl()\n if(hsla.s === 0) hsla.h = props.hue\n return hsla\n })\n\n const pointerLeft = computed(() => {\n if(color.value.h === 0 && pullDirection.value === 'right') return '100%'\n return color.value.h * 100 / 360 + '%'\n })\n\n watch(() => props.value, () => {\n const hsla = tinycolor(props.value).toHsl()\n const h = hsla.s === 0 ? props.hue : hsla.h\n if(h !== 0 && h - oldHue.value > 0) pullDirection.value = 'right'\n if(h !== 0 && h - oldHue.value < 0) pullDirection.value = 'left'\n oldHue.value = h\n })\n\n const hueRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!hueRef.value) return\n\n const containerWidth = hueRef.value.clientWidth\n const xOffset = hueRef.value.getBoundingClientRect().left + window.pageXOffset\n const left = e.pageX - xOffset\n let h, percent\n \n if(left < 0) h = 0\n else if(left > containerWidth) h = 360\n else {\n percent = left * 100 / containerWidth\n h = (360 * percent / 100)\n }\n if(color.value.h !== h) {\n emit('colorChange', {\n h,\n l: color.value.l,\n s: color.value.s,\n a: color.value.a,\n })\n }\n }\n\n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n hueRef,\n handleMouseDown,\n pointerLeft,\n }\n },\n})\n","import { render } from \"./Hue.vue?vue&type=template&id=0cb6d507&scoped=true\"\nimport script from \"./Hue.vue?vue&type=script&lang=ts\"\nexport * from \"./Hue.vue?vue&type=script&lang=ts\"\n\nimport \"./Hue.vue?vue&type=style&index=0&id=0cb6d507&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0cb6d507\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\nimport throttle from 'lodash/throttle'\nimport clamp from 'lodash/clamp'\n\nexport default defineComponent({\n name: 'saturation',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n hue: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const color = computed(() => {\n const hsva = tinycolor(props.value).toHsv()\n if(hsva.s === 0) hsva.h = props.hue\n return hsva\n })\n\n const bgColor = computed(() => `hsl(${color.value.h}, 100%, 50%)`)\n const pointerTop = computed(() => (-(color.value.v * 100) + 1) + 100 + '%')\n const pointerLeft = computed(() => color.value.s * 100 + '%')\n\n const emitChangeEvent = throttle(function(param) {\n emit('colorChange', param)\n }, 20, { leading: true, trailing: false })\n\n const saturationRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!saturationRef.value) return\n \n const containerWidth = saturationRef.value.clientWidth\n const containerHeight = saturationRef.value.clientHeight\n const xOffset = saturationRef.value.getBoundingClientRect().left + window.pageXOffset\n const yOffset = saturationRef.value.getBoundingClientRect().top + window.pageYOffset\n const left = clamp(e.pageX - xOffset, 0, containerWidth)\n const top = clamp(e.pageY - yOffset, 0, containerHeight)\n const saturation = left / containerWidth\n const bright = clamp(-(top / containerHeight) + 1, 0, 1)\n\n emitChangeEvent({\n h: color.value.h,\n s: saturation,\n v: bright,\n a: color.value.a,\n })\n }\n\n \n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n saturationRef,\n bgColor,\n handleMouseDown,\n pointerTop,\n pointerLeft,\n }\n },\n})\n","import { render } from \"./Saturation.vue?vue&type=template&id=792755a0&scoped=true\"\nimport script from \"./Saturation.vue?vue&type=script&lang=ts\"\nexport * from \"./Saturation.vue?vue&type=script&lang=ts\"\n\nimport \"./Saturation.vue?vue&type=style&index=0&id=792755a0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-792755a0\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'editable-input',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props, { emit }) {\n const val = computed(() => {\n let _hex = ''\n if(props.value.a < 1) _hex = tinycolor(props.value).toHex8String().toUpperCase()\n else _hex = tinycolor(props.value).toHexString().toUpperCase()\n return _hex.replace('#', '')\n })\n\n const handleInput = (e: InputEvent) => {\n const value = (e.target as HTMLInputElement).value\n if(value.length >= 6) emit('colorChange', tinycolor(value).toRgb())\n }\n\n return {\n val,\n handleInput,\n }\n },\n})\n","import { render } from \"./EditableInput.vue?vue&type=template&id=67f94aae&scoped=true\"\nimport script from \"./EditableInput.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableInput.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableInput.vue?vue&type=style&index=0&id=67f94aae&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-67f94aae\"\n\nexport default script","\nimport { computed, defineComponent, ref } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nimport Alpha from './Alpha.vue'\nimport Checkboard from './Checkboard.vue'\nimport Hue from './Hue.vue'\nimport Saturation from './Saturation.vue'\nimport EditableInput from './EditableInput.vue'\n\nconst presetColorConfig = [\n ['#7f7f7f', '#f2f2f2'],\n ['#0d0d0d', '#808080'],\n ['#1c1a10', '#ddd8c3'],\n ['#0e243d', '#c6d9f0'],\n ['#233f5e', '#dae5f0'],\n ['#632623', '#f2dbdb'],\n ['#4d602c', '#eaf1de'],\n ['#3f3150', '#e6e0ec'],\n ['#1e5867', '#d9eef3'],\n ['#99490f', '#fee9da'],\n]\n\nconst gradient = (startColor: string, endColor: string, step: number) => {\n const _startColor = tinycolor(startColor).toRgb()\n const _endColor = tinycolor(endColor).toRgb()\n\n const rStep = (_endColor.r - _startColor.r) / step\n const gStep = (_endColor.g - _startColor.g) / step\n const bStep = (_endColor.b - _startColor.b) / step\n const gradientColorArr = []\n\n for(let i = 0; i < step; i++) {\n const gradientColor = tinycolor({\n r: _startColor.r + rStep * i,\n g: _startColor.g + gStep * i,\n b: _startColor.b + bStep * i,\n }).toRgbString()\n gradientColorArr.push(gradientColor)\n }\n return gradientColorArr\n}\n\nconst getPresetColors = () => {\n const presetColors = []\n for(const color of presetColorConfig) {\n presetColors.push(gradient(color[1], color[0], 5))\n }\n return presetColors\n}\n\nexport default defineComponent({\n name: 'color-picker',\n components: {\n Alpha,\n Checkboard,\n Hue,\n Saturation,\n EditableInput,\n },\n props: {\n modelValue: {\n type: String,\n default: '#e86b99',\n },\n },\n setup(props, { emit }) {\n const hue = ref(0)\n\n const color = computed({\n get() {\n return tinycolor(props.modelValue).toRgb()\n },\n set(rgba: ColorFormats.RGBA) {\n const rgbaString = `rgba(${[rgba.r, rgba.g, rgba.b, rgba.a].join(',')})`\n emit('update:modelValue', rgbaString)\n },\n })\n\n const themeColors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\n const standardColors = ['#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57', '#00afee', '#0071be', '#00215f', '#72349d']\n const presetColors = getPresetColors()\n\n const currentColor = computed(() => {\n return `rgba(${[color.value.r, color.value.g, color.value.b, color.value.a].join(',')})`\n })\n\n const selectPresetColor = (colorString: string) => {\n emit('update:modelValue', colorString)\n }\n\n const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {\n if('h' in value) {\n hue.value = value.h\n color.value = tinycolor(value).toRgb()\n }\n else color.value = value\n }\n\n return {\n themeColors,\n standardColors,\n presetColors,\n color,\n hue,\n currentColor,\n changeColor,\n selectPresetColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=dc0cf132&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=dc0cf132&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dc0cf132\"\n\nexport default script","import { createApp } from 'vue'\nimport App from './App.vue'\nimport { store, key } from './store'\n\nimport '@icon-park/vue-next/styles/index.css'\nimport 'prosemirror-view/style/prosemirror.css'\nimport '@/assets/styles/prosemirror.scss'\nimport '@/assets/styles/global.scss'\nimport '@/assets/styles/antd.scss'\nimport '@/assets/styles/font.scss'\nimport 'animate.css'\n\nimport Contextmenu from './plugins/contextmenu'\nimport ClickOutside from './plugins/clickOutside'\nimport IconPark from './plugins/iconPark'\n\nimport FileInput from '@/components/FileInput.vue'\nimport SvgWrapper from '@/components/SvgWrapper.vue'\nimport CheckboxButton from '@/components/CheckboxButton.vue'\nimport CheckboxButtonGroup from '@/components/CheckboxButtonGroup.vue'\nimport ColorPicker from '@/components/ColorPicker/index.vue'\n\nimport {\n InputNumber,\n Divider,\n Button,\n Tooltip,\n Popover,\n Slider,\n Select,\n Switch,\n Radio,\n Input,\n Modal,\n Dropdown,\n Menu,\n Checkbox,\n Drawer,\n} from 'ant-design-vue'\n\nconst app = createApp(App)\n\napp.component('InputNumber', InputNumber)\napp.component('Divider', Divider)\napp.component('Button', Button)\napp.component('ButtonGroup', Button.Group)\napp.component('Tooltip', Tooltip)\napp.component('Popover', Popover)\napp.component('Slider', Slider)\napp.component('Select', Select)\napp.component('SelectOption', Select.Option)\napp.component('SelectOptGroup', Select.OptGroup)\napp.component('Switch', Switch)\napp.component('Radio', Radio)\napp.component('RadioGroup', Radio.Group)\napp.component('RadioButton', Radio.Button)\napp.component('Input', Input)\napp.component('InputGroup', Input.Group)\napp.component('Modal', Modal)\napp.component('Dropdown', Dropdown)\napp.component('Menu', Menu)\napp.component('MenuItem', Menu.Item)\napp.component('Checkbox', Checkbox)\napp.component('Drawer', Drawer)\n\napp.directive('contextmenu', Contextmenu)\napp.directive('click-outside', ClickOutside)\napp.use(IconPark)\n\napp.component('FileInput', FileInput)\napp.component('SvgWrapper', SvgWrapper)\napp.component('CheckboxButton', CheckboxButton)\napp.component('CheckboxButtonGroup', CheckboxButtonGroup)\napp.component('ColorPicker', ColorPicker)\n\napp.use(store, key)\napp.mount('#app')\n","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=0bd1ca02&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Chart.vue?vue&type=style&index=1&id=5f401eca&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./TableGenerator.vue?vue&type=style&index=0&id=0239b43b&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Hue.vue?vue&type=style&index=0&id=0cb6d507&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementOutline.vue?vue&type=style&index=0&id=38e2f880&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MenuContent.vue?vue&type=style&index=0&id=3cad6828&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementPositionPanel.vue?vue&type=style&index=0&id=1a79147f&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=7550799e&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ShapeStylePanel.vue?vue&type=style&index=0&id=d415c6bc&lang=scss&scoped=true\""],"sourceRoot":""} \ No newline at end of file diff --git a/dist/js/app.afd2a1d5.js b/dist/js/app.afd2a1d5.js new file mode 100644 index 0000000..dc09f4d --- /dev/null +++ b/dist/js/app.afd2a1d5.js @@ -0,0 +1,2 @@ +(function(e){function t(t){for(var o,r,l=t[0],i=t[1],u=t[2],s=0,f=[];s一段测试文字,字号固定为28px

"},{id:"xxx3",type:"image",left:80,top:250,width:180,height:180,rotate:0,outline:{width:4,style:"solid",color:"#333"},clip:{range:[[30,0],[100,70]],shape:"ellipse"},fixedRatio:!1,lock:!1,src:"https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/1573622467064v2-7aa3ce420052983d91c6d01b47a7441d_hd.jpg"},{id:"xxx2",type:"image",left:750,top:320,width:150,height:150,rotate:0,fixedRatio:!0,lock:!1,src:"https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/62d9adb3-e7a6-4dc4-a352-095cffb49f08/b1be1a2f-f893-47d3-a8a3-eac7d04d395f/1596159381259v2-b2c69096d25ae16bf6ca09e30add3e65_hd.jpg"}],animations:[{elId:"xxx1",type:"rotateIn",duration:1e3},{elId:"xxx2",type:"zoomIn",duration:1e3}]},{id:"sajd172",elements:[{id:"yyx1",type:"text",left:590,top:90,width:220,height:188,rotate:0,opacity:1,lock:!1,content:"
😀 😐 😶 😜 🔔 ⭐ ⚡ 🔥 👍 💡 🔰 🎀 🎁 🥇 🏅 🏆 🎈 🎉 💎 🚧 ⛔ 📢 ⌛ ⏰ 🕒 🧩 🎵 📎 🔒 🔑 ⛳ 📌 📍 💬 📅 📈 📋 📜 📁 📱 💻 💾 🌏 🚚 🚡 🚢💧 🌐 🧭 💰 💳 🛒
"},{id:"xsfdas",type:"line",width:2,left:100,top:400,end:[0,0],start:[300,120],style:"solid",color:"#888",points:["","arrow"]},{id:"xxx7",type:"shape",left:130,top:50,width:150,height:150,rotate:0,fill:"#eebc29",opacity:.9,fixedRatio:!1,lock:!1,viewBox:1024,path:"M721.35111111 475.59111111H302.64888889c-5.00622222 0-9.10222222 4.096-9.10222222 9.10222222v54.61333334c0 5.00622222 4.096 9.10222222 9.10222222 9.10222222h418.70222222c5.00622222 0 9.10222222-4.096 9.10222222-9.10222222v-54.61333334c0-5.00622222-4.096-9.10222222-9.10222222-9.10222222z M512 2.27555555C230.51377778 2.27555555 2.27555555 230.51377778 2.27555555 512s228.23822222 509.72444445 509.72444445 509.72444445 509.72444445-228.23822222 509.72444445-509.72444445S793.48622222 2.27555555 512 2.27555555z m0 932.97777778c-233.69955555 0-423.25333333-189.55377778-423.25333333-423.25333333s189.55377778-423.25333333 423.25333333-423.25333333 423.25333333 189.55377778 423.25333333 423.25333333-189.55377778 423.25333333-423.25333333 423.25333333z"}],animations:[{elId:"yyx1",type:"flipInX",duration:1e3}]}],I={activeElementIdList:[],handleElementId:"",canvasPercentage:90,canvasScale:1,thumbnailsFocus:!1,editorAreaFocus:!1,disableHotkeys:!1,showGridLines:!1,creatingElement:null,availableFonts:[],toolbarState:"slideStyle",theme:{themeColor:"#d14424",fontColor:"#333",fontName:"微软雅黑",backgroundColor:"#fff"},slides:E,slideIndex:0,snapshotCursor:-1,snapshotLength:0,ctrlKeyState:!1,shiftKeyState:!1,screening:!1,clipingImageElementId:""},S=(n("4de4"),n("7db0"),n("caad"),n("d81d"),n("2532"),{currentSlide:function(e){return e.slides[e.slideIndex]||null},currentSlideAnimations:function(e){var t=e.slides[e.slideIndex];if(!t)return null;var n=t.animations;if(!n)return null;var o=t.elements,c=o.map((function(e){return e.id}));return n.filter((function(e){return c.includes(e.elId)}))},activeElementList:function(e){var t=e.slides[e.slideIndex];return t&&t.elements?t.elements.filter((function(t){return e.activeElementIdList.includes(t.id)})):[]},handleElement:function(e){var t=e.slides[e.slideIndex];return t&&t.elements&&t.elements.find((function(t){return e.handleElementId===t.id}))||null},canUndo:function(e){return e.snapshotCursor>0},canRedo:function(e){return e.snapshotCursor=0&&n.snapshotCursor20&&(a.push(c[0]),l--),l>=2&&M.snapshots.update(c[l-2],{index:n.slideIndex}),t.next=14,M.snapshots.bulkDelete(a);case 14:o(g.SET_SNAPSHOT_CURSOR,l-1),o(g.SET_SNAPSHOT_LENGTH,l);case 16:case"end":return t.stop()}}),t)})))()})),Object(C["a"])(N,y.UN_DO,(function(e){return Object(x["a"])(regeneratorRuntime.mark((function t(){var n,o,c,a,r,l,i;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(n=e.state,o=e.commit,!(n.snapshotCursor<=0)){t.next=3;break}return t.abrupt("return");case 3:return c=n.snapshotCursor-1,t.next=6,M.snapshots.orderBy("id").toArray();case 6:a=t.sent,r=a[c],l=r.index,i=r.slides,o(g.SET_SLIDES,i),o(g.UPDATE_SLIDE_INDEX,l),o(g.SET_SNAPSHOT_CURSOR,c),o(g.SET_ACTIVE_ELEMENT_ID_LIST,[]);case 13:case"end":return t.stop()}}),t)})))()})),Object(C["a"])(N,y.RE_DO,(function(e){return Object(x["a"])(regeneratorRuntime.mark((function t(){var n,o,c,a,r,l,i;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(n=e.state,o=e.commit,!(n.snapshotCursor>=n.snapshotLength-1)){t.next=3;break}return t.abrupt("return");case 3:return c=n.snapshotCursor+1,t.next=6,M.snapshots.orderBy("id").toArray();case 6:a=t.sent,r=a[c],l=r.index,i=r.slides,o(g.SET_SLIDES,i),o(g.UPDATE_SLIDE_INDEX,l),o(g.SET_SNAPSHOT_CURSOR,c),o(g.SET_ACTIVE_ELEMENT_ID_LIST,[]);case 13:case"end":return t.stop()}}),t)})))()})),N),A=(n("99af"),n("c740"),n("a434"),n("2909")),P=n("5530"),R=n("3eea"),F=n.n(R),z=[{zh:"微软雅黑",en:"Microsoft Yahei"},{zh:"宋体",en:"SimSun"},{zh:"黑体",en:"SimHei"},{zh:"楷体",en:"KaiTi"},{zh:"新宋体",en:"NSimSun"},{zh:"仿宋",en:"FangSong"},{zh:"苹方",en:"PingFang SC"},{zh:"华文黑体",en:"STHeiti"},{zh:"华文楷体",en:"STKaiti"},{zh:"华文宋体",en:"STSong"},{zh:"华文仿宋",en:"STFangSong"},{zh:"华文中宋",en:"STZhongSong"},{zh:"华文琥珀",en:"STHupo"},{zh:"华文新魏",en:"STXinwei"},{zh:"华文隶书",en:"STLiti"},{zh:"华文行楷",en:"STXingkai"},{zh:"冬青黑体简",en:"Hiragino Sans GB"},{zh:"兰亭黑-简",en:"Lantinghei SC"},{zh:"偏偏体-简",en:"Hanzipen SC"},{zh:"手札体-简",en:"Hannotate SC"},{zh:"宋体-简",en:"Songti SC"},{zh:"娃娃体-简",en:"Wawati SC"},{zh:"行楷-简",en:"Xingkai SC"},{zh:"圆体-简",en:"Yuanti SC"},{zh:"华文细黑",en:"STXihei"},{zh:"幼圆",en:"YouYuan"},{zh:"隶书",en:"LiSu"},{zh:"Arial",en:"Arial"}],H=[{name:"仓耳小丸子"},{name:"优设标题黑"},{name:"峰广明锐体"},{name:"摄图摩登小方体"},{name:"站酷快乐体"},{name:"站酷酷黑体"},{name:"素材集市康康体"},{name:"联盟起艺卢帅正锐黑体"},{name:"谦度手写楷体"},{name:"途牛类圆体"},{name:"锐字真言体"},{name:"问藏书房"}],U=(n("a15b"),function(e){if("string"!==typeof e)return!1;var t="Arial";if(e.toLowerCase()===t.toLowerCase())return!0;var n="a",o=100,c=100,a=100,r=document.createElement("canvas"),l=r.getContext("2d");if(!l)return!1;r.width=c,r.height=a,l.textAlign="center",l.fillStyle="black",l.textBaseline="middle";var i=function(e){l.clearRect(0,0,c,a),l.font="".concat(o,"px ").concat(e,", ").concat(t),l.fillText(n,c/2,a/2);var r=l.getImageData(0,0,c,a).data;return[].slice.call(r).filter((function(e){return 0!==e}))};return i(t).join("")!==i(e).join("")}),G=(T={},Object(C["a"])(T,g.SET_ACTIVE_ELEMENT_ID_LIST,(function(e,t){1===t.length?e.handleElementId=t[0]:e.handleElementId="",e.activeElementIdList=t})),Object(C["a"])(T,g.SET_HANDLE_ELEMENT_ID,(function(e,t){e.handleElementId=t})),Object(C["a"])(T,g.SET_CANVAS_PERCENTAGE,(function(e,t){e.canvasPercentage=t})),Object(C["a"])(T,g.SET_CANVAS_SCALE,(function(e,t){e.canvasScale=t})),Object(C["a"])(T,g.SET_THUMBNAILS_FOCUS,(function(e,t){e.thumbnailsFocus=t})),Object(C["a"])(T,g.SET_EDITORAREA_FOCUS,(function(e,t){e.editorAreaFocus=t})),Object(C["a"])(T,g.SET_DISABLE_HOTKEYS_STATE,(function(e,t){e.disableHotkeys=t})),Object(C["a"])(T,g.SET_GRID_LINES_STATE,(function(e,t){e.showGridLines=t})),Object(C["a"])(T,g.SET_CREATING_ELEMENT,(function(e,t){e.creatingElement=t})),Object(C["a"])(T,g.SET_AVAILABLE_FONTS,(function(e){e.availableFonts=z.filter((function(e){return U(e.en)}))})),Object(C["a"])(T,g.SET_TOOLBAR_STATE,(function(e,t){e.toolbarState=t})),Object(C["a"])(T,g.SET_CLIPING_IMAGE_ELEMENT_ID,(function(e,t){e.clipingImageElementId=t})),Object(C["a"])(T,g.SET_THEME,(function(e,t){e.theme=Object(P["a"])(Object(P["a"])({},e.theme),t)})),Object(C["a"])(T,g.SET_SLIDES,(function(e,t){e.slides=t})),Object(C["a"])(T,g.ADD_SLIDE,(function(e,t){var n=e.slideIndex+1;e.slides.splice(n,0,t),e.slideIndex=n})),Object(C["a"])(T,g.UPDATE_SLIDE,(function(e,t){var n=e.slideIndex;e.slides[n]=Object(P["a"])(Object(P["a"])({},e.slides[n]),t)})),Object(C["a"])(T,g.DELETE_SLIDE,(function(e,t){var n=e.slides.findIndex((function(e){return e.id===t}));n===e.slides.length-1&&(e.slideIndex=n-1),e.slides.splice(n,1)})),Object(C["a"])(T,g.UPDATE_SLIDE_INDEX,(function(e,t){e.slideIndex=t})),Object(C["a"])(T,g.ADD_ELEMENT,(function(e,t){var n=Array.isArray(t)?t:[t],o=e.slides[e.slideIndex].elements,c=[].concat(Object(A["a"])(o),Object(A["a"])(n));e.slides[e.slideIndex].elements=c})),Object(C["a"])(T,g.UPDATE_ELEMENT,(function(e,t){var n=t.id,o=t.props,c="string"===typeof n?[n]:n,a=e.slideIndex,r=e.slides[a],l=r.elements.map((function(e){return c.includes(e.id)?Object(P["a"])(Object(P["a"])({},e),o):e}));e.slides[a].elements=l})),Object(C["a"])(T,g.REMOVE_ELEMENT_PROPS,(function(e,t){var n=t.id,o=t.propName,c="string"===typeof o?[o]:o,a=e.slideIndex,r=e.slides[a],l=r.elements.map((function(e){return e.id===n?F()(e,c):e}));e.slides[a].elements=l})),Object(C["a"])(T,g.SET_SNAPSHOT_CURSOR,(function(e,t){e.snapshotCursor=t})),Object(C["a"])(T,g.SET_SNAPSHOT_LENGTH,(function(e,t){e.snapshotLength=t})),Object(C["a"])(T,g.SET_CTRL_KEY_STATE,(function(e,t){e.ctrlKeyState=t})),Object(C["a"])(T,g.SET_SHIFT_KEY_STATE,(function(e,t){e.shiftKeyState=t})),Object(C["a"])(T,g.SET_SCREENING,(function(e,t){e.screening=t})),T),q=Symbol(),W=Object(k["a"])({state:I,getters:S,mutations:G,actions:D}),X=function(){return Object(k["b"])(q)},Y=Object(h["withScopeId"])("data-v-d5c6b448");Object(h["pushScopeId"])("data-v-d5c6b448");var Z={class:"hamster-ppt-editor"},J={class:"layout-content"},K={class:"layout-content-center"};Object(h["popScopeId"])();var $,Q=Y((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("EditorHeader"),l=Object(h["resolveComponent"])("Thumbnails"),i=Object(h["resolveComponent"])("CanvasTool"),u=Object(h["resolveComponent"])("Canvas"),d=Object(h["resolveComponent"])("Toolbar");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Z,[Object(h["createVNode"])(r,{class:"layout-header"}),Object(h["createVNode"])("div",J,[Object(h["createVNode"])(l,{class:"layout-content-left"}),Object(h["createVNode"])("div",K,[Object(h["createVNode"])(i,{class:"center-top"}),Object(h["createVNode"])(u,{class:"center-body"})]),Object(h["createVNode"])(d,{class:"layout-content-right"})])])}));(function(e){e["C"]="C",e["X"]="X",e["Z"]="Z",e["Y"]="Y",e["A"]="A",e["G"]="G",e["L"]="L",e["F"]="F",e["D"]="D",e["MINUS"]="-",e["EQUAL"]="=",e["DIGIT_0"]="0",e["DELETE"]="DELETE",e["UP"]="ARROWUP",e["DOWN"]="ARROWDOWN",e["LEFT"]="ARROWLEFT",e["RIGHT"]="ARROWRIGHT",e["ENTER"]="ENTER",e["SPACE"]=" ",e["TAB"]="TAB"})($||($={}));n("3b18");var ee=n("f64c"),te=n("4106"),ne=n.n(te),oe=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:6,t="_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",n=t.length,o="",c=0;cEe?(n=Ee,o=n*c):o>Ee*Ie&&(o=Ee*Ie,n=o/c),a({type:"image",id:oe(),src:e,width:n,height:o,left:(Ee-n)/2,top:(Ee*Ie-o)/2,fixedRatio:!0})}))},l=function(e){a({type:"chart",id:oe(),chartType:e,left:300,top:81.25,width:400,height:400,themeColor:t.value,gridColor:n.value,data:{labels:["类别1","类别2","类别3","类别4","类别5"],series:[[12,19,5,2,18]]}})},i=function(e,n){var o=new Array(n).fill({id:oe(),colspan:1,rowspan:1,text:""}),c=new Array(e).fill(o),r=100,l=36,i=new Array(n).fill(1/n),u=n*r,d=e*l;a({type:"table",id:oe(),width:u,height:d,colWidths:i,data:c,left:(Ee-u)/2,top:(Ee*Ie-d)/2,outline:{width:2,style:"solid",color:"#eeece1"},theme:{color:t.value,rowHeader:!0,rowFooter:!1,colHeader:!1,colFooter:!1}})},u=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"请输入内容",n=e.left,o=e.top,c=e.width,r=e.height;a({type:"text",id:oe(),left:n,top:o,width:c,height:r,content:t})},d=function(e,n){var o=e.left,c=e.top,r=e.width,l=e.height;a({type:"shape",id:oe(),left:o,top:c,width:r,height:l,viewBox:n.viewBox,path:n.path,fill:t.value,fixedRatio:!1})},s=function(e,n){var o=e.left,c=e.top,r=e.start,l=e.end;a({type:"line",id:oe(),left:o,top:c,start:r,end:l,points:n.points,color:t.value,style:"solid",width:2})};return{createImageElement:r,createChartElement:l,createTableElement:i,createTextElement:u,createShapeElement:d,createLineElement:s}},Ce=function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.currentSlide})),n=ge(),o=n.addHistorySnapshot,c=Se(),a=c.createTextElement,r=function(n){var c,a={},r={},l=Object(me["a"])(n);try{for(l.s();!(c=l.n()).done;){var i=c.value,u=i.groupId;u&&!a[u]&&(a[u]=oe()),r[i.id]=oe()}}catch(m){l.e(m)}finally{l.f()}var d,s=t.value.elements.map((function(e){return e.id})),f=Object(me["a"])(n);try{for(f.s();!(d=f.n()).done;){var p=d.value,b=s.includes(p.id);p.id=r[p.id],b&&(p.left=p.left+10,p.top=p.top+10),p.groupId&&(p.groupId=a[p.groupId])}}catch(m){f.e(m)}finally{f.f()}e.commit(g.ADD_ELEMENT,n),e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,Object.values(r)),o()},l=function(t){e.commit(g.ADD_SLIDE,t),o()},i=function(e){a({left:0,top:0,width:600,height:50},e)},u=function(e,t){var n,o=(null===t||void 0===t?void 0:t.onlySlide)||!1,c=(null===t||void 0===t?void 0:t.onlyElements)||!1;try{n=JSON.parse(pe(e))}catch(s){n=e}if("object"===Object(be["a"])(n)){var a=n,u=a.type,d=a.data;"elements"!==u||o?"slide"!==u||c||l(d):r(d)}else c||o||i(n)};return{pasteTextClipboardData:u}},xe=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slideIndex})),n=Object(h["computed"])((function(){return e.state.theme})),o=Object(h["computed"])((function(){return e.state.slides.length})),c=Object(h["computed"])((function(){return e.getters.currentSlide})),a=Ce(),r=a.pasteTextClipboardData,l=ge(),i=l.addHistorySnapshot,u=function(n){var c=0;n===$.UP&&t.value>0?c=t.value-1:n===$.DOWN&&t.value=r&&(o-=c),e.commit(g.SET_CANVAS_PERCENTAGE,o)},o=function(t){e.commit(g.SET_CANVAS_PERCENTAGE,t)};return{scaleCanvas:n,setCanvasPercentage:o}},Re=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.ctrlKeyState})),n=Object(h["computed"])((function(){return e.state.shiftKeyState})),o=Object(h["computed"])((function(){return e.state.disableHotkeys})),c=Object(h["computed"])((function(){return e.state.activeElementIdList})),a=Object(h["computed"])((function(){return e.state.editorAreaFocus})),r=Object(h["computed"])((function(){return e.state.thumbnailsFocus})),l=xe(),i=l.updateSlideIndex,u=l.copySlide,d=l.createSlide,s=l.deleteSlide,f=l.cutSlide,p=l.copyAndPasteSlide,b=we(),m=b.combineElements,v=b.uncombineElements,O=Te(),j=O.deleteElement,y=Ne(),k=y.lockElement,E=Le(),I=E.copyElement,S=E.cutElement,C=E.quickCopyElement,x=Ve(),N=x.selectAllElement,T=_e(),w=T.moveElement,L=ge(),V=L.redo,_=L.undo,B=Ae(),M=B.enterScreening,D=Pe(),A=D.scaleCanvas,P=D.setCanvasPercentage,R=function(){c.value.length?I():r.value&&u()},F=function(){c.value.length?S():r.value&&f()},z=function(){c.value.length?C():r.value&&p()},H=function(){a.value&&N()},U=function(){a.value&&k()},G=function(){a.value&&m()},q=function(){a.value&&v()},W=function(){c.value.length?j():r.value&&s()},Y=function(e){c.value.length?w(e):e!==$.UP&&e!==$.DOWN||i(e)},Z=function(){r.value&&d()},J=function(c){var l=c.ctrlKey,i=c.shiftKey,u=c.metaKey,d=c.key.toUpperCase();if(l&&!t.value&&e.commit(g.SET_CTRL_KEY_STATE,!0),i&&!n.value&&e.commit(g.SET_SHIFT_KEY_STATE,!0),l&&d===$.F&&(c.preventDefault(),M(),e.commit(g.SET_CTRL_KEY_STATE,!1)),a.value||r.value){if((l||u)&&d===$.C){if(o.value)return;c.preventDefault(),R()}if(l&&d===$.X){if(o.value)return;c.preventDefault(),F()}if(l&&d===$.D){if(o.value)return;c.preventDefault(),z()}if(l&&d===$.Z){if(o.value)return;c.preventDefault(),_()}if(l&&d===$.Y){if(o.value)return;c.preventDefault(),V()}if(l&&d===$.A){if(o.value)return;c.preventDefault(),H()}if(l&&d===$.L){if(o.value)return;c.preventDefault(),U()}if(!i&&l&&d===$.G){if(o.value)return;c.preventDefault(),G()}if(i&&l&&d===$.G){if(o.value)return;c.preventDefault(),q()}if(d===$.DELETE){if(o.value)return;c.preventDefault(),W()}if(d===$.UP){if(o.value)return;c.preventDefault(),Y($.UP)}if(d===$.DOWN){if(o.value)return;c.preventDefault(),Y($.DOWN)}if(d===$.LEFT){if(o.value)return;c.preventDefault(),Y($.LEFT)}if(d===$.RIGHT){if(o.value)return;c.preventDefault(),Y($.RIGHT)}if(d===$.ENTER){if(o.value)return;c.preventDefault(),Z()}if(d===$.MINUS){if(o.value)return;c.preventDefault(),A("-")}if(d===$.EQUAL){if(o.value)return;c.preventDefault(),A("+")}if(d===$.DIGIT_0){if(o.value)return;c.preventDefault(),P(90)}}},K=function(){t.value&&e.commit(g.SET_CTRL_KEY_STATE,!1),n.value&&e.commit(g.SET_SHIFT_KEY_STATE,!1)};Object(h["onMounted"])((function(){document.addEventListener("keydown",J),document.addEventListener("keyup",K),window.addEventListener("blur",K)})),Object(h["onUnmounted"])((function(){document.removeEventListener("keydown",J),document.removeEventListener("keyup",K),window.removeEventListener("blur",K)}))},Fe=(n("c975"),function(){var e=X(),t=Object(h["computed"])((function(){return e.state.editorAreaFocus})),n=Object(h["computed"])((function(){return e.state.thumbnailsFocus})),o=Object(h["computed"])((function(){return e.state.disableHotkeys})),c=Ce(),a=c.pasteTextClipboardData,r=Se(),l=r.createImageElement,i=function(e){ke(e).then((function(e){return l(e)}))},u=function(e){if((t.value||n.value)&&!o.value&&e.clipboardData){var c=e.clipboardData.items,r=c[0];if(r){var l,u=Object(me["a"])(c);try{for(u.s();!(l=u.n()).done;){var d=l.value;if("file"===d.kind&&-1!==d.type.indexOf("image")){var s=d.getAsFile();return void(s&&i(s))}}}catch(f){u.e(f)}finally{u.f()}"string"===r.kind&&"text/plain"===r.type&&r.getAsString((function(e){return a(e)}))}}};Object(h["onMounted"])((function(){document.addEventListener("paste",u)})),Object(h["onUnmounted"])((function(){document.removeEventListener("paste",u)}))}),ze=Object(h["withScopeId"])("data-v-2accc3e9");Object(h["pushScopeId"])("data-v-2accc3e9");var He={class:"editor-header"},Ue={class:"left"},Ge={class:"menu-item"},qe=Object(h["createTextVNode"])(" 编辑"),We=Object(h["createTextVNode"])("撤销"),Xe=Object(h["createTextVNode"])("重做"),Ye=Object(h["createTextVNode"])("添加页面"),Ze=Object(h["createTextVNode"])("删除页面"),Je=Object(h["createTextVNode"])("重置幻灯片"),Ke={class:"menu-item"},$e=Object(h["createTextVNode"])(" 演示"),Qe=Object(h["createTextVNode"])("从头开始"),et=Object(h["createTextVNode"])("从当前页开始"),tt={class:"menu-item"},nt=Object(h["createTextVNode"])(" 帮助"),ot=Object(h["createTextVNode"])("开发文档"),ct=Object(h["createTextVNode"])("快捷键"),at={class:"right"},rt={class:"menu-item"},lt={class:"hotkeys"},it={class:"title"},ut={class:"label"},dt={class:"value"};Object(h["popScopeId"])();var st=ze((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEdit"),l=Object(h["resolveComponent"])("MenuItem"),i=Object(h["resolveComponent"])("Menu"),u=Object(h["resolveComponent"])("Dropdown"),d=Object(h["resolveComponent"])("IconPpt"),s=Object(h["resolveComponent"])("IconHelpcenter"),f=Object(h["resolveComponent"])("Tooltip"),p=Object(h["resolveComponent"])("IconGithub"),b=Object(h["resolveComponent"])("Drawer");return Object(h["openBlock"])(),Object(h["createBlock"])("div",He,[Object(h["createVNode"])("div",Ue,[Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[1]||(t[1]=function(t){return e.undo()})},{default:ze((function(){return[We]})),_:1}),Object(h["createVNode"])(l,{onClick:t[2]||(t[2]=function(t){return e.redo()})},{default:ze((function(){return[Xe]})),_:1}),Object(h["createVNode"])(l,{onClick:t[3]||(t[3]=function(t){return e.createSlide()})},{default:ze((function(){return[Ye]})),_:1}),Object(h["createVNode"])(l,{onClick:t[4]||(t[4]=function(t){return e.deleteSlide()})},{default:ze((function(){return[Ze]})),_:1}),Object(h["createVNode"])(l,{onClick:t[5]||(t[5]=function(t){return e.toggleGridLines()})},{default:ze((function(){return[Object(h["createTextVNode"])(Object(h["toDisplayString"])(e.showGridLines?"关闭网格线":"打开网格线"),1)]})),_:1}),Object(h["createVNode"])(l,{onClick:t[6]||(t[6]=function(t){return e.resetSlides()})},{default:ze((function(){return[Je]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",Ge,[Object(h["createVNode"])(r),qe])]})),_:1}),Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[7]||(t[7]=function(t){return e.enterScreeningFromStart()})},{default:ze((function(){return[Qe]})),_:1}),Object(h["createVNode"])(l,{onClick:t[8]||(t[8]=function(t){return e.enterScreening()})},{default:ze((function(){return[et]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",Ke,[Object(h["createVNode"])(d),$e])]})),_:1}),Object(h["createVNode"])(u,{trigger:["click"]},{overlay:ze((function(){return[Object(h["createVNode"])(i,null,{default:ze((function(){return[Object(h["createVNode"])(l,{onClick:t[9]||(t[9]=function(t){return e.openDoc()})},{default:ze((function(){return[ot]})),_:1}),Object(h["createVNode"])(l,{onClick:t[10]||(t[10]=function(t){return e.hotkeyDrawerVisible=!0})},{default:ze((function(){return[ct]})),_:1})]})),_:1})]})),default:ze((function(){return[Object(h["createVNode"])("div",tt,[Object(h["createVNode"])(s),nt])]})),_:1})]),Object(h["createVNode"])("div",at,[Object(h["createVNode"])(f,{mouseLeaveDelay:0,title:"幻灯片放映"},{default:ze((function(){return[Object(h["createVNode"])("div",{class:"menu-item",onClick:t[11]||(t[11]=function(t){return e.enterScreening()})},[Object(h["createVNode"])(d,{size:"18",fill:"#666",style:{"margin-top":"2px"}})])]})),_:1}),Object(h["createVNode"])(f,{mouseLeaveDelay:0,title:"Github 仓库"},{default:ze((function(){return[Object(h["createVNode"])("div",rt,[Object(h["createVNode"])(p,{size:"18",fill:"#666"})])]})),_:1})]),Object(h["createVNode"])(b,{width:"320",placement:"right",visible:e.hotkeyDrawerVisible,onClose:t[12]||(t[12]=function(t){return e.hotkeyDrawerVisible=!1})},{default:ze((function(){return[Object(h["createVNode"])("div",lt,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.hotkeys,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:e.type},[Object(h["createVNode"])("div",it,Object(h["toDisplayString"])(e.type),1),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.children,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"hotkey-item",key:e.label},[Object(h["createVNode"])("div",ut,Object(h["toDisplayString"])(e.label),1),Object(h["createVNode"])("div",dt,Object(h["toDisplayString"])(e.value),1)])})),128))],64)})),128))])]})),_:1},8,["visible"])])})),ft=[{type:"通用",children:[{label:"剪切",value:"Ctrl + X"},{label:"复制",value:"Ctrl + C"},{label:"粘贴",value:"Ctrl + V"},{label:"快速复制粘贴",value:"Ctrl + D"},{label:"全选",value:"Ctrl + A"},{label:"撤销",value:"Ctrl + Z"},{label:"恢复",value:"Ctrl + Y"},{label:"删除",value:"Delete"}]},{type:"幻灯片放映",children:[{label:"开始放映幻灯片",value:"Ctrl + F"},{label:"切换上一页",value:"↑ / ←"},{label:"切换下一页",value:"↓ / → / Enter / Space"},{label:"退出放映",value:"ESC"}]},{type:"幻灯片编辑",children:[{label:"新建幻灯片",value:"Enter"},{label:"缩放画布",value:"Ctrl + 鼠标滚动"},{label:"放大画布",value:"Ctrl + ="},{label:"缩小画布",value:"Ctrl + -"},{label:"缩放画布到合适大小",value:"Ctrl + 0"},{label:"编辑上一页",value:"↑ / ←"},{label:"编辑下一页",value:"↓ / →"}]},{type:"元素操作",children:[{label:"移动",value:"↑ / ← / ↓ / →"},{label:"锁定",value:"Ctrl + L"},{label:"组合",value:"Ctrl + G"},{label:"取消组合",value:"Ctrl + Shift + G"},{label:"多选",value:"按住 Ctrl 或 Shift"},{label:"锁定宽高比例",value:"按住 Ctrl 或 Shift"},{label:"创建水平 / 垂直线条",value:"按住 Ctrl 或 Shift"},{label:"确认图片裁剪",value:"Enter"}]},{type:"表格编辑",children:[{label:"聚焦到下一个单元格",value:"Tab"}]},{type:"文本编辑",children:[{label:"加粗",value:"Ctrl + B"},{label:"斜体",value:"Ctrl + I"},{label:"下划线",value:"Ctrl + U"},{label:"删除线",value:"Ctrl + D"}]}],pt=Object(h["defineComponent"])({name:"editor-header",setup:function(){var e=X(),t=Ae(),n=t.enterScreening,o=t.enterScreeningFromStart,c=xe(),a=c.createSlide,r=c.deleteSlide,l=ge(),i=l.redo,u=l.undo,d=Object(h["computed"])((function(){return e.state.showGridLines})),s=function(){e.commit(g.SET_GRID_LINES_STATE,!d.value)},f=function(){e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,[]),e.commit(g.SET_SLIDES,[{id:oe(),elements:[]}])},p=function(){ee["a"].warning("作者努力编写中...")},b=Object(h["ref"])(!1);return{enterScreening:n,enterScreeningFromStart:o,createSlide:a,deleteSlide:r,redo:i,undo:u,toggleGridLines:s,showGridLines:d,resetSlides:f,openDoc:p,hotkeyDrawerVisible:b,hotkeys:ft}}});n("5c0a");pt.render=st,pt.__scopeId="data-v-2accc3e9";var bt=pt,mt=Object(h["withScopeId"])("data-v-75c486b2");Object(h["pushScopeId"])("data-v-75c486b2");var vt={class:"operates"};Object(h["popScopeId"])();var Ot,ht,jt,gt,yt,kt=mt((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementCreateSelection"),l=Object(h["resolveComponent"])("AlignmentLine"),i=Object(h["resolveComponent"])("MultiSelectOperate"),u=Object(h["resolveComponent"])("Operate"),d=Object(h["resolveComponent"])("SlideBackground"),s=Object(h["resolveComponent"])("MouseSelection"),f=Object(h["resolveComponent"])("EditableElement"),p=Object(h["resolveDirective"])("contextmenu"),b=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"canvas",ref:"canvasRef",onMousewheel:t[2]||(t[2]=function(t){return e.mousewheelScaleCanvas(t)}),onMousedown:t[3]||(t[3]=function(t){return e.handleClickBlankArea(t)})},[e.creatingElement?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,onCreated:t[1]||(t[1]=function(t){return e.insertElementFromCreateSelection(t)})})):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"viewport-wrapper",style:{width:e.viewportStyles.width*e.canvasScale+"px",height:e.viewportStyles.height*e.canvasScale+"px",left:e.viewportStyles.left+"px",top:e.viewportStyles.top+"px"}},[Object(h["createVNode"])("div",vt,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.alignmentLines,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:t,type:e.type,axis:e.axis,length:e.length},null,8,["type","axis","length"])})),128)),e.activeElementIdList.length>1?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:0,elementList:e.elementList,scaleMultiElement:e.scaleMultiElement},null,8,["elementList","scaleMultiElement"])):Object(h["createCommentVNode"])("",!0),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.elementList,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(u,{key:t.id,elementInfo:t,isSelected:e.activeElementIdList.includes(t.id),isActive:e.handleElementId===t.id,isActiveGroupElement:e.activeGroupElementId===t.id,isMultiSelect:e.activeElementIdList.length>1,rotateElement:e.rotateElement,scaleElement:e.scaleElement,dragLineElement:e.dragLineElement},null,8,["elementInfo","isSelected","isActive","isActiveGroupElement","isMultiSelect","rotateElement","scaleElement","dragLineElement"])})),128)),Object(h["createVNode"])(d)]),Object(h["createVNode"])("div",{class:"viewport",ref:"viewportRef",style:{transform:"scale(".concat(e.canvasScale,")")}},[e.mouseSelectionState.isShow?(Object(h["openBlock"])(),Object(h["createBlock"])(s,{key:0,top:e.mouseSelectionState.top,left:e.mouseSelectionState.left,width:e.mouseSelectionState.width,height:e.mouseSelectionState.height,quadrant:e.mouseSelectionState.quadrant},null,8,["top","left","width","height","quadrant"])):Object(h["createCommentVNode"])("",!0),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.elementList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(f,{key:t.id,elementInfo:t,elementIndex:n+1,isMultiSelect:e.activeElementIdList.length>1,selectElement:e.selectElement},null,8,["elementInfo","elementIndex","isMultiSelect","selectElement"])})),128))],4)],4)],544)),[[p,e.contextmenus],[b,e.removeEditorAreaFocus]])})),Et=function(){var e=window.getSelection();e&&e.removeAllRanges()},It=function(e){var t=Object(h["ref"])(0),n=Object(h["ref"])(0),o=X(),c=Object(h["computed"])((function(){return o.state.canvasPercentage})),a=function(){if(e.value){var a=e.value.clientWidth,r=e.value.clientHeight;if(r/a>Ie){var l=a*(c.value/100);o.commit(g.SET_CANVAS_SCALE,l/Ee),t.value=(a-l)/2,n.value=(r-l*Ie)/2}else{var i=r*(c.value/100);o.commit(g.SET_CANVAS_SCALE,i/(Ee*Ie)),t.value=(a-i/Ie)/2,n.value=(r-i)/2}}};Object(h["watch"])(c,a);var r=Object(h["computed"])((function(){return{width:Ee,height:Ee*Ie,left:t.value,top:n.value}})),l=new ResizeObserver(a);return Object(h["onMounted"])((function(){e.value&&l.observe(e.value)})),Object(h["onUnmounted"])((function(){e.value&&l.unobserve(e.value)})),{viewportStyles:r}},St=(n("a623"),n("4160"),n("159b"),function(e){var t=e.left,n=e.top,o=e.width,c=e.height,a=e.rotate,r=void 0===a?0:a,l=Math.sqrt(Math.pow(o,2)+Math.pow(c,2))/2,i=180*Math.atan(c/o)/Math.PI,u=(180-r-i)*Math.PI/180,d=(i-r)*Math.PI/180,s=o/2,f=c/2,p=t+s,b=n+f,m=[p+l*Math.cos(u),p+l*Math.cos(d),p-l*Math.cos(u),p-l*Math.cos(d)],v=[b-l*Math.sin(u),b-l*Math.sin(d),b+l*Math.sin(u),b+l*Math.sin(d)];return{xRange:[Math.min.apply(Math,m),Math.max.apply(Math,m)],yRange:[Math.min.apply(Math,v),Math.max.apply(Math,v)]}}),Ct=function(e){var t,n,o,c;if("line"===e.type)t=e.left,n=e.left+Math.max(e.start[0],e.end[0]),o=e.top,c=e.top+Math.max(e.start[1],e.end[1]);else if("rotate"in e&&e.rotate){var a=e.left,r=e.top,l=e.width,i=e.height,u=e.rotate,d=St({left:a,top:r,width:l,height:i,rotate:u}),s=d.xRange,f=d.yRange;t=s[0],n=s[1],o=f[0],c=f[1]}else t=e.left,n=e.left+e.width,o=e.top,c=e.top+e.height;return{minX:t,maxX:n,minY:o,maxY:c}},xt=function(e){var t=[],n=[],o=[],c=[];e.forEach((function(e){var a=Ct(e),r=a.minX,l=a.maxX,i=a.minY,u=a.maxY;t.push(r),n.push(i),o.push(l),c.push(u)}));var a=Math.min.apply(Math,t),r=Math.max.apply(Math,o),l=Math.min.apply(Math,n),i=Math.max.apply(Math,c);return{minX:a,maxX:r,minY:l,maxY:i}},Nt=function(e){var t=[];return e.forEach((function(e){var n=t.findIndex((function(t){return t.value===e.value}));if(-1===n)t.push(e);else{var o=t[n],c=Math.min(o.range[0],e.range[0]),a=Math.max(o.range[1],e.range[1]),r=[c,a],l={value:e.value,range:r};t[n]=l}})),t},Tt=function(e,t){var n=X(),o=Object(h["computed"])((function(){return n.state.canvasScale})),c=Object(h["reactive"])({isShow:!1,top:0,left:0,width:0,height:0,quadrant:1}),a=function(a){if(t.value){var r=!0,l=t.value.getBoundingClientRect(),i=5,u=a.pageX,d=a.pageY,s=(u-l.x)/o.value,f=(d-l.y)/o.value;c.isShow=!1,c.quadrant=4,c.top=f,c.left=s,c.width=0,c.height=0,document.onmousemove=function(e){if(r){var t=e.pageX,n=e.pageY,a=(t-u)/o.value,l=(n-d)/o.value,s=Math.abs(a),f=Math.abs(l);if(!(s0&&l>0?p=4:a<0&&l<0?p=1:a>0&&l<0?p=2:a<0&&l>0&&(p=3),c.isShow=!0,c.quadrant=p,c.width=s,c.height=f}}},document.onmouseup=function(){document.onmousemove=null,document.onmouseup=null,r=!1;for(var t=[],o=0;ol&&bi&&vl-u&&bi-d&&vl&&bi-d&&vl-u&&bi&&v0&&Math.abs(l-45)<=d?l-=l-45:l<0&&Math.abs(l+45)<=d?l-=l+45:l>0&&Math.abs(l-90)<=d?l-=l-90:l<0&&Math.abs(l+90)<=d?l-=l+90:l>0&&Math.abs(l-135)<=d?l-=l-135:l<0&&Math.abs(l+135)<=d?l-=l+135:l>0&&Math.abs(l-180)<=d?l-=l-180:l<0&&Math.abs(l+180)<=d&&(l-=l+180),e.value=e.value.map((function(e){return c.id===e.id?Object(P["a"])(Object(P["a"])({},e),{},{rotate:l}):e}))}},document.onmouseup=function(){r=!1,document.onmousemove=null,document.onmouseup=null,i!==l&&(n.commit(g.UPDATE_SLIDE,{elements:e.value}),a())}}};return{rotateElement:r}};(function(e){e["UP"]="up",e["DOWN"]="down",e["TOP"]="top",e["BOTTOM"]="bottom"})(Ot||(Ot={})),function(e){e["TOP"]="top",e["BOTTOM"]="bottom",e["LEFT"]="left",e["RIGHT"]="right",e["VERTICAL"]="vertical",e["HORIZONTAL"]="horizontal"}(ht||(ht={})),function(e){e["T"]="top",e["B"]="bottom",e["L"]="left",e["R"]="right"}(jt||(jt={})),function(e){e["LEFT_TOP"]="left-top",e["TOP"]="top",e["RIGHT_TOP"]="right-top",e["LEFT"]="left",e["RIGHT"]="right",e["LEFT_BOTTOM"]="left-bottom",e["BOTTOM"]="bottom",e["RIGHT_BOTTOM"]="right-bottom"}(gt||(gt={})),function(e){e["START"]="start",e["END"]="end,"}(yt||(yt={}));var _t,Bt=n("14b7");(function(e){e["UPDATE_TEXT_STATE"]="UPDATE_TEXT_STATE",e["EXEC_TEXT_COMMAND"]="EXEC_TEXT_COMMAND",e["UPDATE_TABLE_SELECTED_CELL"]="UPDATE_TABLE_SELECTED_CELL",e["SCALE_ELEMENT_STATE"]="SCALE_ELEMENT_STATE"})(_t||(_t={}));var Mt=Object(Bt["a"])(),Dt=Mt,At={text:"文本",image:"图片",shape:"形状",line:"线条",chart:"图表",table:"表格"},Pt={text:20,image:20,shape:15,chart:200,table:20},Rt=function(e,t){var n=e.left,o=e.top,c=e.width,a=e.height,r=Math.sqrt(Math.pow(c,2)+Math.pow(a,2))/2,l=180*Math.atan(a/c)/Math.PI,i=(180-t-l)*Math.PI/180,u=(l-t)*Math.PI/180,d=(90-t)*Math.PI/180,s=t*Math.PI/180,f=c/2,p=a/2,b=n+f,m=o+p,v={left:b+r*Math.cos(i),top:m-r*Math.sin(i)},O={left:b+p*Math.cos(d),top:m-p*Math.sin(d)},h={left:b+r*Math.cos(u),top:m-r*Math.sin(u)},j={left:b+f*Math.cos(s),top:m+f*Math.sin(s)},g={left:b-r*Math.cos(i),top:m+r*Math.sin(i)},y={left:b-p*Math.sin(s),top:m+p*Math.cos(s)},k={left:b-r*Math.cos(u),top:m+r*Math.sin(u)},E={left:b-f*Math.cos(s),top:m-f*Math.sin(s)};return{leftTopPoint:v,topPoint:O,rightTopPoint:h,rightPoint:j,rightBottomPoint:g,bottomPoint:y,leftBottomPoint:k,leftPoint:E}},Ft=function(e,t){var n,o=(n={},Object(C["a"])(n,gt.RIGHT_BOTTOM,t.leftTopPoint),Object(C["a"])(n,gt.LEFT_BOTTOM,t.rightTopPoint),Object(C["a"])(n,gt.LEFT_TOP,t.rightBottomPoint),Object(C["a"])(n,gt.RIGHT_TOP,t.leftBottomPoint),Object(C["a"])(n,gt.TOP,t.bottomPoint),Object(C["a"])(n,gt.BOTTOM,t.topPoint),Object(C["a"])(n,gt.LEFT,t.rightPoint),Object(C["a"])(n,gt.RIGHT,t.leftPoint),n);return o[e]},zt=function(e,t,n){var o=X(),c=Object(h["computed"])((function(){return o.state.activeElementIdList})),a=Object(h["computed"])((function(){return o.getters.ctrlOrShiftKeyActive})),r=Object(h["computed"])((function(){return o.state.canvasScale})),l=ge(),i=l.addHistorySnapshot,u=function(l,u,d){var s=!0;Dt.emit(_t.SCALE_ELEMENT_STATE,!0);var f,p=u.left,b=u.top,m=u.width,v=u.height,O=a.value||"fixedRatio"in u&&u.fixedRatio,h=m/v,j="rotate"in u&&u.rotate?u.rotate:0,y=Math.PI*j/180,k=l.pageX,E=l.pageY,I=Pt[u.type]||20,S=function(e){return e2&&void 0!==arguments[2])||arguments[2];if(r.value||o.commit(g.SET_EDITORAREA_FOCUS,!0),c.value.includes(u.id)){if(l.value){var s=[];if(u.groupId){var f=[];e.value.forEach((function(e){e.groupId===u.groupId&&f.push(e.id)})),s=c.value.filter((function(e){return!f.includes(e)}))}else s=c.value.filter((function(e){return e!==u.id}));s.length>0&&o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,s)}else if(a.value!==u.id)o.commit(g.SET_HANDLE_ELEMENT_ID,u.id);else if(t.value!==u.id){var p=i.pageX,b=i.pageY;i.target.onmouseup=function(e){var n=e.pageX,o=e.pageY;p===n&&b===o&&(t.value=u.id,e.target.onmouseup=null)}}}else{var m=[];if(m=l.value?[].concat(Object(A["a"])(c.value),[u.id]):[u.id],u.groupId){var v=[];e.value.forEach((function(e){e.groupId===u.groupId&&v.push(e.id)})),m=[].concat(Object(A["a"])(m),v)}o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,Ut()(m)),o.commit(g.SET_HANDLE_ELEMENT_ID,u.id)}d&&n(i,u)},u=function(){var t=e.value.filter((function(e){return!e.lock})),n=t.map((function(e){return e.id}));o.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,n)};return{selectElement:i,selectAllElement:u}},qt=function(e,t,n){var o=X(),c=Object(h["computed"])((function(){return o.state.activeElementIdList})),a=Object(h["computed"])((function(){return o.state.canvasScale})),r=ge(),l=r.addHistorySnapshot,i=function(r,i){if(c.value.includes(i.id)){var u,d=!0,s=Ee,f=Ee*Ie,p=JSON.parse(JSON.stringify(e.value)),b=p.filter((function(e){return c.value.includes(e.id)})),m=5,v=i.left,O=i.top,h=i.width,j="height"in i&&i.height?i.height:0,y="rotate"in i&&i.rotate?i.rotate:0,k=r.pageX,E=r.pageY,I=null,S=i.id===t.value,C=[],x=[],N=Object(me["a"])(e.value);try{for(N.s();!(u=N.n()).done;){var T=u.value;if("line"!==T.type&&((!S||T.id!==i.id)&&(S||!c.value.includes(T.id)))){var w=void 0,L=void 0,V=void 0,_=void 0;if("rotate"in T&&T.rotate){var B=St({left:T.left,top:T.top,width:T.width,height:T.height,rotate:T.rotate}),M=B.xRange,D=B.yRange;w=M[0],L=D[0],V=M[1]-M[0],_=D[1]-D[0]}else w=T.left,L=T.top,V=T.width,_=T.height;var R=w+V,F=L+_,z=L+_/2,H=w+V/2,U={value:L,range:[w,R]},G={value:F,range:[w,R]},q={value:z,range:[w,R]},W={value:w,range:[L,F]},X={value:R,range:[L,F]},Y={value:H,range:[L,F]};C.push(U,G,q),x.push(W,X,Y)}}}catch(te){N.e(te)}finally{N.f()}var Z={value:0,range:[0,s]},J={value:f,range:[0,s]},K={value:f/2,range:[0,s]},$={value:0,range:[0,f]},Q={value:s,range:[0,f]},ee={value:s/2,range:[0,f]};C.push(Z,J,K),x.push($,Q,ee),C=Nt(C),x=Nt(x),document.onmousemove=function(t){var o=t.pageX,r=t.pageY;if(!1!==I&&(I=Math.abs(k-o)v&&(V[0]=w-N,_[0]=0),m>O&&(V[1]=L-T,_[1]=0),e.value=e.value.map((function(e){return e.id===a.id?Object(P["a"])(Object(P["a"])({},e),{},{left:N,top:T,start:V,end:_}):e}))}},document.onmouseup=function(n){l=!1,document.onmousemove=null,document.onmouseup=null;var o=n.pageX,a=n.pageY;u===o&&d===a||(t.commit(g.UPDATE_SLIDE,{elements:e.value}),c())}};return{dragLineElement:a}},Xt=n("3835"),Yt=function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.creatingElement})),c=function(t){var o=t.start,c=t.end;if(e.value){var a=e.value.getBoundingClientRect(),r=Object(Xt["a"])(o,2),l=r[0],i=r[1],u=Object(Xt["a"])(c,2),d=u[0],s=u[1],f=Math.min(l,d),p=Math.max(l,d),b=Math.min(i,s),m=Math.max(i,s),v=(f-a.x)/n.value,O=(b-a.y)/n.value,h=(p-f)/n.value,j=(m-b)/n.value;return{left:v,top:O,width:h,height:j}}},a=function(t){var o=t.start,c=t.end;if(e.value){var a=e.value.getBoundingClientRect(),r=Object(Xt["a"])(o,2),l=r[0],i=r[1],u=Object(Xt["a"])(c,2),d=u[0],s=u[1],f=Math.min(l,d),p=Math.max(l,d),b=Math.min(i,s),m=Math.max(i,s),v=(f-a.x)/n.value,O=(b-a.y)/n.value,h=(p-f)/n.value,j=(m-b)/n.value,g=[l===f?0:h,i===b?0:j],y=[d===f?0:h,s===b?0:j];return{left:v,top:O,start:g,end:y}}},r=Se(),l=r.createTextElement,i=r.createShapeElement,u=r.createLineElement,d=function(e){if(o.value){var n=o.value.type;if("text"===n){var r=c(e);r&&l(r)}else if("shape"===n){var d=c(e);d&&i(d,o.value.data)}else if("line"===n){var s=a(e);s&&u(s,o.value.data)}t.commit(g.SET_CREATING_ELEMENT,null)}};return{insertElementFromCreateSelection:d}};function Zt(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"editable-element",ref:"elementRef",id:"editable-element-"+e.elementInfo.id,style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo,selectElement:e.selectElement,contextmenus:e.contextmenus},null,8,["elementInfo","selectElement","contextmenus"]))],12,["id"])}var Jt;n("a9e3");(function(e){e["TEXT"]="text",e["IMAGE"]="image",e["SHAPE"]="shape",e["LINE"]="line",e["CHART"]="chart",e["TABLE"]="table"})(Jt||(Jt={}));var Kt,$t,Qt=function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.currentSlide})),n=ge(),o=n.addHistorySnapshot,c=function(e,t){var n=e.findIndex((function(e){return e.id===t[0].id})),o=e.findIndex((function(e){return e.id===t[t.length-1].id}));return{minIndex:n,maxIndex:o}},a=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex,l=a.maxIndex;if(l===e.length-1)return null;var i=n[l+1],u=n.splice(r,o.length);if(i.groupId){var d=n.filter((function(e){return e.groupId===i.groupId}));n.splice.apply(n,[r+d.length,0].concat(Object(A["a"])(u)))}else n.splice.apply(n,[r+1,0].concat(Object(A["a"])(u)))}else{var s=e.findIndex((function(e){return e.id===t.id}));if(s===e.length-1)return null;var f=n[s+1],p=n.splice(s,1)[0];if(f.groupId){var b=n.filter((function(e){return e.groupId===f.groupId}));n.splice(s+b.length,0,p)}else n.splice(s+1,0,p)}return n},r=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex;if(0===r)return null;var l=n[r-1],i=n.splice(r,o.length);if(l.groupId){var u=n.filter((function(e){return e.groupId===l.groupId}));n.splice.apply(n,[r-u.length,0].concat(Object(A["a"])(i)))}else n.splice.apply(n,[r-1,0].concat(Object(A["a"])(i)))}else{var d=e.findIndex((function(e){return e.id===t.id}));if(0===d)return null;var s=n[d-1],f=n.splice(d,1)[0];if(s.groupId){var p=n.filter((function(e){return e.groupId===s.groupId}));n.splice(d-p.length,0,f)}else n.splice(d-1,0,f)}return n},l=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex,l=a.maxIndex;if(l===e.length-1)return null;var i=n.splice(r,o.length);n.push.apply(n,Object(A["a"])(i))}else{var u=e.findIndex((function(e){return e.id===t.id}));if(u===e.length-1)return null;n.splice(u,1),n.push(t)}return n},i=function(e,t){var n=JSON.parse(JSON.stringify(e));if(t.groupId){var o=n.filter((function(e){return e.groupId===t.groupId})),a=c(e,o),r=a.minIndex;if(0===r)return null;var l=n.splice(r,o.length);n.unshift.apply(n,Object(A["a"])(l))}else{var i=e.findIndex((function(e){return e.id===t.id}));if(0===i)return null;n.splice(i,1),n.unshift(t)}return n},u=function(n,c){var u=null;c===Ot.UP?u=a(t.value.elements,n):c===Ot.DOWN?u=r(t.value.elements,n):c===Ot.TOP?u=l(t.value.elements,n):c===Ot.BOTTOM&&(u=i(t.value.elements,n)),u&&(e.commit(g.UPDATE_SLIDE,{elements:u}),o())};return{orderElement:u}},en=function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.getters.activeElementList})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=function(c){var a,r=Ee,l=Ee*Ie,i=xt(n.value),u=i.minX,d=i.maxX,s=i.minY,f=i.maxY,p=JSON.parse(JSON.stringify(o.value.elements)),b=Object(me["a"])(p);try{for(b.s();!(a=b.n()).done;){var m=a.value;if(t.value.includes(m.id))if(c===ht.TOP){var v=s-0;m.top=m.top-v}else if(c===ht.VERTICAL){var O=s+(f-s)/2-l/2;m.top=m.top-O}else if(c===ht.BOTTOM){var h=f-l;m.top=m.top-h}else if(c===ht.LEFT){var j=u-0;m.left=m.left-j}else if(c===ht.HORIZONTAL){var y=u+(d-u)/2-r/2;m.left=m.left-y}else if(c===ht.RIGHT){var k=d-r;m.left=m.left-k}}}catch(E){b.e(E)}finally{b.f()}e.commit(g.UPDATE_SLIDE,{elements:p})};return{alignElementToCanvas:c}},tn=Object(h["withScopeId"])("data-v-c9d8ae3c"),nn=tn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ImageClipHandler"),l=Object(h["resolveComponent"])("ImageRectOutline"),i=Object(h["resolveComponent"])("ImageEllipseOutline"),u=Object(h["resolveComponent"])("ImagePolygonOutline"),d=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-image",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")},onMousedown:t[2]||(t[2]=function(t){return e.handleSelectElement(t)})},[e.isCliping?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,src:e.elementInfo.src,clipData:e.elementInfo.clip,width:e.elementInfo.width,height:e.elementInfo.height,top:e.elementInfo.top,left:e.elementInfo.left,clipPath:e.clipShape.style,onClip:t[1]||(t[1]=function(t){return e.clip(t)})},null,8,["src","clipData","width","height","top","left","clipPath"])):Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:1,class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):"",transform:e.flip}},["rect"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:0,width:e.elementInfo.width,height:e.elementInfo.height,radius:e.clipShape.radius,outline:e.elementInfo.outline},null,8,["width","height","radius","outline"])):"ellipse"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:1,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"])):"polygon"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(u,{key:2,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline,createPath:e.clipShape.createPath},null,8,["width","height","outline","createPath"])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"image-content",style:{clipPath:e.clipShape.style}},[Object(h["createVNode"])("img",{src:e.elementInfo.src,draggable:!1,style:{top:e.imgPosition.top,left:e.imgPosition.left,width:e.imgPosition.width,height:e.imgPosition.height,filter:e.filter},alt:""},null,12,["src"])],4)],4)),[[d,e.contextmenus]])],38)}));n("b64b");(function(e){e["RECT"]="rect",e["ELLIPSE"]="ellipse",e["POLYGON"]="polygon"})(Kt||(Kt={})),function(e){e["RECT"]="rect",e["ROUNDRECT"]="roundRect",e["ELLIPSE"]="ellipse",e["TRIANGLE"]="triangle",e["PENTAGON"]="pentagon",e["RHOMBUS"]="rhombus",e["STAR"]="star"}($t||($t={}));var on={rect:{name:"矩形",type:Kt.RECT,radius:"0",style:""},rect2:{name:"矩形2",type:Kt.POLYGON,style:"polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 0 100%)",createPath:function(e,t){return"M 0 0 L ".concat(.8*e," 0 L ").concat(e," ").concat(.2*t," L ").concat(e," ").concat(t," L 0 ").concat(t," Z")}},rect3:{name:"矩形3",type:Kt.POLYGON,style:"polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 20% 100%, 0% 80%)",createPath:function(e,t){return"M 0 0 L ".concat(.8*e," 0 L ").concat(e," ").concat(.2*t," L ").concat(e," ").concat(t," L ").concat(.2*e," ").concat(t," L 0 ").concat(.8*t," Z")}},roundRect:{name:"圆角矩形",type:Kt.RECT,radius:"10%",style:"inset(0 0 0 0 round 10% 10% 10% 10%)"},ellipse:{name:"圆形",type:Kt.ELLIPSE,style:"ellipse(50% 50% at 50% 50%)"},triangle:{name:"三角形",type:Kt.POLYGON,style:"polygon(50% 0%, 0% 100%, 100% 100%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L 0 ").concat(t," L ").concat(e," ").concat(t," Z")}},triangle2:{name:"三角形2",type:Kt.POLYGON,style:"polygon(50% 100%, 0% 0%, 100% 0%)",createPath:function(e,t){return"M ".concat(.5*e," ").concat(t," L 0 0 L ").concat(e," 0 Z")}},triangle3:{name:"三角形3",type:Kt.POLYGON,style:"polygon(0% 0%, 0% 100%, 100% 100%)",createPath:function(e,t){return"M 0 0 L 0 ".concat(t," L ").concat(e," ").concat(t," Z")}},rhombus:{name:"菱形",type:Kt.POLYGON,style:"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L ").concat(e," ").concat(.5*t," L ").concat(.5*e," ").concat(t," L 0 ").concat(.5*t," Z")}},hexagon:{name:"六边形",type:Kt.POLYGON,style:"polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)",createPath:function(e,t){return"M ".concat(.2*e," 0 L ").concat(.8*e," 0 L ").concat(e," ").concat(.5*t," L ").concat(.8*e," ").concat(t," L ").concat(.2*e," ").concat(t," L 0 ").concat(.5*t," Z")}},pentagon:{name:"五边形",type:Kt.POLYGON,style:"polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)",createPath:function(e,t){return"M ".concat(.5*e," 0 L ").concat(e," ").concat(.38*t," L ").concat(.82*e," ").concat(t," L ").concat(.18*e," ").concat(t," L 0 ").concat(.38*t," Z")}},parallelogram:{name:"平行四边形",type:Kt.POLYGON,style:"polygon(30% 0%, 100% 0%, 70% 100%, 0% 100%)",createPath:function(e,t){return"M ".concat(.3*e," 0 L ").concat(e," 0 L ").concat(.7*e," ").concat(t," L 0 ").concat(t," Z")}},parallelogram2:{name:"平行四边形2",type:Kt.POLYGON,style:"polygon(30% 100%, 100% 100%, 70% 0%, 0% 0%)",createPath:function(e,t){return"M ".concat(.3*e," ").concat(t," L ").concat(e," ").concat(t," L ").concat(.7*e," 0 L 0 0 Z")}},trapezoid:{name:"梯形",type:Kt.POLYGON,style:"polygon(25% 0%, 75% 0%, 100% 100%, 0% 100%)",createPath:function(e,t){return"M ".concat(.25*e," 0 L ").concat(.75*e," 0 L ").concat(e," ").concat(t," L 0 ").concat(t," Z")}},trapezoid2:{name:"梯形2",type:Kt.POLYGON,style:"polygon(0% 0%, 100% 0%, 75% 100%, 25% 100%)",createPath:function(e,t){return"M 0 0 L ".concat(e," 0 L ").concat(.75*e," ").concat(t," L ").concat(.25*e," ").concat(t," Z")}}},cn=function(e){var t=Object(h["ref"])("");return Object(h["watchEffect"])((function(){if(e.value){var n=e.value,o=n.h,c=n.v,a=n.blur,r=n.color;t.value="".concat(o,"px ").concat(c,"px ").concat(a,"px ").concat(r)}else t.value=""})),{shadowStyle:t}},an=Object(h["withScopeId"])("data-v-4efc595a"),rn=an((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-rect-outline",overflow:"visible",width:e.width,height:e.height},{default:an((function(){return[Object(h["createVNode"])("rect",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",rx:e.radius,ry:e.radius,width:e.width,height:e.height,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["rx","ry","width","height","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),ln=function(e){var t=Object(h["computed"])((function(){return e.value&&void 0!==e.value.width?e.value.width:0})),n=Object(h["computed"])((function(){return e.value&&void 0!==e.value.style?e.value.style:"solid"})),o=Object(h["computed"])((function(){return e.value&&void 0!==e.value.color?e.value.color:"#d14424"}));return{outlineWidth:t,outlineStyle:n,outlineColor:o}},un=Object(h["defineComponent"])({name:"image-rect-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object},radius:{type:String,default:"0"}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("b640");un.render=rn,un.__scopeId="data-v-4efc595a";var dn=un,sn=Object(h["withScopeId"])("data-v-4a286c0d"),fn=sn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-ellipse-outline",overflow:"visible",width:e.width,height:e.height},{default:sn((function(){return[Object(h["createVNode"])("ellipse",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",cx:e.width/2,cy:e.height/2,rx:e.width/2,ry:e.height/2,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["cx","cy","rx","ry","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),pn=Object(h["defineComponent"])({name:"image-ellipse-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("0741");pn.render=fn,pn.__scopeId="data-v-4a286c0d";var bn=pn,mn=Object(h["withScopeId"])("data-v-0a37b709"),vn=mn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"image-polygon-outline",overflow:"visible",width:e.width,height:e.height},{default:mn((function(){return[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",d:e.createPath(e.width,e.height),stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["d","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),On=Object(h["defineComponent"])({name:"image-polygon-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object},createPath:{type:Function,required:!0}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("b19e");On.render=vn,On.__scopeId="data-v-0a37b709";var hn=On,jn=Object(h["withScopeId"])("data-v-1e41275c");Object(h["pushScopeId"])("data-v-1e41275c");var gn=Object(h["createVNode"])("path",{"stroke-width":"0.3","shape-rendering":"crispEdges",d:"M 16 0 L 0 0 L 0 16 L 4 16 L 4 4 L 16 4 L 16 0 Z"},null,-1);Object(h["popScopeId"])();var yn=jn((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper"),l=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"image-clip-handler",style:e.clipWrapperPositionStyle},[Object(h["createVNode"])("img",{class:"bottom-img",src:e.src,draggable:!1,alt:"",style:e.bottomImgPositionStyle},null,12,["src"]),Object(h["createVNode"])("div",{class:"top-image-content",style:Object(P["a"])(Object(P["a"])({},e.topImgWrapperPositionStyle),{},{clipPath:e.clipPath})},[Object(h["createVNode"])("img",{class:"top-img",src:e.src,draggable:!1,alt:"",style:e.topImgPositionStyle},null,12,["src"])],4),Object(h["createVNode"])("div",{class:"operate",style:e.topImgWrapperPositionStyle,onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.moveClipRange(t)}),["stop"]))},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(["t-l","t-r","b-l","b-r"],(function(t){return Object(h["createVNode"])("div",{class:["clip-point",t],key:t,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleClipRange(n,t)}),["stop"])},[Object(h["createVNode"])(r,{width:"12",height:"12",fill:"#fff",stroke:"#333"},{default:jn((function(){return[gn]})),_:1})],42,["onMousedown"])})),64))],36)],4)),[[l,e.handleClip]])})),kn=Object(h["defineComponent"])({name:"image-clip-handler",props:{src:{type:String,required:!0},clipData:{type:Object},clipPath:{type:String,required:!0},width:{type:Number,required:!0},height:{type:Number,required:!0},top:{type:Number,required:!0},left:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.state.canvasScale})),a=Object(h["reactive"])({top:0,left:0,width:0,height:0}),r=Object(h["reactive"])({top:"0",left:"0"}),l=Object(h["ref"])(!1),i=Object(h["ref"])(null),u=function(){var t=e.clipData?e.clipData.range:[[0,0],[100,100]],n=Object(Xt["a"])(t,2),o=n[0],c=n[1],a=(c[0]-o[0])/100,r=(c[1]-o[1])/100,l=o[0]/a,i=o[1]/r;return{widthScale:a,heightScale:r,left:l,top:i}},d=Object(h["computed"])((function(){var e=u(),t=e.widthScale,n=e.heightScale,o=e.left,c=e.top;return{left:-o,top:-c,width:100/t,height:100/n}})),s=Object(h["computed"])((function(){return{top:d.value.top+"%",left:d.value.left+"%",width:d.value.width+"%",height:d.value.height+"%"}})),f=Object(h["computed"])((function(){return{top:a.top+"%",left:a.left+"%",width:a.width+"%",height:a.height+"%"}})),p=Object(h["computed"])((function(){var e=d.value.width,t=d.value.height,n=a.left,o=a.top,c=a.width,r=a.height;return{left:100/c*-n+"%",top:100/r*-o+"%",width:e/c*100+"%",height:t/r*100+"%"}})),b=function(){var e=u(),t=e.left,n=e.top;a.left=t,a.top=n,a.width=100,a.height=100,r.top=-n+"%",r.left=-t+"%"},m=function(){if(!l.value)if(i.value){var t=u(),o=t.left,c=t.top,r={left:(a.left-o)/100*e.width,top:(a.top-c)/100*e.height,width:(a.width-100)/100*e.width,height:(a.height-100)/100*e.height},d={range:i.value,position:r};n("clip",d)}else n("clip",null)},v=function(e){var t=e.key.toUpperCase();t===$.ENTER&&m()};Object(h["onMounted"])((function(){b(),document.addEventListener("keydown",v)})),Object(h["onUnmounted"])((function(){document.removeEventListener("keydown",v)}));var O=function(){var e={left:parseInt(p.value.left),top:parseInt(p.value.top),width:parseInt(p.value.width),height:parseInt(p.value.height)},t=100/e.width,n=100/e.height,o=[-e.left*t,-e.top*n],c=[100*t+o[0],100*n+o[1]];i.value=[o,c]},j=function(t){l.value=!0;var n=!0,o=t.pageX,r=t.pageY,i=d.value,u={left:a.left,top:a.top,width:a.width,height:a.height};document.onmousemove=function(t){if(n){var l=t.pageX,d=t.pageY,s=(l-o)/c.value/e.width*100,f=(d-r)/c.value/e.height*100,p=u.left+s,b=u.top+f;p<0?p=0:p+u.width>i.width&&(p=i.width-u.width),b<0?b=0:b+u.height>i.height&&(b=i.height-u.height),a.left=p,a.top=b}},document.onmouseup=function(){n=!1,document.onmousemove=null,document.onmouseup=null,O(),setTimeout((function(){l.value=!1}),0)}},g=function(t,n){l.value=!0;var o=!0,r=50/e.width*100,i=50/e.height*100,u=t.pageX,s=t.pageY,f=d.value,p={left:a.left,top:a.top,width:a.width,height:a.height};document.onmousemove=function(t){if(o){var l,d,b,m,v=t.pageX,O=t.pageY,h=(v-u)/c.value/e.width*100,j=(O-s)/c.value/e.height*100;"t-l"===n?(p.left+h<0&&(h=-p.left),p.top+j<0&&(j=-p.top),p.width-hf.width&&(h=f.width-(p.left+p.width)),p.top+j<0&&(j=-p.top),p.width+hf.height&&(j=f.height-(p.top+p.height)),p.width-hf.width&&(h=f.width-(p.left+p.width)),p.top+p.height+j>f.height&&(j=f.height-(p.top+p.height)),p.width+h\s$/,e)},Fn=function(e){return Object(An["g"])(/^(\d+)\.\s$/,e,(function(e){return{order:+e[1]}}),(function(e,t){return t.childCount+t.attrs.order===+e[1]}))},zn=function(e){return Object(An["g"])(/^\s*([-+*])\s$/,e)},Hn=function(e){return Object(An["e"])(/^```$/,e)},Un=function(e){var t=[].concat(Object(A["a"])(An["d"]),[An["a"],An["b"]]);return t.push(Rn(e.nodes.blockquote)),t.push(Fn(e.nodes.ordered_list)),t.push(zn(e.nodes.bullet_list)),t.push(Hn(e.nodes.code_block)),Object(An["c"])({rules:t})},Gn=function(e){return[Un(e),Object(Vn["b"])(Pn(e)),Object(Vn["b"])(Nn["a"]),Object(Bn["a"])(),Object(Mn["a"])(),Object(_n["a"])()]},qn=n("2210"),Wn=Object(P["a"])(Object(P["a"])({},Dn["d"]),{},{content:"list_item+",group:"block"}),Xn=Object(P["a"])(Object(P["a"])({},Dn["a"]),{},{content:"list_item+",group:"block"}),Yn=Object(P["a"])(Object(P["a"])({},Dn["c"]),{},{content:"paragraph block*",group:"block"}),Zn={attrs:{align:{default:""}},content:"inline*",group:"block",parseDOM:[{tag:"p",getAttrs:function(e){var t=e.style.textAlign,n=e.getAttribute("align")||t||"";return n=/(left|right|center|justify)/.test(n)?n:"",{align:n}}}],toDOM:function(e){var t=e.attrs.align,n="";return t&&"left"!==t&&(n+="text-align: ".concat(t,";")),["p",{style:n},0]}},Jn=Object(P["a"])(Object(P["a"])({},qn["b"]),{},{ordered_list:Wn,bullet_list:Xn,list_item:Yn,paragraph:Zn}),Kn=(n("ac1f"),n("5319"),{excludes:"subscript",parseDOM:[{tag:"sub"},{style:"vertical-align",getAttrs:function(e){return"sub"===e&&null}}],toDOM:function(){return["sub",0]}}),$n={excludes:"superscript",parseDOM:[{tag:"sup"},{style:"vertical-align",getAttrs:function(e){return"super"===e&&null}}],toDOM:function(){return["sup",0]}},Qn={parseDOM:[{tag:"strike"},{style:"text-decoration",getAttrs:function(e){return"line-through"===e&&null}},{style:"text-decoration-line",getAttrs:function(e){return"line-through"===e&&null}}],toDOM:function(){return["span",{style:"text-decoration-line: line-through"},0]}},eo={parseDOM:[{tag:"u"},{style:"text-decoration",getAttrs:function(e){return"underline"===e&&null}},{style:"text-decoration-line",getAttrs:function(e){return"underline"===e&&null}}],toDOM:function(){return["span",{style:"text-decoration: underline"},0]}},to={attrs:{color:{}},parseDOM:[{style:"color",getAttrs:function(e){return e?{color:e}:{}}}],toDOM:function(e){var t=e.attrs.color,n="";return t&&(n+="color: ".concat(t,";")),["span",{style:n},0]}},no={attrs:{backcolor:{}},inline:!0,group:"inline",parseDOM:[{tag:"span[style*=background-color]",getAttrs:function(e){return e?{backcolor:e}:{}}}],toDOM:function(e){var t=e.attrs.backcolor,n="";return t&&(n+="background-color: ".concat(t,";")),["span",{style:n},0]}},oo={attrs:{fontsize:{}},inline:!0,group:"inline",parseDOM:[{style:"font-size",getAttrs:function(e){return e?{fontsize:e}:{}}}],toDOM:function(e){var t=e.attrs.fontsize,n="";return t&&(n+="font-size: ".concat(t)),["span",{style:n},0]}},co={attrs:{fontname:{}},inline:!0,group:"inline",parseDOM:[{style:"font-family",getAttrs:function(e){return{fontname:e&&"string"===typeof e?e.replace(/[\"\']/g,""):""}}}],toDOM:function(e){var t=e.attrs.fontname,n="";return t&&(n+="font-family: ".concat(t)),["span",{style:n},0]}},ao=Object(P["a"])(Object(P["a"])({},qn["a"]),{},{subscript:Kn,superscript:$n,strikethrough:Qn,underline:eo,forecolor:to,backcolor:no,fontsize:oo,fontname:co}),ro=Jn,lo=ao,io=new Ln["i"]({nodes:ro,marks:lo}),uo=function(e){var t="
".concat(e,"
"),n=new window.DOMParser,o=n.parseFromString(t,"text/html").body.firstElementChild;return Ln["a"].fromSchema(io).parse(o)},so=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return new wn["c"](e,Object(P["a"])({state:Tn["b"].create({doc:uo(t),plugins:Gn(io)})},n))},fo=(n("b0c0"),function(e,t){return Array.isArray(e)&&e.indexOf(t.type)>-1||t.type===e}),po=function(e,t){for(var n=e.depth;n>0;n--){var o=e.node(n);if(t(o))return{pos:n>0?e.before(n):0,start:e.start(n),depth:n,node:o}}},bo=function(e){return function(t){return po(t.$from,e)}},mo=function(e){return function(t){return bo((function(t){return fo(e,t)}))(t)}},vo=function(e,t){var n=t.schema.nodes[e];return!!mo(n)(t.selection)},Oo=function(e){var t=e.state,n=t.selection,o=t.doc,c=n.from,a=o.nodeAt(c);return(null===a||void 0===a?void 0:a.marks)||[]},ho=function(e,t,n){var o,c=Oo(e),a=Object(me["a"])(c);try{for(a.s();!(o=a.n()).done;){var r=o.value;if(r.type.name===t&&r.attrs[n])return r.attrs[n]}}catch(l){a.e(l)}finally{a.f()}return null},jo=function(e,t){var n,o=Oo(e),c=Object(me["a"])(o);try{for(c.s();!(n=c.n()).done;){var a=n.value;if(a.type.name===t)return!0}}catch(r){c.e(r)}finally{c.f()}return!1},go=function(e,t){var n=e.state,o=n.selection,c=n.doc,a=o.from,r=o.to,l=!0,i="";return c.nodesBetween(a,r,(function(e){return l&&e.attrs[t]&&(l=!1,i=e.attrs[t]),l})),i},yo=function(e){var t=jo(e,"strong"),n=jo(e,"em"),o=jo(e,"underline"),c=jo(e,"strikethrough"),a=jo(e,"superscript"),r=jo(e,"subscript"),l=jo(e,"code"),i=ho(e,"forecolor","color")||"#000",u=ho(e,"backcolor","backcolor")||"#000",d=ho(e,"fontsize","fontsize")||"12px",s=ho(e,"fontname","fontname")||"微软雅黑",f=go(e,"align")||"left",p=vo("bullet_list",e.state),b=vo("ordered_list",e.state),m=vo("blockquote",e.state);return{bold:t,em:n,underline:o,strikethrough:c,superscript:a,subscript:r,code:l,color:i,backcolor:u,fontsize:d,fontname:s,align:f,bulletList:p,orderedList:b,blockquote:m}},ko=(n("6062"),n("3ca3"),function(e,t,n){var o=e,c=o.selection,a=o.doc;if(!c||!a)return e;var r=c.from,l=c.to,i=t.nodes,u=i.blockquote,d=i.list_item,s=i.paragraph,f=[];n=n||"";var p=new Set([u,d,s]);return a.nodesBetween(r,l,(function(e,t){var o=e.type,c=e.attrs.align||"";return c!==n&&p.has(o)&&f.push({node:e,pos:t,nodeType:o}),!0})),f.length?(f.forEach((function(t){var o=t.node,c=t.pos,a=t.nodeType,r=o.attrs;r=n?Object(P["a"])(Object(P["a"])({},r),{},{align:n}):Object(P["a"])(Object(P["a"])({},r),{},{align:null}),e=e.setNodeMarkup(c,a,r,o.marks)})),e):e}),Eo=function(e,t){var n=e.state,o=n.schema,c=n.selection,a=ko(n.tr.setSelection(c),o,t);e.dispatch(a)},Io=function(e,t){return e.type===t.nodes.bullet_list||e.type===t.nodes.ordered_list},So=function(e,t){return function(n,o){var c=n.schema,a=n.selection,r=a.$from,l=a.$to,i=r.blockRange(l);if(!i)return!1;var u=bo((function(e){return Io(e,c)}))(a);if(i.depth>=1&&u&&i.depth-u.depth<=1){if(u.node.type===e)return Object(Dn["b"])(t)(n,o);if(Io(u.node,c)&&e.validContent(u.node.content)){var d=n.tr;return d.setNodeMarkup(u.pos,e),o&&o(d),!1}}return Object(Dn["g"])(e)(n,o)}},Co=Object(h["withScopeId"])("data-v-59365834"),xo=Co((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return e.outline?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"element-outline",overflow:"visible",width:e.width,height:e.height},{default:Co((function(){return[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",d:"M0,0 L".concat(e.width,",0 L").concat(e.width,",").concat(e.height," L0,").concat(e.height," Z"),stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"12 9":"0 0"},null,8,["d","stroke","stroke-width","stroke-dasharray"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)})),No=Object(h["defineComponent"])({name:"element-outline",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},outline:{type:Object}},setup:function(e){var t=ln(Object(h["toRef"])(e,"outline")),n=t.outlineWidth,o=t.outlineStyle,c=t.outlineColor;return{outlineWidth:n,outlineStyle:o,outlineColor:c}}});n("606f");No.render=xo,No.__scopeId="data-v-59365834";var To=No,wo=Object(h["defineComponent"])({name:"editable-element-text",components:{ElementOutline:To},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=X(),n=ge(),o=n.addHistorySnapshot,c=Object(h["ref"])(),a=Object(h["ref"])(!1),r=Object(h["ref"])(-1),l=function(n){a.value=n,n||-1===r.value||(t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:r.value}}),r.value=-1)};Dt.on(_t.SCALE_ELEMENT_STATE,(function(e){return l(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.SCALE_ELEMENT_STATE,(function(e){return l(e)}))}));var i=function(n){var o=n[0].contentRect;if(c.value){var l=o.height;e.elementInfo.height!==l&&(a.value?r.value=l:t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:l}}))}},u=new ResizeObserver(i);Object(h["onMounted"])((function(){c.value&&u.observe(c.value)})),Object(h["onUnmounted"])((function(){c.value&&u.unobserve(c.value)}));var d,s=Object(h["ref"])(),f=function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,!0)},p=function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,!1)},b=Oe()((function(){t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{content:d.dom.innerHTML}}),o()}),300,{trailing:!0}),m=Oe()((function(){var e=yo(d);Dt.emit(_t.UPDATE_TEXT_STATE,e)}),30,{trailing:!0}),v=function(){b(),m()},O=Object(h["computed"])((function(){return e.elementInfo.content}));Object(h["watch"])(O,(function(){d&&(d.hasFocus()||(d.dom.innerHTML=O.value))}));var j=Object(h["computed"])((function(){return!e.elementInfo.lock}));Object(h["watch"])(j,(function(){d.setProps({editable:function(){return j.value}})})),Object(h["onMounted"])((function(){d=so(s.value,O.value,{handleDOMEvents:{focus:f,blur:p,keydown:v,click:m},editable:function(){return j.value}})})),Object(h["onUnmounted"])((function(){d&&d.destroy()}));var y=function(t){var n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo,n))},k=Object(h["computed"])((function(){return e.elementInfo.shadow})),E=cn(k),I=E.shadowStyle,S=Object(h["computed"])((function(){return t.state.handleElementId})),C=function(t){if(S.value===e.elementInfo.id){var n,o="command"in t?[t]:t,c=Object(me["a"])(o);try{for(c.s();!(n=c.n()).done;){var a=n.value;if("fontname"===a.command&&a.value){var r=d.state.schema.marks.fontname.create({fontname:a.value}),l=d.state.selection.empty;l&&Object(Nn["d"])(d.state,d.dispatch);var i=d.state.selection,u=i.$from,s=i.$to;d.dispatch(d.state.tr.addMark(u.pos,s.pos,r))}else if("fontsize"===a.command&&a.value){var f=d.state.schema.marks.fontsize.create({fontsize:a.value}),p=d.state.selection.empty;p&&Object(Nn["d"])(d.state,d.dispatch);var v=d.state.selection,O=v.$from,h=v.$to;d.dispatch(d.state.tr.addMark(O.pos,h.pos,f))}else if("color"===a.command&&a.value){var j=d.state.schema.marks.forecolor.create({color:a.value}),g=d.state.selection.empty;g&&Object(Nn["d"])(d.state,d.dispatch);var y=d.state.selection,k=y.$from,E=y.$to;d.dispatch(d.state.tr.addMark(k.pos,E.pos,j))}else if("backcolor"===a.command&&a.value){var I=d.state.schema.marks.backcolor.create({backcolor:a.value}),C=d.state.selection.empty;C&&Object(Nn["d"])(d.state,d.dispatch);var x=d.state.selection,N=x.$from,T=x.$to;d.dispatch(d.state.tr.addMark(N.pos,T.pos,I))}else if("bold"===a.command){var w=d.state.selection.empty;w&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.strong)(d.state,d.dispatch)}else if("em"===a.command){var L=d.state.selection.empty;L&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.em)(d.state,d.dispatch)}else if("underline"===a.command){var V=d.state.selection.empty;V&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.underline)(d.state,d.dispatch)}else if("strikethrough"===a.command){var _=d.state.selection.empty;_&&Object(Nn["d"])(d.state,d.dispatch),Object(Nn["f"])(d.state.schema.marks.strikethrough)(d.state,d.dispatch)}else if("subscript"===a.command)Object(Nn["f"])(d.state.schema.marks.subscript)(d.state,d.dispatch);else if("superscript"===a.command)Object(Nn["f"])(d.state.schema.marks.superscript)(d.state,d.dispatch);else if("blockquote"===a.command)Object(Nn["g"])(d.state.schema.nodes.blockquote)(d.state,d.dispatch);else if("code"===a.command)Object(Nn["f"])(d.state.schema.marks.code)(d.state,d.dispatch);else if("align"===a.command&&a.value)Eo(d,a.value);else if("bulletList"===a.command){var B=d.state.schema.nodes,M=B.bullet_list,D=B.list_item;So(M,D)(d.state,d.dispatch)}else if("orderedList"===a.command){var A=d.state.schema.nodes,P=A.ordered_list,R=A.list_item;So(P,R)(d.state,d.dispatch)}else if("clear"===a.command){var F=d.state.selection.empty;F&&Object(Nn["d"])(d.state,d.dispatch);var z=d.state.selection,H=z.$from,U=z.$to;d.dispatch(d.state.tr.removeMark(H.pos,U.pos))}}}catch(G){c.e(G)}finally{c.f()}d.focus(),b(),m()}};return Dt.on(_t.EXEC_TEXT_COMMAND,(function(e){return C(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.EXEC_TEXT_COMMAND,(function(e){return C(e)}))})),{elementRef:c,editorViewRef:s,handleSelectElement:y,shadowStyle:I}}});n("01f7");wo.render=xn,wo.__scopeId="data-v-092f3d4e";var Lo=wo,Vo=Object(h["withScopeId"])("data-v-6a9228f2");Object(h["pushScopeId"])("data-v-6a9228f2");var _o={key:0};Object(h["popScopeId"])();var Bo=Vo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("GradientDefs"),l=Object(h["resolveComponent"])("SvgWrapper"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-shape",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")},onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"element-content",style:{opacity:e.elementInfo.opacity,filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):""}},[Object(h["createVNode"])(l,{overflow:"visible",width:e.elementInfo.width,height:e.elementInfo.height},{default:Vo((function(){return[e.elementInfo.gradient?(Object(h["openBlock"])(),Object(h["createBlock"])("defs",_o,[Object(h["createVNode"])(r,{id:"editabel-gradient-".concat(e.elementInfo.id),type:e.elementInfo.gradient.type,color1:e.elementInfo.gradient.color[0],color2:e.elementInfo.gradient.color[1],rotate:e.elementInfo.gradient.rotate},null,8,["id","type","color1","color2","rotate"])])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("g",{transform:"scale(".concat(e.elementInfo.width/e.elementInfo.viewBox,", ").concat(e.elementInfo.height/e.elementInfo.viewBox,") translate(0,0) matrix(1,0,0,1,0,0)")},[Object(h["createVNode"])("path",{"vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",d:e.elementInfo.path,fill:e.elementInfo.gradient?"url(#editabel-gradient-".concat(e.elementInfo.id,")"):e.elementInfo.fill,stroke:e.outlineColor,"stroke-width":e.outlineWidth,"stroke-dasharray":"dashed"===e.outlineStyle?"10 5":"0 0"},null,8,["d","fill","stroke","stroke-width","stroke-dasharray"])],8,["transform"])]})),_:1},8,["width","height"])],4),[[i,e.contextmenus]])],38)}));function Mo(e,t,n,o,c,a){return"linear"===e.type?(Object(h["openBlock"])(),Object(h["createBlock"])("linearGradient",{key:0,id:e.id,x1:"0%",y1:"0%",x2:"100%",y2:"0%",gradientTransform:"rotate(".concat(e.rotate,",0.5,0.5)")},[Object(h["createVNode"])("stop",{offset:"0%","stop-color":e.color1},null,8,["stop-color"]),Object(h["createVNode"])("stop",{offset:"100%","stop-color":e.color2},null,8,["stop-color"])],8,["id","gradientTransform"])):(Object(h["openBlock"])(),Object(h["createBlock"])("radialGradient",{key:1,id:e.id},[Object(h["createVNode"])("stop",{offset:"0%","stop-color":e.color1},null,8,["stop-color"]),Object(h["createVNode"])("stop",{offset:"100%","stop-color":e.color2},null,8,["stop-color"])],8,["id"]))}var Do=Object(h["defineComponent"])({name:"gradient-defs",props:{id:{type:String,required:!0},type:{type:String},color1:{type:String,required:!0},color2:{type:String,required:!0},rotate:{type:Number,default:0}}});Do.render=Mo;var Ao=Do,Po=Object(h["defineComponent"])({name:"editable-element-shape",components:{GradientDefs:Ao},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},n=Object(h["computed"])((function(){return e.elementInfo.outline})),o=ln(n),c=o.outlineWidth,a=o.outlineStyle,r=o.outlineColor,l=Object(h["computed"])((function(){return e.elementInfo.shadow})),i=cn(l),u=i.shadowStyle;return{handleSelectElement:t,shadowStyle:u,outlineWidth:c,outlineStyle:a,outlineColor:r}}});n("2a31");Po.render=Bo,Po.__scopeId="data-v-6a9228f2";var Ro=Po,Fo=Object(h["withScopeId"])("data-v-d93ab0c4"),zo=Fo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("LinePointMarker"),l=Object(h["resolveComponent"])("SvgWrapper"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-shape",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px"}},[Object(h["createVNode"])("div",{class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):""}},[Object(h["createVNode"])(l,{overflow:"visible",width:e.svgWidth,height:e.svgHeight},{default:Fo((function(){return[Object(h["createVNode"])("defs",null,[e.elementInfo.points[0]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,id:e.elementInfo.id,position:"start",type:e.elementInfo.points[0],color:e.elementInfo.color,baseSize:e.elementInfo.width},null,8,["id","type","color","baseSize"])):Object(h["createCommentVNode"])("",!0),e.elementInfo.points[1]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,id:e.elementInfo.id,position:"end",type:e.elementInfo.points[1],color:e.elementInfo.color,baseSize:e.elementInfo.width},null,8,["id","type","color","baseSize"])):Object(h["createCommentVNode"])("",!0)]),Object(h["createVNode"])("path",{d:e.path,stroke:e.elementInfo.color,"stroke-width":e.elementInfo.width,"stroke-dasharray":e.lineDashArray,fill:"none","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":"","marker-start":e.elementInfo.points[0]?"url(#".concat(e.elementInfo.id,"-").concat(e.elementInfo.points[0],"-start)"):"","marker-end":e.elementInfo.points[1]?"url(#".concat(e.elementInfo.id,"-").concat(e.elementInfo.points[1],"-end)"):""},null,8,["d","stroke","stroke-width","stroke-dasharray","marker-start","marker-end"]),Object(h["withDirectives"])(Object(h["createVNode"])("path",{class:"line-path",d:e.path,stroke:"transparent","stroke-width":"20",fill:"none",onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},null,40,["d"]),[[i,e.contextmenus]])]})),_:1},8,["width","height"])],4)],6)}));function Ho(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("marker",{id:"".concat(e.id,"-").concat(e.type,"-").concat(e.position),markerUnits:"userSpaceOnUse",orient:"auto",markerWidth:3*e.size,markerHeight:3*e.size,refX:1.5*e.size,refY:1.5*e.size},[Object(h["createVNode"])("path",{d:e.path,fill:e.color,transform:"scale(".concat(.3*e.size,", ").concat(.3*e.size,") rotate(").concat(e.rotate,", 5, 5)")},null,8,["d","fill","transform"])],8,["id","markerWidth","markerHeight","refX","refY"])}var Uo={dot:"m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",arrow:"M0,0 L10,5 0,10 Z"},Go={"arrow-start":180,"arrow-end":0},qo=Object(h["defineComponent"])({name:"line-point-marker",props:{id:{type:String,required:!0},position:{type:String,required:!0},type:{type:String,required:!0},color:{type:String},baseSize:{type:Number,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){return Uo[e.type]})),n=Object(h["computed"])((function(){return Go["".concat(e.type,"-").concat(e.position)]||0})),o=Object(h["computed"])((function(){return e.baseSize<2?2:e.baseSize}));return{path:t,rotate:n,size:o}}});qo.render=Ho;var Wo=qo,Xo=Object(h["defineComponent"])({name:"editable-element-shape",components:{LinePointMarker:Wo},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},n=Object(h["computed"])((function(){return e.elementInfo.shadow})),o=cn(n),c=o.shadowStyle,a=Object(h["computed"])((function(){var t=Math.abs(e.elementInfo.start[0]-e.elementInfo.end[0]);return t<24?24:t})),r=Object(h["computed"])((function(){var t=Math.abs(e.elementInfo.start[1]-e.elementInfo.end[1]);return t<24?24:t})),l=Object(h["computed"])((function(){return"dashed"===e.elementInfo.style?"10, 5":"0, 0"})),i=Object(h["computed"])((function(){var t=e.elementInfo.start.join(","),n=e.elementInfo.end.join(",");return"M".concat(t," L").concat(n)}));return{handleSelectElement:t,shadowStyle:c,svgWidth:a,svgHeight:r,lineDashArray:l,path:i}}});n("1c60");Xo.render=zo,Xo.__scopeId="data-v-d93ab0c4";var Yo=Xo,Zo=Object(h["withScopeId"])("data-v-7550799e"),Jo=Zo((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementOutline"),l=Object(h["resolveComponent"])("Chart"),i=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-chart",{lock:e.elementInfo.lock}],style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px"},onMousedown:t[1]||(t[1]=function(t){return e.handleSelectElement(t)})},[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"element-content",style:{backgroundColor:e.elementInfo.fill}},[Object(h["createVNode"])(r,{width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"]),Object(h["createVNode"])(l,{width:e.elementInfo.width,height:e.elementInfo.height,type:e.elementInfo.chartType,data:e.elementInfo.data,options:e.elementInfo.options,themeColor:e.elementInfo.themeColor,gridColor:e.elementInfo.gridColor},null,8,["width","height","type","data","options","themeColor","gridColor"])],4),[[i,e.contextmenus]])],38)})),Ko=Object(h["withScopeId"])("data-v-5f401eca");Object(h["pushScopeId"])("data-v-5f401eca");var $o={class:"chart"};Object(h["popScopeId"])();var Qo=Ko((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",$o,[Object(h["createVNode"])("div",{class:"chart-content",ref:"chartRef",style:{width:e.width+"px",height:e.height+"px",transform:"scale(".concat(1/e.slideScale,")")}},null,4)])})),ec=n("8103"),tc=n.n(ec),nc=n("66cb"),oc=n.n(nc),cc=n("ba48"),ac=n.n(cc),rc=(n("aa97"),Object(h["defineComponent"])({name:"chart",props:{width:{type:Number,required:!0},height:{type:Number,required:!0},type:{type:String,required:!0},data:{type:Object,required:!0},options:{type:Object},themeColor:{type:String,required:!0},gridColor:{type:String}},setup:function(e){var t,n=Object(h["ref"])(),o=Object(h["inject"])("slideScale")||Object(h["ref"])(1),c=function(){var t=e.options||{},n=Object(P["a"])(Object(P["a"])({},t),{},{width:e.width*o.value,height:e.height*o.value}),c="pie"===e.type?Object(P["a"])(Object(P["a"])({},e.data),{},{series:e.data.series[0]}):e.data;return{data:c,options:n}},a=function(){if(n.value){var o=tc()(e.type),a=c(),r=a.data,l=a.options;t=new ac.a[o](n.value,r,l)}},r=function(){if(t){var e=c(),n=e.data,o=e.options;t.update(n,o)}else a()};Object(h["watch"])([function(){return e.width},function(){return e.height},function(){return e.data},o],r),Object(h["onMounted"])(a);var l=function(){if(n.value){for(var t=oc()(e.themeColor).toHsl(),o=0;o<10;o++){var c=t.h+36*o;c>360&&(c-=360);var a=Object(P["a"])(Object(P["a"])({},t),{},{h:c});n.value.style.setProperty("--theme-color-".concat(o+1),oc()(a).toRgbString())}e.gridColor&&n.value.style.setProperty("--grid-color",e.gridColor)}};return Object(h["watch"])([function(){return e.themeColor},function(){return e.gridColor}],l),Object(h["onMounted"])(l),{slideScale:o,chartRef:n}}}));n("380f8"),n("d85b");rc.render=Qo,rc.__scopeId="data-v-5f401eca";var lc=rc,ic=Object(h["defineComponent"])({name:"editable-element-chart",components:{ElementOutline:To,Chart:lc},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))};return{handleSelectElement:t}}});n("fba1");ic.render=Jo,ic.__scopeId="data-v-7550799e";var uc=ic,dc=Object(h["withScopeId"])("data-v-045f7664");Object(h["pushScopeId"])("data-v-045f7664");var sc={class:"element-content"};Object(h["popScopeId"])();var fc=dc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("EditableTable"),l=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["editable-element-table",{lock:e.elementInfo.lock}],ref:"elementRef",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px"}},[Object(h["withDirectives"])(Object(h["createVNode"])("div",sc,[Object(h["createVNode"])(r,{onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(){}),["stop"])),data:e.elementInfo.data,width:e.elementInfo.width,colWidths:e.elementInfo.colWidths,outline:e.elementInfo.outline,theme:e.elementInfo.theme,editable:e.editable,onChange:t[2]||(t[2]=function(t){return e.updateTableCells(t)}),onChangeColWidths:t[3]||(t[3]=function(t){return e.updateColWidths(t)}),onChangeSelectedCells:t[4]||(t[4]=function(t){return e.updateSelectedCells(t)})},null,8,["data","width","colWidths","outline","theme","editable"]),!e.editable||e.elementInfo.lock?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["table-mask",{lock:e.elementInfo.lock}],onDblclick:t[5]||(t[5]=function(t){return e.startEdit()}),onMousedown:t[6]||(t[6]=function(t){return e.handleSelectElement(t)})},[Object(h["createVNode"])("div",{class:"mask-tip",style:{transform:"scale(".concat(1/e.canvasScale,")")}},"双击编辑",4)],34)):Object(h["createCommentVNode"])("",!0)],512),[[l,e.contextmenus]])],6)})),pc=(n("13d5"),Object(h["withScopeId"])("data-v-7859e10e"));Object(h["pushScopeId"])("data-v-7859e10e");var bc={key:0,class:"handler"};Object(h["popScopeId"])();var mc=pc((function(e,t,n,o,c,a){var r,l,i,u,d,s=Object(h["resolveComponent"])("CustomTextarea"),f=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"editable-table",style:{width:e.totalWidth+"px"}},[e.editable?(Object(h["openBlock"])(),Object(h["createBlock"])("div",bc,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.dragLinePosition,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"drag-line",key:n,style:{left:t+"px"},onMousedown:function(t){return e.handleMousedownColHandler(t,n)}},null,44,["onMousedown"])})),128))])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("table",{class:{theme:e.theme,"row-header":null===(r=e.theme)||void 0===r?void 0:r.rowHeader,"row-footer":null===(l=e.theme)||void 0===l?void 0:l.rowFooter,"col-header":null===(i=e.theme)||void 0===i?void 0:i.colHeader,"col-footer":null===(u=e.theme)||void 0===u?void 0:u.colFooter},style:"--themeColor: ".concat(null===(d=e.theme)||void 0===d?void 0:d.color,"; --subThemeColor1: ").concat(e.subThemeColor[0],"; --subThemeColor2: ").concat(e.subThemeColor[1])},[Object(h["createVNode"])("colgroup",null,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.colSizeList,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])("col",{span:"1",key:t,width:e},null,8,["width"])})),128))]),Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.tableCells,(function(n,o){return Object(h["openBlock"])(),Object(h["createBlock"])("tr",{key:o},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(n,(function(n,c){return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("td",{class:["cell",{selected:e.selectedCells.includes("".concat(o,"_").concat(c))&&e.selectedCells.length>1,active:e.activedCell==="".concat(o,"_").concat(c)}],style:Object(P["a"])({borderStyle:e.outline.style,borderColor:e.outline.color,borderWidth:e.outline.width+"px"},e.getTextStyle(n.style)),key:n.id,rowspan:n.rowspan,colspan:n.colspan,"data-cell-index":"".concat(o,"_").concat(c),onMousedown:function(t){return e.handleCellMousedown(t,o,c)},onMouseenter:function(t){return e.handleCellMouseenter(o,c)}},[Object(h["createVNode"])(s,{class:["cell-text",{active:e.activedCell==="".concat(o,"_").concat(c)}],contenteditable:e.activedCell==="".concat(o,"_").concat(c)&&"plaintext-only",modelValue:n.text,"onUpdate:modelValue":[function(e){return n.text=e},t[1]||(t[1]=function(t){return e.handleInput()})]},null,8,["class","contenteditable","modelValue","onUpdate:modelValue"])],46,["rowspan","colspan","data-cell-index","onMousedown","onMouseenter"])),[[h["vShow"],!e.hideCells.includes("".concat(o,"_").concat(c))],[f,function(t){return e.contextmenus(t)}]])})),128))])})),128))])],6)],4)}));n("1276"),n("cc71");function vc(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"custom-textarea",ref:"textareaRef",contenteditable:e.contenteditable,onFocus:t[1]||(t[1]=function(){return e.handleFocus&&e.handleFocus.apply(e,arguments)}),onBlur:t[2]||(t[2]=function(){return e.handleBlur&&e.handleBlur.apply(e,arguments)}),onInput:t[3]||(t[3]=function(t){return e.handleInput(t)}),innerHTML:e.text},null,40,["contenteditable","innerHTML"])}var Oc=Object(h["defineComponent"])({name:"custom-textarea",props:{modelValue:{type:String,default:""},contenteditable:{type:[Boolean,String],default:!1}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=Object(h["ref"])(""),a=Object(h["ref"])(!1);Object(h["watch"])((function(){return e.modelValue}),(function(){a.value||(c.value=e.modelValue,o.value&&(o.value.innerHTML=e.modelValue))}),{immediate:!0});var r=function(){if(o.value){var e=o.value.innerHTML;n("update:modelValue",e)}},l=function(){a.value=!0,o.value&&(o.value.onpaste=function(e){if(e.preventDefault(),e.clipboardData){var t=e.clipboardData.items[0];t&&"string"===t.kind&&"text/plain"===t.type&&t.getAsString((function(e){return n("update:modelValue",e)}))}})},i=function(){a.value=!1,o.value&&(o.value.onpaste=null)};return Object(h["onUnmounted"])((function(){o.value&&(o.value.onpaste=null)})),{textareaRef:o,handleFocus:l,handleInput:r,handleBlur:i,text:c}}});Oc.render=vc;var hc=Oc,jc=Object(h["defineComponent"])({name:"editable-table",components:{CustomTextarea:hc},props:{data:{type:Array,required:!0},width:{type:Number,required:!0},colWidths:{type:Array,required:!0},outline:{type:Object,required:!0},theme:{type:Object},editable:{type:Boolean,default:!0}},setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.state.canvasScale})),a=Object(h["ref"])(["",""]);Object(h["watch"])((function(){return e.theme}),(function(){if(e.theme){var t=oc()(e.theme.color).toRgb(),n={r:t.r,g:t.g,b:t.b,a:.3*t.a},o={r:t.r,g:t.g,b:t.b,a:.1*t.a};a.value=["rgba(".concat([n.r,n.g,n.b,n.a].join(","),")"),"rgba(".concat([o.r,o.g,o.b,o.a].join(","),")")]}}),{immediate:!0});var r=Object(h["computed"])({get:function(){return e.data},set:function(e){n("change",e)}}),l=Object(h["ref"])([]),i=Object(h["computed"])((function(){return l.value.reduce((function(e,t){return e+t}))}));Object(h["watch"])([function(){return e.colWidths},function(){return e.width}],(function(){l.value=e.colWidths.map((function(t){return t*e.width}))}),{immediate:!0});var u=Object(h["ref"])(!1),d=Object(h["ref"])([]),s=Object(h["ref"])([]),f=function(){d.value=[],s.value=[]};Object(h["watch"])((function(){return e.editable}),(function(){e.editable||f()}));var p=Object(h["computed"])((function(){for(var e=[],t=1;t1||c.rowspan>1)for(var a=t;a=i&&b<=f&&v>=u&&v<=p&&l.push("".concat(b,"_").concat(v));return l}));Object(h["watch"])(m,(function(){n("changeSelectedCells",m.value)}));var v=Object(h["computed"])((function(){return m.value.length>1?null:m.value[0]})),O=Object(h["computed"])((function(){if(!d.value.length)return null;var e=Object(Xt["a"])(d.value,2),t=e[0],n=e[1];if(!s.value.length)return{row:[t,t],col:[n,n]};var o=Object(Xt["a"])(s.value,2),c=o[0],a=o[1];if(t===c&&n===a)return{row:[t,t],col:[n,n]};var r=Math.min(t,c),l=Math.min(n,a),i=Math.max(t,c),u=Math.max(n,a);return{row:[r,i],col:[l,u]}})),j=function(){return u.value=!1},g=function(e,t,n){0===e.button&&(s.value=[],u.value=!0,d.value=[t,n])},y=function(e,t){u.value&&(s.value=[e,t])};Object(h["onMounted"])((function(){document.addEventListener("mouseup",j)})),Object(h["onUnmounted"])((function(){document.removeEventListener("mouseup",j)}));var k=function(e,t){return b.value.includes("".concat(e,"_").concat(t))},E=function(e){var t=r.value.length-1;d.value=[0,e],s.value=[t,e]},I=function(e){var t=r.value[e].length-1;d.value=[e,0],s.value=[e,t]},S=function(){var e=r.value.length-1,t=r.value[e].length-1;d.value=[0,0],s.value=[e,t]},C=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),n=r.value[e],o=[],c=0;c=0;u--)if(!k(u,i)){t[u][i].rowspan=t[u][i].rowspan-1;break}t.splice(e,1),r.value=t},x=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),o=[],c=0;c=0;d--)if(!k(u,d)){t[u][d].colspan=t[u][d].colspan-1;break}r.value=t.map((function(t){return t.splice(e,1),t})),l.value.splice(e,1),n("changeColWidths",l.value)},N=function(e){for(var t=JSON.parse(JSON.stringify(r.value)),n=[],o=0;o1,n=e[0].length>1;return{canDeleteRow:t,canDeleteCol:n}},F=function(e,t){var n=m.value.length>1,o=r.value[e][t],c=n,a=!n&&(o.rowspan>1||o.colspan>1);return{canMerge:c,canSplit:a}},z=function(e){var t=e.dataset.cellIndex,n=+t.split("_")[0],o=+t.split("_")[1];m.value.includes("".concat(n,"_").concat(o))||(d.value=[n,o],s.value=[]);var c=F(n,o),a=c.canMerge,r=c.canSplit,l=R(),i=l.canDeleteRow,u=l.canDeleteCol;return[{text:"插入列",children:[{text:"到左侧",handler:function(){return T(o)}},{text:"到右侧",handler:function(){return T(o+1)}}]},{text:"插入行",children:[{text:"到上方",handler:function(){return N(n)}},{text:"到下方",handler:function(){return N(n+1)}}]},{text:"删除列",disable:!u,handler:function(){return x(o)}},{text:"删除行",disable:!i,handler:function(){return C(n)}},{divider:!0},{text:"合并单元格",disable:!a,handler:w},{text:"取消合并单元格",disable:!r,handler:function(){return L(n,o)}},{divider:!0},{text:"选中当前列",handler:function(){return E(o)}},{text:"选中当前行",handler:function(){return I(n)}},{text:"选中全部单元格",handler:S}]};return{getTextStyle:D,dragLinePosition:p,tableCells:r,colSizeList:l,totalWidth:i,hideCells:b,selectedCells:m,activedCell:v,selectedRange:O,handleCellMousedown:g,handleCellMouseenter:y,selectCol:E,selectRow:I,handleMousedownColHandler:V,contextmenus:z,handleInput:A,subThemeColor:a}}});n("14ac");jc.render=mc,jc.__scopeId="data-v-7859e10e";var gc=jc,yc=Object(h["defineComponent"])({name:"editable-element-table",components:{EditableTable:gc},props:{elementInfo:{type:Object,required:!0},selectElement:{type:Function,required:!0},contextmenus:{type:Function}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=ge(),c=o.addHistorySnapshot,a=function(t){e.elementInfo.lock||(t.stopPropagation(),e.selectElement(t,e.elementInfo))},r=Object(h["ref"])(!1),l=Object(h["computed"])((function(){return t.state.handleElementId}));Object(h["watch"])(l,(function(){l.value!==e.elementInfo.id&&(r.value=!1)})),Object(h["watch"])(r,(function(){t.commit(g.SET_DISABLE_HOTKEYS_STATE,r.value)}));var i=Object(h["ref"])(),u=Object(h["ref"])(!1),d=Object(h["ref"])(-1),s=function(n){u.value=n,n&&(r.value=!1),n||-1===d.value||(t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:d.value}}),d.value=-1)};Dt.on(_t.SCALE_ELEMENT_STATE,(function(e){return s(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.SCALE_ELEMENT_STATE,(function(e){return s(e)}))}));var f=function(n){var o=n[0].contentRect;if(i.value){var c=o.height;e.elementInfo.height!==c&&(u.value?d.value=c:t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{height:c}}))}},p=new ResizeObserver(f);Object(h["onMounted"])((function(){i.value&&p.observe(i.value)})),Object(h["onUnmounted"])((function(){i.value&&p.unobserve(i.value)}));var b=function(n){t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{data:n}}),c()},m=function(n){var o=n.reduce((function(e,t){return e+t})),a=n.map((function(e){return e/o}));t.commit(g.UPDATE_ELEMENT,{id:e.elementInfo.id,props:{width:o,colWidths:a}}),c()},v=function(e){Object(h["nextTick"])((function(){return Dt.emit(_t.UPDATE_TABLE_SELECTED_CELL,e)}))},O=function(){e.elementInfo.lock||(r.value=!0)};return{elementRef:i,canvasScale:n,handleSelectElement:a,updateTableCells:b,updateColWidths:m,editable:r,startEdit:O,updateSelectedCells:v}}});n("7e16");yc.render=fc,yc.__scopeId="data-v-045f7664";var kc=yc,Ec=Object(h["defineComponent"])({name:"editable-element",props:{elementInfo:{type:Object,required:!0},elementIndex:{type:Number,required:!0},isMultiSelect:{type:Boolean,required:!0},selectElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.theme})),o=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,Sn),Object(C["a"])(t,Jt.TEXT,Lo),Object(C["a"])(t,Jt.SHAPE,Ro),Object(C["a"])(t,Jt.LINE,Yo),Object(C["a"])(t,Jt.CHART,uc),Object(C["a"])(t,Jt.TABLE,kc),t);return n[e.elementInfo.type]||null})),c=Qt(),a=c.orderElement,r=en(),l=r.alignElementToCanvas,i=we(),u=i.combineElements,d=i.uncombineElements,s=Te(),f=s.deleteElement,p=Ne(),b=p.lockElement,m=p.unlockElement,v=Le(),O=v.copyElement,j=v.cutElement,g=function(){return e.elementInfo.lock?[{text:"解锁",handler:function(){return m(e.elementInfo)}}]:[{text:"剪切",subText:"Ctrl + X",handler:j},{text:"复制",subText:"Ctrl + C",handler:O},{divider:!0},{text:"层级排序",disable:e.isMultiSelect&&!e.elementInfo.groupId,children:[{text:"置顶层",handler:function(){return a(e.elementInfo,Ot.TOP)}},{text:"置底层",handler:function(){return a(e.elementInfo,Ot.BOTTOM)}},{divider:!0},{text:"上移一层",handler:function(){return a(e.elementInfo,Ot.UP)}},{text:"下移一层",handler:function(){return a(e.elementInfo,Ot.DOWN)}}]},{text:"水平对齐",children:[{text:"水平居中",handler:function(){return l(ht.HORIZONTAL)}},{text:"左对齐",handler:function(){return l(ht.LEFT)}},{text:"右对齐",handler:function(){return l(ht.RIGHT)}}]},{text:"垂直对齐",children:[{text:"垂直居中",handler:function(){return l(ht.VERTICAL)}},{text:"上对齐",handler:function(){return l(ht.TOP)}},{text:"下对齐",handler:function(){return l(ht.BOTTOM)}}]},{divider:!0},{text:e.elementInfo.groupId?"取消组合":"组合",subText:"Ctrl + G",handler:e.elementInfo.groupId?d:u,hide:!e.isMultiSelect},{text:"锁定",subText:"Ctrl + L",handler:b},{text:"删除",subText:"Delete",handler:f}]};return{currentElementComponent:o,contextmenus:g,theme:n}}});Ec.render=Zt;var Ic=Ec,Sc=Object(h["withScopeId"])("data-v-1619c258"),Cc=Sc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"mouse-selection quadrant-".concat(n.quadrant),style:{top:n.top+"px",left:n.left+"px",width:n.width+"px",height:n.height+"px"}},null,6)})),xc={name:"mouse-selection",props:{top:{type:Number,required:!0},left:{type:Number,required:!0},width:{type:Number,required:!0},height:{type:Number,required:!0},quadrant:{type:Number,required:!0,validator:function(e){return[1,2,3,4].includes(e)}}}};n("2007");xc.render=Cc,xc.__scopeId="data-v-1619c258";var Nc=xc,Tc=Object(h["withScopeId"])("data-v-774174ab"),wc=Tc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("GridLines");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"slide-background",style:e.backgroundStyle},[e.showGridLines?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0})):Object(h["createCommentVNode"])("",!0)],4)})),Lc=Object(h["withScopeId"])("data-v-6515bb1c"),Vc=Lc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"grid-lines"},{default:Lc((function(){return[Object(h["createVNode"])("path",{style:{transform:"scale(".concat(e.canvasScale,")")},d:e.path,fill:"none",stroke:e.gridColor,"stroke-width":"0.3","shape-rendering":"crispEdges","stroke-dasharray":"5"},null,12,["d","stroke"])]})),_:1})})),_c=Object(h["defineComponent"])({name:"grid-lines",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.canvasScale})),n=Object(h["computed"])((function(){return e.getters.currentSlide.background})),o=Object(h["computed"])((function(){if(!n.value||"image"===n.value.type)return"rgba(100, 100, 100, 0.5)";var e=n.value.color,t=oc()(e).toRgb(),o={r:t.r>128?t.r-128:t.r+127,g:t.g>128?t.g-128:t.g+127,b:t.b>128?t.b-128:t.b+127,a:.5};return"rgba(".concat([o.r,o.g,o.b,o.a].join(","),")")})),c=50,a=function(){for(var e=Ee,t=Ee*Ie,n="",o=0;o<=Math.floor(t/c);o++)n+="M0 ".concat(o*c,", L").concat(e," ").concat(o*c);for(var a=0;a<=Math.floor(e/c);a++)n+="M".concat(a*c," 0, L").concat(a*c," ").concat(t);return n};return{canvasScale:t,gridColor:o,width:Ee,height:Ee*Ie,path:a()}}});n("bd86");_c.render=Vc,_c.__scopeId="data-v-6515bb1c";var Bc=_c,Mc=function(e){var t=Object(h["computed"])((function(){if(!e.value)return{backgroundColor:"#fff"};var t=e.value,n=t.type,o=t.color,c=t.image,a=t.imageSize,r=t.gradientColor,l=t.gradientRotate,i=t.gradientType;if("solid"===n)return{backgroundColor:o};if("image"===n)return c?"repeat"===a?{backgroundImage:"url(".concat(c),backgroundRepeat:"repeat",backgroundSize:"initial"}:{backgroundImage:"url(".concat(c),backgroundRepeat:"no-repeat",backgroundSize:a||"cover"}:{backgroundColor:"#fff"};if("gradient"===n){var u=l||0,d=r?r[0]:"#fff",s=r?r[1]:"#fff";return"radial"===i?{backgroundImage:"radial-gradient(".concat(d,", ").concat(s)}:{backgroundImage:"linear-gradient(".concat(u,"deg, ").concat(d,", ").concat(s)}}return{backgroundColor:"#fff"}}));return{backgroundStyle:t}},Dc=Object(h["defineComponent"])({name:"slide-background",components:{GridLines:Bc},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.showGridLines})),n=Object(h["computed"])((function(){return e.getters.currentSlide.background})),o=Mc(n),c=o.backgroundStyle;return{showGridLines:t,backgroundStyle:c}}});n("7aa8");Dc.render=wc,Dc.__scopeId="data-v-774174ab";var Ac=Dc,Pc=Object(h["withScopeId"])("data-v-520a7023"),Rc=Pc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"alignment-line",style:{left:e.left,top:e.top}},[Object(h["createVNode"])("div",{class:["line",e.type],style:e.sizeStyle},null,6)],4)})),Fc=Object(h["defineComponent"])({name:"alignment-line",props:{type:{type:String,required:!0},axis:{type:Object,required:!0},length:{type:Number,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.axis.x*n.value+"px"})),c=Object(h["computed"])((function(){return e.axis.y*n.value+"px"})),a=Object(h["computed"])((function(){return"vertical"===e.type?{height:e.length*n.value+"px"}:{width:e.length*n.value+"px"}}));return{left:o,top:c,sizeStyle:a}}});n("032d");Fc.render=Rc,Fc.__scopeId="data-v-520a7023";var zc=Fc,Hc=Object(h["withScopeId"])("data-v-eea668f4"),Uc=Hc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"element-create-selection",ref:"selectionRef",onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.createSelection(t)}),["stop"]))},[e.start&&e.end?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["selection",e.creatingElement.type],style:e.position},["line"===e.creatingElement.type&&e.lineData?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,overflow:"visible",width:e.lineData.svgWidth,height:e.lineData.svgHeight},{default:Hc((function(){return[Object(h["createVNode"])("path",{d:e.lineData.path,stroke:"#888",fill:"none","stroke-width":"1","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":""},null,8,["d"])]})),_:1},8,["width","height"])):Object(h["createCommentVNode"])("",!0)],6)):Object(h["createCommentVNode"])("",!0)],544)})),Gc=Object(h["defineComponent"])({name:"element-create-selection",setup:function(e,t){var n=t.emit,o=X(),c=Object(h["computed"])((function(){return o.getters.ctrlOrShiftKeyActive})),a=Object(h["computed"])((function(){return o.state.creatingElement})),r=Object(h["ref"])(null),l=Object(h["ref"])(null),i=Object(h["ref"])(),u=Object(h["reactive"])({x:0,y:0});Object(h["onMounted"])((function(){if(i.value){var e=i.value.getBoundingClientRect(),t=e.x,n=e.y;u.x=t,u.y=n}}));var d=function(e){var t=!0,i=e.pageX,u=e.pageY;r.value=[i,u],document.onmousemove=function(e){if(a.value&&t){var n=e.pageX,o=e.pageY;if(c.value){var r=n-i,d=o-u,s=Math.abs(r),f=Math.abs(d);if("shape"===a.value.type){var p=d>0&&r<0||d<0&&r>0;s>f?o=p?u-r:u+r:n=p?i-d:i+d}else"line"===a.value.type&&(s>f?o=u:n=i)}l.value=[n,o]}},document.onmouseup=function(e){document.onmousemove=null,document.onmouseup=null,t=!1;var c=e.pageX,a=e.pageY,d=30;Math.abs(c-i)>=d||Math.abs(a-u)>=d?n("created",{start:r.value,end:l.value}):o.commit(g.SET_CREATING_ELEMENT,null)}},s=Object(h["computed"])((function(){if(!r.value||!l.value)return null;if(!a.value||"line"!==a.value.type)return null;var e=Object(Xt["a"])(r.value,2),t=e[0],n=e[1],o=Object(Xt["a"])(l.value,2),c=o[0],i=o[1],u=Math.min(t,c),d=Math.max(t,c),s=Math.min(n,i),f=Math.max(n,i),p=d-u>=24?d-u:24,b=f-s>=24?f-s:24,m=t===u?0:d-u,v=n===s?0:f-s,O=c===u?0:d-u,h=i===s?0:f-s,j="M".concat(m,", ").concat(v," L").concat(O,", ").concat(h);return{svgWidth:p,svgHeight:b,startX:m,startY:v,endX:O,endY:h,path:j}})),f=Object(h["computed"])((function(){if(!r.value||!l.value)return{};var e=Object(Xt["a"])(r.value,2),t=e[0],n=e[1],o=Object(Xt["a"])(l.value,2),c=o[0],a=o[1],i=Math.min(t,c),d=Math.max(t,c),s=Math.min(n,a),f=Math.max(n,a),p=d-i,b=f-s;return{left:i-u.x+"px",top:s-u.y+"px",width:p+"px",height:b+"px"}}));return{selectionRef:i,start:r,end:l,creatingElement:a,createSelection:d,lineData:s,position:f}}});n("4e78");Gc.render=Uc,Gc.__scopeId="data-v-eea668f4";var qc=Gc,Wc=Object(h["withScopeId"])("data-v-66dfa39d"),Xc=Wc((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"multi-select-operate",style:{left:e.minX*e.canvasScale+"px",top:e.minY*e.canvasScale+"px"}},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.disableResize?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleMultiElement(n,{minX:e.minX,maxX:e.maxX,minY:e.minY,maxY:e.maxY},t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))],4)})),Yc=function(e,t){var n=Object(h["computed"])((function(){return[{direction:gt.LEFT_TOP,style:{}},{direction:gt.TOP,style:{left:e.value/2+"px"}},{direction:gt.RIGHT_TOP,style:{left:e.value+"px"}},{direction:gt.LEFT,style:{top:t.value/2+"px"}},{direction:gt.RIGHT,style:{left:e.value+"px",top:t.value/2+"px"}},{direction:gt.LEFT_BOTTOM,style:{top:t.value+"px"}},{direction:gt.BOTTOM,style:{left:e.value/2+"px",top:t.value+"px"}},{direction:gt.RIGHT_BOTTOM,style:{left:e.value+"px",top:t.value+"px"}}]})),o=Object(h["computed"])((function(){return[{direction:gt.LEFT,style:{top:t.value/2+"px"}},{direction:gt.RIGHT,style:{left:e.value+"px",top:t.value/2+"px"}}]})),c=Object(h["computed"])((function(){return[{type:jt.T,style:{width:e.value+"px"}},{type:jt.B,style:{top:t.value+"px",width:e.value+"px"}},{type:jt.L,style:{height:t.value+"px"}},{type:jt.R,style:{left:e.value+"px",height:t.value+"px"}}]}));return{resizeHandlers:n,textElementResizeHandlers:o,borderLines:c}},Zc=Object(h["withScopeId"])("data-v-1c2a68d0"),Jc=Zc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["resize-handler",n.type]},null,2)})),Kc={name:"resize-handler",props:{type:{type:String,default:""}}};n("a933");Kc.render=Jc,Kc.__scopeId="data-v-1c2a68d0";var $c=Kc,Qc=Object(h["withScopeId"])("data-v-630e246b"),ea=Qc((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["border-line",n.type,{wide:n.isWide}]},null,2)})),ta={name:"border-line",props:{type:{type:String,required:!0},isWide:{type:Boolean,default:!1}}};n("fb1d");ta.render=ea,ta.__scopeId="data-v-630e246b";var na=ta,oa=Object(h["defineComponent"])({name:"multi-select-operate",components:{ResizeHandler:$c,BorderLine:na},props:{elementList:{type:Array,required:!0},scaleMultiElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.activeElementIdList})),o=Object(h["computed"])((function(){return t.state.canvasScale})),c=Object(h["computed"])((function(){return e.elementList.filter((function(e){return n.value.includes(e.id)}))})),a=Object(h["reactive"])({minX:0,maxX:0,minY:0,maxY:0}),r=Object(h["computed"])((function(){return(a.maxX-a.minX)*o.value})),l=Object(h["computed"])((function(){return(a.maxY-a.minY)*o.value})),i=Yc(r,l),u=i.resizeHandlers,d=i.borderLines,s=Object(h["computed"])((function(){return c.value.some((function(e){return!!("image"!==e.type&&"shape"!==e.type||e.rotate)}))})),f=function(){var e=xt(c.value),t=e.minX,n=e.maxX,o=e.minY,r=e.maxY;a.minX=t,a.maxX=n,a.minY=o,a.maxY=r};return Object(h["watchEffect"])(f),Object(P["a"])(Object(P["a"])({},Object(h["toRefs"])(a)),{},{canvasScale:o,borderLines:d,disableResize:s,resizeHandlers:u})}});n("6aa3");oa.render=Xc,oa.__scopeId="data-v-66dfa39d";var ca=oa,aa=Object(h["withScopeId"])("data-v-558a94fe");Object(h["pushScopeId"])("data-v-558a94fe");var ra={key:1,class:"animation-index"};Object(h["popScopeId"])();var la=aa((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["operate",{"multi-select":e.isMultiSelect&&!e.isActive}],style:{top:e.elementInfo.top*e.canvasScale+"px",left:e.elementInfo.left*e.canvasScale+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)"),transformOrigin:"".concat(e.elementInfo.width*e.canvasScale/2,"px ").concat(e.elementInfo.height*e.canvasScale/2,"px")}},[e.isSelected?(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentOperateComponent),{key:0,elementInfo:e.elementInfo,isActiveGroupElement:e.isActiveGroupElement,isMultiSelect:e.isMultiSelect,rotateElement:e.rotateElement,scaleElement:e.scaleElement,dragLineElement:e.dragLineElement},null,8,["elementInfo","isActiveGroupElement","isMultiSelect","rotateElement","scaleElement","dragLineElement"])):Object(h["createCommentVNode"])("",!0),"elAnimation"===e.toolbarState&&-1!==e.elementIndexInAnimation?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ra,Object(h["toDisplayString"])(e.elementIndexInAnimation+1),1)):Object(h["createCommentVNode"])("",!0)],6)})),ia=Object(h["withScopeId"])("data-v-5b0628aa"),ua=ia((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["image-element-operate",{cliping:e.isCliping}]},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))],2)})),da=Object(h["withScopeId"])("data-v-9a549510");Object(h["pushScopeId"])("data-v-9a549510");var sa={class:"rotate-handler"};Object(h["popScopeId"])();var fa=da((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",sa)})),pa={name:"rotate-handler"};n("8754");pa.render=fa,pa.__scopeId="data-v-9a549510";var ba=pa,ma=Object(h["defineComponent"])({name:"image-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.clipingImageElementId})),c=Object(h["computed"])((function(){return o.value===e.elementInfo.id})),a=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),r=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),l=Yc(a,r),i=l.resizeHandlers,u=l.borderLines;return{isCliping:c,scaleWidth:a,resizeHandlers:i,borderLines:u}}});n("5c02");ma.render=ua,ma.__scopeId="data-v-5b0628aa";var va=ma,Oa={class:"text-element-operate"};function ha(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Oa,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.textElementResizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))])}var ja=Object(h["defineComponent"])({name:"text-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.textElementResizeHandlers,l=a.borderLines;return{scaleWidth:o,textElementResizeHandlers:r,borderLines:l}}});ja.render=ha;var ga=ja,ya={class:"shape-element-operate"};function ka(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler"),i=Object(h["resolveComponent"])("RotateHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ya,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128)),Object(h["createVNode"])(i,{class:"operate-rotate-handler",style:{left:e.scaleWidth/2+"px"},onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.rotateElement(e.elementInfo)}),["stop"]))},null,8,["style"])],64))])}var Ea=Object(h["defineComponent"])({name:"shape-element-operate",inheritAttrs:!1,components:{RotateHandler:ba,ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.resizeHandlers,l=a.borderLines;return{scaleWidth:o,resizeHandlers:r,borderLines:l}}});Ea.render=ka;var Ia=Ea,Sa={class:"text-element-operate"};function Ca(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Sa,[e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.dragLineElement(n,e.elementInfo,t.handler)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var xa=Object(h["defineComponent"])({name:"text-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},dragLineElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return[{handler:yt.START,style:{left:e.elementInfo.start[0]*n.value+"px",top:e.elementInfo.start[1]*n.value+"px"}},{handler:yt.END,style:{left:e.elementInfo.end[0]*n.value+"px",top:e.elementInfo.end[1]*n.value+"px"}}]}));return{resizeHandlers:o}}});xa.render=Ca;var Na=xa,Ta={class:"chart-element-operate"};function wa(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Ta,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.resizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var La=Object(h["defineComponent"])({name:"chart-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.width*n.value})),c=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),a=Yc(o,c),r=a.resizeHandlers,l=a.borderLines;return{scaleWidth:o,resizeHandlers:r,borderLines:l}}});La.render=wa;var Va=La,_a={class:"table-element-operate"};function Ba(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("BorderLine"),l=Object(h["resolveComponent"])("ResizeHandler");return Object(h["openBlock"])(),Object(h["createBlock"])("div",_a,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.borderLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{class:"operate-border-line",key:e.type,type:e.type,style:e.style},null,8,["type","style"])})),128)),e.elementInfo.lock||!e.isActiveGroupElement&&e.isMultiSelect?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],{key:0},Object(h["renderList"])(e.textElementResizeHandlers,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{class:"operate-resize-handler",key:t.direction,type:t.direction,style:t.style,onMousedown:Object(h["withModifiers"])((function(n){return e.scaleElement(n,e.elementInfo,t.direction)}),["stop"])},null,8,["type","style","onMousedown"])})),128))])}var Ma=Object(h["defineComponent"])({name:"table-element-operate",inheritAttrs:!1,components:{ResizeHandler:$c,BorderLine:na},props:{elementInfo:{type:Object,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},scaleElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return e.elementInfo.outline.width||1})),c=Object(h["computed"])((function(){return(e.elementInfo.width+o.value)*n.value})),a=Object(h["computed"])((function(){return e.elementInfo.height*n.value})),r=Yc(c,a),l=r.textElementResizeHandlers,i=r.borderLines;return{scaleWidth:c,textElementResizeHandlers:l,borderLines:i}}});Ma.render=Ba;var Da=Ma,Aa=Object(h["defineComponent"])({name:"operate",props:{elementInfo:{type:Object,required:!0},isSelected:{type:Boolean,required:!0},isActive:{type:Boolean,required:!0},isActiveGroupElement:{type:Boolean,required:!0},isMultiSelect:{type:Boolean,required:!0},rotateElement:{type:Function,required:!0},scaleElement:{type:Function,required:!0},dragLineElement:{type:Function,required:!0}},setup:function(e){var t=X(),n=Object(h["computed"])((function(){return t.state.canvasScale})),o=Object(h["computed"])((function(){return t.state.toolbarState})),c=Object(h["computed"])((function(){return t.getters.currentSlide})),a=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,va),Object(C["a"])(t,Jt.TEXT,ga),Object(C["a"])(t,Jt.SHAPE,Ia),Object(C["a"])(t,Jt.LINE,Na),Object(C["a"])(t,Jt.CHART,Va),Object(C["a"])(t,Jt.TABLE,Da),t);return n[e.elementInfo.type]||null})),r=Object(h["computed"])((function(){var t=c.value.animations||[];return t.findIndex((function(t){return t.elId===e.elementInfo.id}))}));return{currentOperateComponent:a,canvasScale:n,toolbarState:o,elementIndexInAnimation:r}}});n("9884");Aa.render=la,Aa.__scopeId="data-v-558a94fe";var Pa=Aa,Ra=Object(h["defineComponent"])({name:"editor-canvas",components:{EditableElement:Ic,MouseSelection:Nc,SlideBackground:Ac,AlignmentLine:zc,ElementCreateSelection:qc,MultiSelectOperate:ca,Operate:Pa},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.state.handleElementId})),o=Object(h["computed"])((function(){return e.state.editorAreaFocus})),c=Object(h["computed"])((function(){return e.state.ctrlKeyState})),a=Object(h["computed"])((function(){return e.getters.ctrlOrShiftKeyActive})),r=Object(h["ref"])(),l=Object(h["ref"])([]),i=Object(h["ref"])("");Object(h["watch"])(n,(function(){return i.value=""}));var u=Object(h["computed"])((function(){return e.getters.currentSlide})),d=Object(h["ref"])([]),s=function(){d.value=u.value?JSON.parse(JSON.stringify(u.value.elements)):[]};Object(h["watchEffect"])(s);var f=Object(h["ref"])(),p=Object(h["computed"])((function(){return e.state.canvasScale})),b=It(f),m=b.viewportStyles;wt(f);var v=Tt(d,r),O=v.mouseSelectionState,j=v.updateMouseSelection,y=qt(d,i,l),k=y.dragElement,E=Wt(d),I=E.dragLineElement,S=Gt(d,i,k),C=S.selectElement,x=zt(d,i,l),N=x.scaleElement,T=x.scaleMultiElement,w=Vt(d,r),L=w.rotateElement,V=Ve(),_=V.selectAllElement,B=Te(),M=B.deleteAllElements,D=Le(),A=D.pasteElement,P=function(t){e.commit(g.SET_ACTIVE_ELEMENT_ID_LIST,[]),a.value||j(t),o.value||e.commit(g.SET_EDITORAREA_FOCUS,!0),Et()},R=function(){o.value&&e.commit(g.SET_EDITORAREA_FOCUS,!1)},F=Pe(),z=F.scaleCanvas,H=je()(z,100,{leading:!0,trailing:!1}),U=function(e){c.value&&(e.preventDefault(),e.deltaY>0?H("-"):e.deltaY<0&&H("+"))},G=Object(h["computed"])((function(){return e.state.showGridLines})),q=function(){e.commit(g.SET_GRID_LINES_STATE,!G.value)},W=Object(h["computed"])((function(){return e.state.creatingElement})),Y=Yt(r),Z=Y.insertElementFromCreateSelection,J=function(){return[{text:"全选",subText:"Ctrl + A",handler:_},{text:"粘贴",subText:"Ctrl + V",handler:A},{text:G.value?"关闭网格线":"打开网格线",handler:q},{text:"清空本页",handler:M}]};return Object(h["provide"])("slideScale",p),{elementList:d,activeElementIdList:t,handleElementId:n,activeGroupElementId:i,canvasRef:f,viewportRef:r,viewportStyles:m,canvasScale:p,mouseSelectionState:O,handleClickBlankArea:P,removeEditorAreaFocus:R,currentSlide:u,creatingElement:W,insertElementFromCreateSelection:Z,alignmentLines:l,selectElement:C,rotateElement:L,scaleElement:N,dragLineElement:I,scaleMultiElement:T,mousewheelScaleCanvas:U,contextmenus:J}}});n("923f");Ra.render=kt,Ra.__scopeId="data-v-75c486b2";var Fa=Ra,za=Object(h["withScopeId"])("data-v-1a2df855");Object(h["pushScopeId"])("data-v-1a2df855");var Ha={class:"canvas-tool"},Ua={class:"left-handler"},Ga={class:"add-element-handler"},qa={class:"right-handler"},Wa={class:"text"};Object(h["popScopeId"])();var Xa=za((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconBack"),l=Object(h["resolveComponent"])("Tooltip"),i=Object(h["resolveComponent"])("IconNext"),u=Object(h["resolveComponent"])("IconFontSize"),d=Object(h["resolveComponent"])("IconPicture"),s=Object(h["resolveComponent"])("FileInput"),f=Object(h["resolveComponent"])("ShapePool"),p=Object(h["resolveComponent"])("IconPentagonOne"),b=Object(h["resolveComponent"])("Popover"),m=Object(h["resolveComponent"])("LinePool"),v=Object(h["resolveComponent"])("IconConnection"),O=Object(h["resolveComponent"])("ChartPool"),j=Object(h["resolveComponent"])("IconChartProportion"),g=Object(h["resolveComponent"])("TableGenerator"),y=Object(h["resolveComponent"])("IconInsertTable"),k=Object(h["resolveComponent"])("IconMinus"),E=Object(h["resolveComponent"])("IconPlus"),I=Object(h["resolveComponent"])("IconFullScreen");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Ha,[Object(h["createVNode"])("div",Ua,[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"撤销"},{default:za((function(){return[Object(h["createVNode"])(r,{class:["handler-item",{disable:!e.canUndo}],onClick:t[1]||(t[1]=function(t){return e.undo()})},null,8,["class"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"重做"},{default:za((function(){return[Object(h["createVNode"])(i,{class:["handler-item",{disable:!e.canRedo}],onClick:t[2]||(t[2]=function(t){return e.redo()})},null,8,["class"])]})),_:1},8,["mouseEnterDelay"])]),Object(h["createVNode"])("div",Ga,[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入文字"},{default:za((function(){return[Object(h["createVNode"])(u,{class:"handler-item",onClick:t[3]||(t[3]=function(t){return e.drawText()})})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(s,{onChange:t[4]||(t[4]=function(t){return e.insertImageElement(t)})},{default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入图片"},{default:za((function(){return[Object(h["createVNode"])(d,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(b,{trigger:"click",visible:e.shapePoolVisible,"onUpdate:visible":t[6]||(t[6]=function(t){return e.shapePoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(f,{onSelect:t[5]||(t[5]=function(t){return e.drawShape(t)})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入形状"},{default:za((function(){return[Object(h["createVNode"])(p,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.linePoolVisible,"onUpdate:visible":t[8]||(t[8]=function(t){return e.linePoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(m,{onSelect:t[7]||(t[7]=function(t){return e.drawLine(t)})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入线条"},{default:za((function(){return[Object(h["createVNode"])(v,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.chartPoolVisible,"onUpdate:visible":t[10]||(t[10]=function(t){return e.chartPoolVisible=t})},{content:za((function(){return[Object(h["createVNode"])(O,{onSelect:t[9]||(t[9]=function(t){e.createChartElement(t),e.chartPoolVisible=!1})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入图表"},{default:za((function(){return[Object(h["createVNode"])(j,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"]),Object(h["createVNode"])(b,{trigger:"click",visible:e.tableGeneratorVisible,"onUpdate:visible":t[13]||(t[13]=function(t){return e.tableGeneratorVisible=t})},{content:za((function(){return[Object(h["createVNode"])(g,{onClose:t[11]||(t[11]=function(t){return e.tableGeneratorVisible=!1}),onInsert:t[12]||(t[12]=function(t){var n=t.row,o=t.col;e.createTableElement(n,o),e.tableGeneratorVisible=!1})})]})),default:za((function(){return[Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"插入表格"},{default:za((function(){return[Object(h["createVNode"])(y,{class:"handler-item"})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["visible"])]),Object(h["createVNode"])("div",qa,[Object(h["createVNode"])(k,{class:"handler-item viewport-size",onClick:t[14]||(t[14]=function(t){return e.scaleCanvas("-")})}),Object(h["createVNode"])("span",Wa,Object(h["toDisplayString"])(e.canvasScalePercentage),1),Object(h["createVNode"])(E,{class:"handler-item viewport-size",onClick:t[15]||(t[15]=function(t){return e.scaleCanvas("+")})}),Object(h["createVNode"])(l,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"适配屏幕"},{default:za((function(){return[Object(h["createVNode"])(I,{class:"handler-item viewport-size-adaptation",onClick:t[16]||(t[16]=function(t){return e.setCanvasPercentage(90)})})]})),_:1},8,["mouseEnterDelay"])])])})),Ya=Object(h["withScopeId"])("data-v-e95c032e");Object(h["pushScopeId"])("data-v-e95c032e");var Za={class:"shape-pool"},Ja={class:"category-name"},Ka={class:"shape-list"};Object(h["popScopeId"])();var $a=Ya((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Za,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.shapeList,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"category",key:t.type},[Object(h["createVNode"])("div",Ja,Object(h["toDisplayString"])(t.type),1),Object(h["createVNode"])("div",Ka,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(t.children,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"shape-item",key:n},[Object(h["createVNode"])("div",{class:"shape-content",onClick:function(n){return e.selectShape(t)}},[Object(h["createVNode"])(r,{overflow:"visible",width:"20",height:"20"},{default:Ya((function(){return[Object(h["createVNode"])("g",{transform:"scale(".concat(20/t.viewBox,", ").concat(20/t.viewBox,") translate(0,0) matrix(1,0,0,1,0,0)")},[Object(h["createVNode"])("path",{class:"shape-path","vector-effect":"non-scaling-stroke","stroke-linecap":"butt","stroke-miterlimit":"8","stroke-linejoin":"",fill:"transparent",stroke:"#999","stroke-width":"2",d:t.path},null,8,["d"])],8,["transform"])]})),_:2},1024)],8,["onClick"])])})),128))])])})),128))])})),Qa=[{type:"矩形",children:[{viewBox:200,path:"M 0 0 L 200 0 L 200 200 L 0 200 Z"},{viewBox:200,path:"M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z"},{viewBox:200,path:"M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z"},{viewBox:200,path:"M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200"},{viewBox:200,path:"M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z"},{viewBox:200,path:"M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z"},{viewBox:200,path:"M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z"},{viewBox:200,path:"M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z"}]},{type:"常用形状",children:[{viewBox:200,path:"M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 100 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 A 100 100 102 1 0 200 100 L 200 0 L 100 0 Z"},{viewBox:200,path:"M 0 0 L 200 0 Q 200 200 0 200 L 0 0 Z"},{viewBox:200,path:"M 100 0 L 0 200 L 200 200 L 100 0 Z"},{viewBox:200,path:"M 0 0 L 0 200 L 200 200 Z"},{viewBox:200,path:"M 50 0 L 200 0 L 150 200 L 0 200 L 50 0 Z"},{viewBox:200,path:"M 50 0 L 150 0 L 200 200 L 0 200 L 50 0 Z"},{viewBox:200,path:"M 100 0 L 0 100 L 100 200 L 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 0 L 0 90 L 50 200 L 150 200 L 200 90 L 100 0 Z"},{viewBox:200,path:"M 100 0 L 0 60 L 0 140 L 100 200 L 200 140 L 200 60 L 100 0 Z"},{viewBox:200,path:"M 60 0 L 140 0 L 200 60 L 200 140 L 140 200 L 60 200 L 0 140 L 0 60 L 60 0 Z"},{viewBox:200,path:"M 100 0 L 0 50 L 0 200 L 200 200 L 200 50 L 100 0 Z"},{viewBox:200,path:"M 150 0 A 50 100 0 1 1 150 200 L 0 200 L 0 0 L 150 0 Z"},{viewBox:200,path:"M 150 0 A 50 100 0 1 1 150 200 L 0 200 A 50 100 0 0 0 0 0 L 150 0 Z"},{viewBox:200,path:"M 200 100 L 150 0 L 0 0 L 50 100 L 0 200 L 150 200 L 200 100 Z"},{viewBox:200,path:"M 200 0 L 200 200 L 0 200 L 0 100 L 200 0 Z"},{viewBox:200,path:"M 50 0 L 150 0 L 150 50 L 200 50 L 200 150 L 150 150 L 150 200 L 50 200 L 50 150 L 0 150 L 0 50 L 50 50 L 50 0 Z"},{viewBox:200,path:"M 0 0 L 0 200 L 200 200 L 200 140 L 60 140 L 60 0 L 0 0 Z"},{viewBox:200,path:"M0 0 L200 0 L200 200 L0 200 L0 0 Z M50 50 L50 150 L150 150 L150 50 Z"},{viewBox:200,path:"M0 100 A100 100 0 1 1 0 101 Z M150 100 A50 50 0 1 0 150 101 Z"},{viewBox:200,path:"M 70 0 L 70 70 L 0 70 L 0 130 L 70 130 L 70 200 L 130 200 L 130 130 L 200 130 L 200 70 L 130 70 L 130 0 L 70 0 Z"},{viewBox:200,path:"M 40 0 L 0 40 L 60 100 L 0 160 L 40 200 L 100 140 L 160 200 L 200 160 L 140 100 L 200 40 L 160 0 L 100 60 L 40 0 Z"},{viewBox:200,path:"M 0 0 L 200 0 L 200 160 L 100 160 L 60 200 L 60 160 L 0 160 L 0 0 Z"},{viewBox:200,path:"M 0 40 Q 0 0 40 0 L 160 0 Q 200 0 200 40 L 200 120 Q 200 160 160 160 L 100 160 L 60 200 L 60 160 L 40 160 Q 0 160 0 120 L 0 40 Z"}]},{type:"箭头",children:[{viewBox:200,path:"M 100 0 L 0 100 L 50 100 L 50 200 L 150 200 L 150 100 L 200 100 L 100 0 Z"},{viewBox:200,path:"M 100 200 L 200 100 L 150 100 L 150 0 L 50 0 L 50 100 L 0 100 L 100 200 Z"},{viewBox:200,path:"M 0 100 L 100 0 L 100 50 L 200 50 L 200 150 L 100 150 L 100 200 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 100 0 L 100 50 L 0 50 L 0 150 L 100 150 L 100 200 L 200 100 Z"},{viewBox:200,path:"M 100 0 L 0 60 L 60 60 L 60 140 L 0 140 L 100 200 L 200 140 L 140 140 L 140 60 L 200 60 L 100 0 Z"},{viewBox:200,path:"M 0 100 L 60 0 L 60 60 L 140 60 L 140 0 L 200 100 L 140 200 L 140 140 L 60 140 L 60 200 L 0 100 Z"},{viewBox:200,path:"M 100 0 L 60 40 L 80 40 L 80 80 L 40 80 L 40 60 L 0 100 L 40 140 L 40 120 L 80 120 L 80 160 L 60 160 L 100 200 L 140 160 L 120 160 L 120 120 L 160 120 L 160 140 L 200 100 L 160 60 L 160 80 L 120 80 L 120 40 L 140 40 L 100 0 Z"},{viewBox:200,path:"M 0 100 L 100 0 L 100 50 L 200 50 L 150 100 L 200 150 L 100 150 L 100 200 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 100 0 L 100 50 L 0 50 L 50 100 L 0 150 L 100 150 L 100 200 L 200 100 Z"},{viewBox:200,path:"M 0 100 L 80 20 L 80 80 L 120 80 L 120 0 L 200 0 L 200 200 L 120 200 L 120 120 L 80 120 L 80 180 L 0 100 Z"},{viewBox:200,path:"M 200 100 L 120 20 L 120 80 L 80 80 L 80 0 L 0 0 L 0 200 L 80 200 L 80 120 L 120 120 L 120 180 L 200 100 Z"},{viewBox:200,path:"M 0 0 L 120 0 L 200 100 L 120 200 L 0 200 L 80 100 L 0 0 Z"},{viewBox:200,path:"M 80 0 L 200 0 L 120 100 L 200 200 L 80 200 L 0 100 L 80 0 Z"},{viewBox:200,path:"M 0 0 L 140 0 L 200 100 L 140 200 L 0 200 L 0 100 L 0 0 Z"},{viewBox:200,path:"M 60 0 L 200 0 L 200 100 L 200 200 L 60 200 L 0 100 L 60 0 Z"}]},{type:"其他形状",children:[{viewBox:1024,path:"M995.336 243.4016c-15.7584-36.5736-38.3376-69.26639999-66.91440001-97.37280001-28.5768-27.98879999-61.73999999-49.8624-98.78399999-65.26799998-38.22-15.876-78.6744-23.8728-120.4224-23.87280001-57.97680001 0-114.5424 15.876-163.69919999 45.864-11.76 7.17360001-22.932 15.05279999-33.51600001 23.63760001-10.584-8.5848-21.75600001-16.46400001-33.51600001-23.63760001-49.1568-29.98799999-105.7224-45.86399999-163.69919999-45.864-41.74799999 0-82.2024 7.9968-120.4224 23.87280001-36.9264 15.28799999-70.2072 37.27919999-98.78399999 65.26799998-28.6944 28.10640001-51.156 60.79919999-66.91440001 97.37280001-16.34639999 37.9848-24.696 78.3216-24.696 119.83439999 0 39.1608 7.9968 79.96800001 23.8728 121.48080001 13.28880001 34.692 32.34000001 70.67760001 56.6832 107.016 38.57279999 57.5064 91.61040001 117.4824 157.4664 178.28160001 109.1328 100.78319999 217.2072 170.4024 221.79359999 173.22479998l27.87120001 17.8752c12.348 7.8792 28.224 7.8792 40.572 0l27.87119999-17.8752c4.58639999-2.94 112.54319999-72.44159999 221.79360001-173.22479998 65.85599999-60.79919999 118.89359999-120.7752 157.4664-178.28160001 24.3432-36.33839999 43.512-72.324 56.68319999-107.016 15.876-41.5128 23.8728-82.32 23.87280001-121.48080001 0.1176-41.5128-8.232-81.8496-24.5784-119.83439999z"},{viewBox:1024,path:"M985.20746667 343.50079998l-303.32586667-44.08319999L546.28693333 24.5248c-3.70346666-7.5264-9.79626667-13.6192-17.32266665-17.32266668-18.87573334-9.3184-41.81333333-1.55306667-51.25120001 17.32266668L342.1184 299.41759999l-303.32586667 44.08319999c-8.36266667 1.19466667-16.00853333 5.13706667-21.8624 11.11040001-14.69440001 15.17226667-14.45546667 39.30453334 0.71679999 54.1184l219.46026668 213.9648-51.84853333 302.1312c-1.43359999 8.24320001-0.11946667 16.8448 3.82293333 24.25173333 9.79626667 18.6368 32.9728 25.92426667 51.6096 16.00853334L512 822.44266665l271.3088 142.64320001c7.40693333 3.9424 16.00853333 5.25653333 24.25173333 3.82293333 20.78719999-3.584 34.7648-23.296 31.1808-44.0832l-51.84853333-302.1312 219.46026668-213.9648c5.97333334-5.85386666 9.91573333-13.49973334 11.11039999-21.8624 3.2256-20.90666667-11.34933333-40.26026667-32.256-43.36640001z"},{viewBox:1024,path:"M852.65066667 405.84533333C800.54044445 268.40177778 667.76177778 170.66666667 512.22755555 170.66666667S223.91466667 268.288 171.80444445 405.73155555C74.29688889 431.33155555 2.27555555 520.07822222 2.27555555 625.77777778c0 125.72444445 101.83111111 227.55555555 227.44177778 227.55555555h564.56533334C919.89333333 853.33333333 1021.72444445 751.50222222 1021.72444445 625.77777778c0-105.472-71.79377778-194.21866667-169.07377778-219.93244445z"},{viewBox:1024,path:"M926.25224691 323.7371485H654.6457886L898.88200917 15.14388241c5.05486373-6.53433603 0.49315743-16.02761669-7.76722963-16.02761668H418.30008701c-3.45210206 0-6.78091476 1.84934039-8.50696579 4.93157436L90.35039154 555.76772251c-3.82197013 6.53433603 0.86302552 14.7947231 8.50696578 14.79472311h215.01664245l-110.22068713 440.88274851c-2.34249783 9.61657002 9.24670194 16.39748478 16.39748477 9.49328065L933.03316167 340.62779071c6.41104668-6.0411786 2.09591911-16.8906422-6.78091476-16.89064221z"},{viewBox:1024,path:"M878.47822222 463.30311111c-22.18666667-49.83466667-53.93066667-93.98044445-94.32177777-131.072l-33.10933334-30.37866666c-4.89244445-4.32355555-12.62933333-2.38933333-14.79111111 3.75466666l-14.79111111 42.43911111c-9.216 26.624-26.16888889 53.81688889-50.176 80.55466667-1.59288889 1.70666667-3.41333333 2.16177778-4.66488889 2.27555556-1.25155555 0.11377778-3.18577778-0.11377778-4.89244445-1.70666667-1.59288889-1.36533333-2.38933333-3.41333333-2.27555555-5.46133333 4.20977778-68.49422222-16.27022222-145.74933333-61.09866667-229.83111112C561.26577778 124.01777778 509.72444445 69.51822222 445.32622222 31.51644445l-46.99022222-27.648c-6.144-3.64088889-13.99466667 1.13777778-13.65333333 8.30577777l2.50311111 54.61333333c1.70666667 37.31911111-2.61688889 70.31466667-12.85688889 97.73511112-12.51555555 33.56444445-30.49244445 64.73955555-53.47555556 92.72888888-16.15644445 19.56977778-34.24711111 37.20533333-54.04444444 52.45155556-47.90044445 36.75022222-87.38133333 84.65066667-114.11911111 138.24C125.72444445 502.10133333 111.50222222 562.74488889 111.50222222 623.50222222c0 53.70311111 10.58133333 105.69955555 31.51644445 154.73777778 20.25244445 47.21777778 49.152 89.77066667 85.90222222 126.17955555 36.864 36.40888889 79.64444445 65.08088889 127.31733333 84.992C405.61777778 1010.11911111 457.95555555 1020.58666667 512 1020.58666667s106.38222222-10.46755555 155.76177778-31.06133334c47.67288889-19.91111111 90.56711111-48.46933333 127.31733333-84.992 36.864-36.40888889 65.76355555-78.96177778 85.90222222-126.17955555 20.93511111-49.03822222 31.51644445-101.03466667 31.51644445-154.73777778 0-55.52355555-11.37777778-109.45422222-34.01955556-160.31288889z"},{viewBox:1024,path:"M968.20337778 20.11591112H705.44042667c-22.17301333 0-41.92483556 15.16430222-47.14951111 37.33731555C642.36202666 124.73685332 582.08711111 173.03324444 512 173.03324444s-130.36202666-48.29639112-146.29091556-115.58001777c-5.22467555-22.17301333-24.84906667-37.33731556-47.14951111-37.33731555H55.79662222c-30.96576 0-56.06968889 25.10392889-56.06968888 56.06968888v321.12639999c0 30.96576 25.10392889 56.06968889 56.06968888 56.06968889h95.57333334v494.43271112c0 30.96576 25.10392889 56.06968889 56.06968889 56.06968888h609.1207111c30.96576 0 56.06968889-25.10392889 56.06968889-56.06968888V453.38168888h95.57333334c30.96576 0 56.06968889-25.10392889 56.06968888-56.06968889V76.1856c0-30.96576-25.10392889-56.06968889-56.06968888-56.06968888z"},{viewBox:1024,path:"M980.94648889 239.80714666H523.46880001L373.99210666 96.82944c-1.91146667-1.78403556-4.46008889-2.80348444-7.00871111-2.80348445H43.05351111c-22.55530667 0-40.77795555 18.22264888-40.77795555 40.77795557v754.39217776c0 22.55530667 18.22264888 40.77795555 40.77795555 40.77795557h937.89297778c22.55530667 0 40.77795555-18.22264888 40.77795555-40.77795557V280.58510222c0-22.55530667-18.22264888-40.77795555-40.77795555-40.77795556z"},{viewBox:1024,path:"M972.60904597 164.57058577L841.30587843 33.39070759c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480282-29.3428675-26.75379095 0-51.90482023 10.47959553-70.76809219 29.3428675L558.60337778 174.68031322c-18.86327195 18.86327195-29.34286748 44.1375906-29.34286749 70.64480283 0 26.75379095 10.47959553 51.90482023 29.34286749 70.76809218l103.31648301 103.31648302c-24.28800376 53.50758189-57.69942011 101.59043198-99.24793416 143.13894603-41.42522469 41.67180341-89.63136414 75.08321976-143.13894603 99.61780223L316.21649759 558.84995649c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480283-29.34286747-26.75379095 0-51.90482023 10.47959553-70.76809217 29.34286747L33.39070759 700.01627278c-18.86327195 18.86327195-29.34286748 44.1375906-29.3428675 70.76809217 0 26.75379095 10.47959553 51.90482023 29.3428675 70.76809219l131.05658883 131.05658883c30.08260365 30.205893 71.63111769 47.34311394 114.28923598 47.34311394 9.00012323 0 17.63037836-0.73973616 26.13734414-2.21920846 166.19405621-27.37023774 331.03192945-115.76870829 464.06114804-248.67463751C901.84095379 636.27567408 990.11613498 471.56109018 1017.85624079 304.87387654c8.38367642-50.91850535-8.50696579-103.31648302-45.24719482-140.30329077z"},{viewBox:1024,path:"M910.60451556 640.96028445c-20.38897778-65.49959112-43.83630221-120.54983112-79.89930667-210.64362666C836.31217778 193.67708444 737.93535999 2.27555556 511.36284444 2.27555556 282.24170667 2.27555556 186.03121778 197.50001778 192.14791111 430.31665779c-36.19043555 90.22122667-59.51032888 144.88917333-79.89930667 210.64362666-43.32657778 139.53706668-29.30915556 197.26336001-18.60494222 198.53767111 22.9376 2.80348444 89.32920888-105.00323556 89.32920889-105.00323556 0 62.44124445 32.11264001 143.86972444 101.69002667 202.61546667-33.64181333 10.32192-109.20846222 38.10190221-91.24067556 68.55793777 14.52714667 24.59420444 250.01984 15.67402668 317.94062222 8.02816 67.92078222 7.64586667 303.41347556 16.56604444 317.94062223-8.02816 17.96778667-30.32860444-57.72629333-58.23601779-91.24067555-68.55793777 69.57738667-58.87317334 101.69002667-140.30165333 101.69002667-202.61546667 0 0 66.39160889 107.80672 89.32920888 105.00323556 10.83164445-1.40174222 24.84906667-59.12803556-18.47751111-198.53767111z"},{viewBox:1024,path:"M1016.86992592 199.24764445c-37.13706667 16.01991111-77.55093333 27.54939259-119.17842962 32.03982222 42.96248889-25.60758518 75.60912592-66.02145185 91.02222222-114.08118519-39.68568889 23.66577778-84.58998518 41.02068148-131.31472593 50.00154074C819.53374815 126.79395555 765.76995555 101.79318518 706.18074075 101.79318518c-114.688 0-206.92385185 92.96402963-206.92385186 207.04521482 0 16.01991111 1.94180741 32.03982222 5.09724444 47.45291852-171.72859259-8.98085925-324.88865185-91.02222222-426.71217778-216.63288889-17.96171852 30.82619259-28.15620741 66.02145185-28.1562074 104.49351112 0 71.84687408 36.53025185 135.19834075 92.23585185 172.45677036-33.98162963-1.33499259-66.02145185-10.92266667-93.57084445-26.33576296v2.54862222c0 100.6098963 71.1186963 183.98625185 165.90317037 203.1616-17.3549037 4.49042963-35.92343703 7.03905185-54.49197037 7.03905185-13.47128889 0-26.2144-1.33499259-39.07887407-3.15543704C146.69748148 681.90814815 223.03478518 741.49736297 313.93564445 743.43917037c-71.1186963 55.7056-160.19911111 88.4736-256.9253926 88.4736-17.3549037 0-33.37481482-0.60681482-50.00154074-2.54862222C98.75911111 888.22518518 207.62168889 922.20681482 324.85831111 922.20681482 705.45256297 922.20681482 913.71140741 606.90583703 913.71140741 333.23235555c0-8.98085925 0-17.96171852-0.60681482-26.94257777 40.2925037-29.4912 75.60912592-66.02145185 103.76533333-107.04213333z"}]}],er=Object(h["defineComponent"])({name:"shape-pool",setup:function(e,t){var n=t.emit,o=Qa,c=function(e){n("select",e)};return{shapeList:o,selectShape:c}}});n("a2a2");er.render=$a,er.__scopeId="data-v-e95c032e";var tr=er,nr=Object(h["withScopeId"])("data-v-a0f5af54");Object(h["pushScopeId"])("data-v-a0f5af54");var or={class:"line-pool"};Object(h["popScopeId"])();var cr=nr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("LinePointMarker"),l=Object(h["resolveComponent"])("SvgWrapper");return Object(h["openBlock"])(),Object(h["createBlock"])("div",or,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.lineList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"line-item",key:n},[Object(h["createVNode"])("div",{class:"line-content",onClick:function(n){return e.selectLine(t)}},[Object(h["createVNode"])(l,{overflow:"visible",width:"20",height:"20"},{default:nr((function(){return[Object(h["createVNode"])("defs",null,[t.points[0]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,class:"line-marker",id:"preset-line-".concat(n),position:"start",type:t.points[0],color:"currentColor",baseSize:2},null,8,["id","type"])):Object(h["createCommentVNode"])("",!0),t.points[1]?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,class:"line-marker",id:"preset-line-".concat(n),position:"end",type:t.points[1],color:"currentColor",baseSize:2},null,8,["id","type"])):Object(h["createCommentVNode"])("",!0)]),Object(h["createVNode"])("path",{class:"line-path",d:t.path,stroke:"currentColor",fill:"none","stroke-width":"2","stroke-dasharray":"solid"===t.style?"0, 0":"4, 1","stroke-linecap":"","stroke-linejoin":"","stroke-miterlimit":"","marker-start":t.points[0]?"url(#".concat("preset-line-".concat(n),"-",t.points[0],"-start)"):"","marker-end":t.points[1]?"url(#".concat("preset-line-".concat(n),"-",t.points[1],"-end)"):""},null,8,["d","stroke-dasharray","marker-start","marker-end"])]})),_:2},1024)],8,["onClick"])])})),128))])})),ar=[{path:"M0,0 L20,20",style:"solid",points:["",""]},{path:"M0,0 L20,20",style:"dashed",points:["",""]},{path:"M0,0 L20,20",style:"solid",points:["","arrow"]},{path:"M0,0 L20,20",style:"dashed",points:["","arrow"]},{path:"M0,0 L20,20",style:"solid",points:["","dot"]}],rr=Object(h["defineComponent"])({name:"line-pool",components:{LinePointMarker:Wo},setup:function(e,t){var n=t.emit,o=ar,c=function(e){n("select",e)};return{lineList:o,selectLine:c}}});n("69b0");rr.render=cr,rr.__scopeId="data-v-a0f5af54";var lr=rr,ir=Object(h["withScopeId"])("data-v-28a1a821");Object(h["pushScopeId"])("data-v-28a1a821");var ur={class:"chart-pool"};Object(h["popScopeId"])();var dr=ir((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconChartLine"),l=Object(h["resolveComponent"])("IconChartHistogram"),i=Object(h["resolveComponent"])("IconChartProportion");return Object(h["openBlock"])(),Object(h["createBlock"])("ul",ur,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.chartList,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("li",{class:"chart-item",key:n},[Object(h["createVNode"])("div",{class:"chart-content",onClick:function(n){return e.selectChart(t)}},["line"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,size:"24"})):"bar"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,size:"24"})):"pie"===t?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:2,size:"24"})):Object(h["createCommentVNode"])("",!0)],8,["onClick"])])})),128))])})),sr=Object(h["defineComponent"])({name:"chart-pool",setup:function(e,t){var n=t.emit,o=["bar","line","pie"],c=function(e){n("select",e)};return{chartList:o,selectChart:c}}});n("4d85");sr.render=dr,sr.__scopeId="data-v-28a1a821";var fr=sr,pr=Object(h["withScopeId"])("data-v-0239b43b");Object(h["pushScopeId"])("data-v-0239b43b");var br={class:"table-generator"},mr={class:"title"},vr={class:"lef"},Or={key:1,class:"custom"},hr={class:"row"},jr=Object(h["createVNode"])("div",{class:"label",style:{flex:"1"}},"行数:",-1),gr={class:"row"},yr=Object(h["createVNode"])("div",{class:"label",style:{flex:"1"}},"列数:",-1),kr={class:"btns"},Er=Object(h["createTextVNode"])("取消"),Ir=Object(h["createTextVNode"])("确认");Object(h["popScopeId"])();var Sr=pr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("InputNumber"),l=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",br,[Object(h["createVNode"])("div",mr,[Object(h["createVNode"])("div",vr,"插入表格 "+Object(h["toDisplayString"])(e.endCell.length?"".concat(e.endCell[0]," x ").concat(e.endCell[1]):""),1),Object(h["createVNode"])("div",{class:"right",onClick:t[1]||(t[1]=function(t){return e.isCustom=!e.isCustom})},Object(h["toDisplayString"])(e.isCustom?"返回":"自定义"),1)]),e.isCustom?(Object(h["openBlock"])(),Object(h["createBlock"])("div",Or,[Object(h["createVNode"])("div",hr,[jr,Object(h["createVNode"])(r,{min:1,max:20,value:e.customRow,"onUpdate:value":t[4]||(t[4]=function(t){return e.customRow=t}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",gr,[yr,Object(h["createVNode"])(r,{min:1,max:20,value:e.customCol,"onUpdate:value":t[5]||(t[5]=function(t){return e.customCol=t}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",kr,[Object(h["createVNode"])(l,{class:"btn",onClick:t[6]||(t[6]=function(t){return e.close()})},{default:pr((function(){return[Er]})),_:1}),Object(h["createVNode"])(l,{class:"btn",type:"primary",onClick:t[7]||(t[7]=function(t){return e.insertCustomTable()})},{default:pr((function(){return[Ir]})),_:1})])])):(Object(h["openBlock"])(),Object(h["createBlock"])("table",{key:0,onMouseleave:t[2]||(t[2]=function(t){return e.endCell=[]}),onClick:t[3]||(t[3]=function(t){return e.handleClickTable()})},[Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(10,(function(t){return Object(h["createVNode"])("tr",{key:t},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(10,(function(n){return Object(h["createVNode"])("td",{onMouseenter:function(o){return e.endCell=[t,n]},key:n},[Object(h["createVNode"])("div",{class:["cell",{active:e.endCell.length&&t<=e.endCell[0]&&n<=e.endCell[1]}]},null,2)],40,["onMouseenter"])})),64))])})),64))])],32))])})),Cr=Object(h["defineComponent"])({name:"table-generator",setup:function(e,t){var n=t.emit,o=Object(h["ref"])([]),c=Object(h["ref"])(3),a=Object(h["ref"])(3),r=Object(h["ref"])(!1),l=function(){if(o.value.length){var e=Object(Xt["a"])(o.value,2),t=e[0],c=e[1];n("insert",{row:t,col:c})}},i=function(){return c.value<1||c.value>20||a.value<1||a.value>20?ee["a"].warning("行数/列数必须在0~20之间!"):(n("insert",{row:c.value,col:a.value}),void(r.value=!1))},u=function(){n("close"),r.value=!1};return{endCell:o,customRow:c,customCol:a,handleClickTable:l,insertCustomTable:i,isCustom:r,close:u}}});n("da1a");Cr.render=Sr,Cr.__scopeId="data-v-0239b43b";var xr=Cr,Nr=Object(h["defineComponent"])({name:"canvas-tool",components:{ShapePool:tr,LinePool:lr,ChartPool:fr,TableGenerator:xr},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.canvasScale})),n=Object(h["computed"])((function(){return e.getters.canUndo})),o=Object(h["computed"])((function(){return e.getters.canRedo})),c=Object(h["computed"])((function(){return parseInt(100*t.value+"")+"%"})),a=Pe(),r=a.scaleCanvas,l=a.setCanvasPercentage,i=ge(),u=i.redo,d=i.undo,s=Se(),f=s.createImageElement,p=s.createChartElement,b=s.createTableElement,m=function(e){var t=e[0];t&&ke(t).then((function(e){return f(e)}))},v=Object(h["ref"])(!1),O=Object(h["ref"])(!1),j=Object(h["ref"])(!1),y=Object(h["ref"])(!1),k=function(){e.commit(g.SET_CREATING_ELEMENT,{type:"text",data:null})},E=function(t){e.commit(g.SET_CREATING_ELEMENT,{type:"shape",data:t}),v.value=!1},I=function(t){e.commit(g.SET_CREATING_ELEMENT,{type:"line",data:t}),O.value=!1};return{scaleCanvas:r,setCanvasPercentage:l,canvasScalePercentage:c,canUndo:n,canRedo:o,redo:u,undo:d,insertImageElement:m,shapePoolVisible:v,linePoolVisible:O,chartPoolVisible:j,tableGeneratorVisible:y,drawText:k,drawShape:E,drawLine:I,createChartElement:p,createTableElement:b}}});n("ae3c");Nr.render=Xa,Nr.__scopeId="data-v-1a2df855";var Tr=Nr,wr=Object(h["withScopeId"])("data-v-6821a1b4");Object(h["pushScopeId"])("data-v-6821a1b4");var Lr=Object(h["createTextVNode"])(" 添加幻灯片"),Vr={class:"slide-index"},_r={class:"thumbnail"};Object(h["popScopeId"])();var Br=wr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconPlus"),l=Object(h["resolveComponent"])("ThumbnailSlide"),i=Object(h["resolveComponent"])("Draggable"),u=Object(h["resolveDirective"])("contextmenu"),d=Object(h["resolveDirective"])("click-outside");return Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"thumbnails",onMousedown:t[2]||(t[2]=function(){return e.setThumbnailsFocus(!0)})},[Object(h["createVNode"])("div",{class:"add-slide",onClick:t[1]||(t[1]=function(t){return e.createSlide()})},[Object(h["createVNode"])(r),Lr]),Object(h["createVNode"])(i,{class:"thumbnail-list",modelValue:e.slides,animation:300,scroll:!0,scrollSensitivity:50,onEnd:e.handleDragEnd,itemKey:"id"},{item:wr((function(t){var n=t.element,o=t.index;return[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:["thumbnail-wrapper",{active:e.slideIndex===o}],onMousedown:function(t){return e.changSlideIndex(o)}},[Object(h["createVNode"])("div",Vr,Object(h["toDisplayString"])(e.fillDigit(o+1,2)),1),Object(h["createVNode"])("div",_r,[Object(h["createVNode"])(l,{slide:n,size:120},null,8,["slide"])])],42,["onMousedown"]),[[u,e.contextmenusThumbnailItem]])]})),_:1},8,["modelValue","onEnd"])],544)),[[d,function(){return e.setThumbnailsFocus(!1)}],[u,e.contextmenusThumbnails]])})),Mr=n("b76a"),Dr=n.n(Mr),Ar=Object(h["withScopeId"])("data-v-1debfb1c"),Pr=Ar((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ThumbnailElement");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"thumbnail-slide",style:{width:e.size+"px",height:e.size*e.VIEWPORT_ASPECT_RATIO+"px"}},[Object(h["createVNode"])("div",{class:"elements-wrapper",style:{width:e.VIEWPORT_SIZE+"px",height:e.VIEWPORT_SIZE*e.VIEWPORT_ASPECT_RATIO+"px",transform:"scale(".concat(e.scale,")")}},[Object(h["createVNode"])("div",{class:"background",style:Object(P["a"])({},e.backgroundStyle)},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slide.elements,(function(e,t){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.id,elementInfo:e,elementIndex:t+1},null,8,["elementInfo","elementIndex"])})),128))],4)],4)}));function Rr(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"base-element",style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo,target:"thumbnail"},null,8,["elementInfo"]))],4)}var Fr=Object(h["withScopeId"])("data-v-008489be"),zr=Fr((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ImageRectOutline"),l=Object(h["resolveComponent"])("ImageEllipseOutline"),i=Object(h["resolveComponent"])("ImagePolygonOutline");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"base-element-image",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px",transform:"rotate(".concat(e.elementInfo.rotate,"deg)")}},[Object(h["createVNode"])("div",{class:"element-content",style:{filter:e.shadowStyle?"drop-shadow(".concat(e.shadowStyle,")"):"",transform:e.flip}},["rect"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,width:e.elementInfo.width,height:e.elementInfo.height,radius:e.clipShape.radius,outline:e.elementInfo.outline},null,8,["width","height","radius","outline"])):"ellipse"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"])):"polygon"===e.clipShape.type?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:2,width:e.elementInfo.width,height:e.elementInfo.height,createPath:e.clipShape.createPath,outline:e.elementInfo.outline},null,8,["width","height","createPath","outline"])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",{class:"image-content",style:{clipPath:e.clipShape.style}},[Object(h["createVNode"])("img",{src:e.elementInfo.src,draggable:!1,style:{top:e.imgPosition.top,left:e.imgPosition.left,width:e.imgPosition.width,height:e.imgPosition.height,filter:e.filter},alt:""},null,12,["src"])],4)],4)],4)})),Hr=Object(h["defineComponent"])({name:"base-element-image",components:{ImageRectOutline:dn,ImageEllipseOutline:bn,ImagePolygonOutline:hn},props:{elementInfo:{type:Object,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){if(!e.elementInfo||!e.elementInfo.clip)return{top:"0",left:"0",width:"100%",height:"100%"};var t=Object(Xt["a"])(e.elementInfo.clip.range,2),n=t[0],o=t[1],c=(o[0]-n[0])/100,a=(o[1]-n[1])/100,r=n[0]/c,l=n[1]/a;return{left:-r+"%",top:-l+"%",width:100/c+"%",height:100/a+"%"}})),n=Object(h["computed"])((function(){if(!e.elementInfo||!e.elementInfo.clip)return on.rect;var t=e.elementInfo.clip.shape||Kt.RECT;return on[t]})),o=Object(h["computed"])((function(){if(!e.elementInfo.filters)return"";for(var t="",n=0,o=Object.keys(e.elementInfo.filters);n1||a.rowspan>1)for(var r=n;r1&&void 0!==arguments[1]?arguments[1]:0,c=s(),a=c.originClipRange,r=c.originWidth,i=c.originHeight,u=c.originLeft,f=c.originTop;if(o){var p,b=i/r,m=0,v=100;if(b>o){var O=(1-o/b)/2*100;p=[[m,O],[v,v-O]]}else{var h=(1-b/o)/2*100;p=[[h,m],[v-h,v]]}e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{clip:Object(P["a"])(Object(P["a"])({},t.value.clip),{},{shape:n,range:p}),left:u+r*(p[0][0]/100),top:f+i*(p[0][1]/100),width:r*(p[1][0]-p[0][0])/100,height:i*(p[1][1]-p[0][1])/100}})}else e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{clip:Object(P["a"])(Object(P["a"])({},t.value.clip),{},{shape:n,range:a})}});d(),l()},p=function(n){var o=n[0];o&&(ke(o).then((function(n){var o={src:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o})})),l())},b=function(){if(t.value.clip){var n=s(),o=n.originWidth,c=n.originHeight,a=n.originLeft,r=n.originTop;e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:{left:a,top:r,width:o,height:c}})}e.commit(g.REMOVE_ELEMENT_PROPS,{id:t.value.id,propName:["clip","outline","flip","shadow","filters"]}),l()},m=function(){var o=Object(P["a"])(Object(P["a"])({},n.value.background),{},{type:"image",image:t.value.src,imageSize:"cover"});e.commit(g.UPDATE_SLIDE,{background:o}),l()};return{clipPanelVisible:o,shapeClipPathOptions:eu,ratioClipOptions:tu,filterOptions:a,flip:c,handleElement:t,updateImage:i,updateFilter:u,clipImage:d,presetImageClip:f,replaceImage:p,resetImage:b,setBackgroundImage:m}}});n("a347");nu.render=$i,nu.__scopeId="data-v-af9fc43e";var ou=nu,cu=Object(h["withScopeId"])("data-v-d415c6bc");Object(h["pushScopeId"])("data-v-d415c6bc");var au={class:"shape-style-panel"},ru={class:"row"},lu=Object(h["createTextVNode"])("纯色填充"),iu=Object(h["createTextVNode"])("渐变填充"),uu=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1),du=Object(h["createTextVNode"])("线性渐变"),su=Object(h["createTextVNode"])("径向渐变"),fu={class:"row"},pu=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点颜色:",-1),bu={class:"row"},mu=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点颜色:",-1),vu={key:0,class:"row"},Ou=Object(h["createVNode"])("div",{style:{flex:"2"}},"渐变角度:",-1);Object(h["popScopeId"])();var hu=cu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("Slider"),f=Object(h["resolveComponent"])("Divider"),p=Object(h["resolveComponent"])("ElementOutline"),b=Object(h["resolveComponent"])("ElementShadow"),m=Object(h["resolveComponent"])("ElementOpacity");return Object(h["openBlock"])(),Object(h["createBlock"])("div",au,[Object(h["createVNode"])("div",ru,[Object(h["createVNode"])(l,{style:{flex:"10"},value:e.fillType,onChange:t[1]||(t[1]=function(t){return e.updateFillType(t)})},{default:cu((function(){return[Object(h["createVNode"])(r,{value:"fill"},{default:cu((function(){return[lu]})),_:1}),Object(h["createVNode"])(r,{value:"gradient"},{default:cu((function(){return[iu]})),_:1})]})),_:1},8,["value"]),uu,"fill"===e.fillType?(Object(h["openBlock"])(),Object(h["createBlock"])(d,{key:0,trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.fill,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateFill(t)})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.fill,style:{flex:"10"}},null,8,["color"])]})),_:1})):(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,style:{flex:"10"},value:e.gradient.type,onChange:t[3]||(t[3]=function(t){return e.updateGradient({type:t})})},{default:cu((function(){return[Object(h["createVNode"])(r,{value:"linear"},{default:cu((function(){return[du]})),_:1}),Object(h["createVNode"])(r,{value:"radial"},{default:cu((function(){return[su]})),_:1})]})),_:1},8,["value"]))]),"gradient"===e.fillType?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",fu,[pu,Object(h["createVNode"])(d,{trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.gradient.color[0],"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.updateGradient({color:[t,e.gradient.color[1]]})})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.gradient.color[0],style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",bu,[mu,Object(h["createVNode"])(d,{trigger:"click"},{content:cu((function(){return[Object(h["createVNode"])(i,{modelValue:e.gradient.color[1],"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.updateGradient({color:[e.gradient.color[0],t]})})},null,8,["modelValue"])]})),default:cu((function(){return[Object(h["createVNode"])(u,{color:e.gradient.color[1],style:{flex:"3"}},null,8,["color"])]})),_:1})]),"linear"===e.gradient.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",vu,[Ou,Object(h["createVNode"])(s,{min:0,max:360,step:15,value:e.gradient.rotate,style:{flex:"3"},onChange:t[6]||(t[6]=function(t){return e.updateGradient({rotate:t})})},null,8,["value"])])):Object(h["createCommentVNode"])("",!0)],64)):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])(f),Object(h["createVNode"])(p),Object(h["createVNode"])(f),Object(h["createVNode"])(b),Object(h["createVNode"])(f),Object(h["createVNode"])(m)])})),ju=Object(h["defineComponent"])({name:"shape-style-panel",components:{ElementOpacity:ql,ElementOutline:si,ElementShadow:xi,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(),o=Object(h["ref"])(),c=Object(h["ref"])("fill");Object(h["watch"])(t,(function(){t.value&&"shape"===t.value.type&&(n.value=t.value.fill||"#000",o.value=t.value.gradient||{type:"linear",rotate:0,color:[n.value,"#fff"]},c.value=t.value.gradient?"gradient":"fill")}),{deep:!0,immediate:!0});var a=ge(),r=a.addHistorySnapshot,l=function(n){if("fill"===n)e.commit(g.REMOVE_ELEMENT_PROPS,{id:t.value.id,propName:"gradient"});else{var c={gradient:o.value};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c})}r()},i=function(n){var c={gradient:Object(P["a"])(Object(P["a"])({},o.value),n)};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c}),r()},u=function(n){var o={fill:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),r()};return{fill:n,gradient:o,fillType:c,updateFillType:l,updateFill:u,updateGradient:i}}});n("ff3e");ju.render=hu,ju.__scopeId="data-v-d415c6bc";var gu=ju,yu=Object(h["withScopeId"])("data-v-65b24fb3");Object(h["pushScopeId"])("data-v-65b24fb3");var ku={class:"line-style-panel"},Eu={class:"row"},Iu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条样式:",-1),Su=Object(h["createTextVNode"])("实线"),Cu=Object(h["createTextVNode"])("虚线"),xu={class:"row"},Nu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条颜色:",-1),Tu={class:"row"},wu=Object(h["createVNode"])("div",{style:{flex:"2"}},"线条宽度:",-1),Lu={class:"row"},Vu=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点样式:",-1),_u=Object(h["createTextVNode"])("无"),Bu=Object(h["createTextVNode"])("箭头"),Mu=Object(h["createTextVNode"])("圆点"),Du={class:"row"},Au=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点样式:",-1),Pu=Object(h["createTextVNode"])("无"),Ru=Object(h["createTextVNode"])("箭头"),Fu=Object(h["createTextVNode"])("圆点");Object(h["popScopeId"])();var zu=yu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("InputNumber"),f=Object(h["resolveComponent"])("Divider"),p=Object(h["resolveComponent"])("ElementShadow");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ku,[Object(h["createVNode"])("div",Eu,[Iu,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.style,onChange:t[1]||(t[1]=function(t){return e.updateLine({style:t})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:"solid"},{default:yu((function(){return[Su]})),_:1}),Object(h["createVNode"])(r,{value:"dashed"},{default:yu((function(){return[Cu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",xu,[Nu,Object(h["createVNode"])(d,{trigger:"click"},{content:yu((function(){return[Object(h["createVNode"])(i,{modelValue:e.handleElement.color,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateLine({color:t})})},null,8,["modelValue"])]})),default:yu((function(){return[Object(h["createVNode"])(u,{color:e.handleElement.color,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",Tu,[wu,Object(h["createVNode"])(s,{value:e.handleElement.width,onChange:t[3]||(t[3]=function(t){return e.updateLine({width:t})}),style:{flex:"3"}},null,8,["value"])]),Object(h["createVNode"])("div",Lu,[Vu,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.points[0],onChange:t[4]||(t[4]=function(t){return e.updateLine({points:[t,e.handleElement.points[1]]})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:""},{default:yu((function(){return[_u]})),_:1}),Object(h["createVNode"])(r,{value:"arrow"},{default:yu((function(){return[Bu]})),_:1}),Object(h["createVNode"])(r,{value:"dot"},{default:yu((function(){return[Mu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",Du,[Au,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.handleElement.points[1],onChange:t[5]||(t[5]=function(t){return e.updateLine({points:[e.handleElement.points[0],t]})})},{default:yu((function(){return[Object(h["createVNode"])(r,{value:""},{default:yu((function(){return[Pu]})),_:1}),Object(h["createVNode"])(r,{value:"arrow"},{default:yu((function(){return[Ru]})),_:1}),Object(h["createVNode"])(r,{value:"dot"},{default:yu((function(){return[Fu]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])(f),Object(h["createVNode"])(p)])})),Hu=Object(h["defineComponent"])({name:"line-style-panel",components:{ElementShadow:xi,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=ge(),o=n.addHistorySnapshot,c=function(n){e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:n}),o()};return{handleElement:t,updateLine:c}}});n("8df8e");Hu.render=zu,Hu.__scopeId="data-v-65b24fb3";var Uu=Hu,Gu=Object(h["withScopeId"])("data-v-0bd1ca02");Object(h["pushScopeId"])("data-v-0bd1ca02");var qu={class:"chart-style-panel"},Wu=Object(h["createTextVNode"])(" 编辑图表数据 "),Xu={class:"row"},Yu=Object(h["createTextVNode"])("面积图样式"),Zu=Object(h["createTextVNode"])("散点图样式"),Ju={class:"row"},Ku=Object(h["createTextVNode"])("使用平滑曲线"),$u={key:1,class:"row"},Qu=Object(h["createTextVNode"])("条形图样式"),ed={key:2,class:"row"},td=Object(h["createTextVNode"])("环形图样式"),nd={class:"row"},od=Object(h["createVNode"])("div",{style:{flex:"2"}},"背景填充:",-1),cd={class:"row"},ad=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题配色:",-1),rd={class:"row"},ld=Object(h["createVNode"])("div",{style:{flex:"2"}},"网格颜色:",-1);Object(h["popScopeId"])();var id=Gu((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEdit"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Divider"),u=Object(h["resolveComponent"])("Checkbox"),d=Object(h["resolveComponent"])("ColorPicker"),s=Object(h["resolveComponent"])("ColorButton"),f=Object(h["resolveComponent"])("Popover"),p=Object(h["resolveComponent"])("ElementOutline"),b=Object(h["resolveComponent"])("ChartDataEditor"),m=Object(h["resolveComponent"])("Modal");return Object(h["openBlock"])(),Object(h["createBlock"])("div",qu,[Object(h["createVNode"])(l,{class:"full-width-btn",onClick:t[1]||(t[1]=function(t){return e.chartDataEditorVisible=!0})},{default:Gu((function(){return[Object(h["createVNode"])(r,{class:"btn-icon"}),Wu]})),_:1}),Object(h["createVNode"])(i),"line"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Xu,[Object(h["createVNode"])(u,{onChange:t[2]||(t[2]=function(t){return e.updateOptions({showArea:t.target.checked})}),checked:e.showArea,style:{flex:"1"}},{default:Gu((function(){return[Yu]})),_:1},8,["checked"]),Object(h["createVNode"])(u,{onChange:t[3]||(t[3]=function(t){return e.updateOptions({showLine:!t.target.checked})}),checked:!e.showLine,style:{flex:"1"}},{default:Gu((function(){return[Zu]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Ju,[Object(h["createVNode"])(u,{onChange:t[4]||(t[4]=function(t){return e.updateOptions({lineSmooth:t.target.checked})}),checked:e.lineSmooth},{default:Gu((function(){return[Ku]})),_:1},8,["checked"])])],64)):Object(h["createCommentVNode"])("",!0),"bar"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",$u,[Object(h["createVNode"])(u,{onChange:t[5]||(t[5]=function(t){return e.updateOptions({horizontalBars:t.target.checked})}),checked:e.horizontalBars},{default:Gu((function(){return[Qu]})),_:1},8,["checked"])])):Object(h["createCommentVNode"])("",!0),"pie"===e.handleElement.chartType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ed,[Object(h["createVNode"])(u,{onChange:t[6]||(t[6]=function(t){return e.updateOptions({donut:t.target.checked})}),checked:e.donut},{default:Gu((function(){return[td]})),_:1},8,["checked"])])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])(i),Object(h["createVNode"])("div",nd,[od,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.fill,"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.updateFill(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.fill,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",cd,[ad,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.themeColor,"onUpdate:modelValue":t[8]||(t[8]=function(t){return e.updateTheme(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.themeColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",rd,[ld,Object(h["createVNode"])(f,{trigger:"click"},{content:Gu((function(){return[Object(h["createVNode"])(d,{modelValue:e.gridColor,"onUpdate:modelValue":t[9]||(t[9]=function(t){return e.updateGridColor(t)})},null,8,["modelValue"])]})),default:Gu((function(){return[Object(h["createVNode"])(s,{color:e.gridColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])(i),Object(h["createVNode"])(p),Object(h["createVNode"])(m,{visible:e.chartDataEditorVisible,"onUpdate:visible":t[12]||(t[12]=function(t){return e.chartDataEditorVisible=t}),footer:null,centered:"",closable:!1,width:648,destroyOnClose:""},{default:Gu((function(){return[Object(h["createVNode"])(b,{data:e.handleElement.data,onClose:t[10]||(t[10]=function(t){return e.chartDataEditorVisible=!1}),onSave:t[11]||(t[11]=function(t){return e.updateData(t)})},null,8,["data"])]})),_:1},8,["visible"])])})),ud=Object(h["withScopeId"])("data-v-73892bc6");Object(h["pushScopeId"])("data-v-73892bc6");var dd={class:"chart-data-editor"},sd={class:"editor-content"},fd={class:"range-box"},pd={class:"btns"},bd=Object(h["createTextVNode"])("取消"),md=Object(h["createTextVNode"])("确认");Object(h["popScopeId"])();var vd=ud((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",dd,[Object(h["createVNode"])("div",sd,[Object(h["createVNode"])("div",fd,[Object(h["createVNode"])("div",{class:"temp-range",style:{width:e.tempRangeSize.width+"px",height:e.tempRangeSize.height+"px"}},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.rangeLines,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["range-line",e.type],key:e.type,style:e.style},null,6)})),128)),Object(h["createVNode"])("div",{class:"resizable",style:e.resizablePointStyle,onMousedown:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.changeSelectRange(t)}),["stop"]))},null,36)]),Object(h["createVNode"])("table",null,[Object(h["createVNode"])("tbody",null,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(30,(function(t){return Object(h["createVNode"])("tr",{key:t},[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(7,(function(n){return Object(h["createVNode"])("td",{key:n,class:{head:1===n&&t<=e.selectedRange[1]}},[Object(h["createVNode"])("input",{class:["item",{selected:t<=e.selectedRange[1]&&n<=e.selectedRange[0]}],id:"cell-".concat(t-1,"-").concat(n-1),autocomplete:"off"},null,10,["id"])],2)})),64))])})),64))])])]),Object(h["createVNode"])("div",pd,[Object(h["createVNode"])(r,{class:"btn",onClick:t[2]||(t[2]=function(t){return e.closeEditor()})},{default:ud((function(){return[bd]})),_:1}),Object(h["createVNode"])(r,{type:"primary",class:"btn",onClick:t[3]||(t[3]=function(t){return e.getTableData()})},{default:ud((function(){return[md]})),_:1})])])})),Od=100,hd=32,jd=Object(h["defineComponent"])({name:"chart-data-editor",props:{data:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])([0,0]),c=Object(h["ref"])({width:0,height:0}),a=Object(h["computed"])((function(){var e=o.value[0]*Od,t=o.value[1]*hd;return[{type:"t",style:{width:e+"px"}},{type:"b",style:{top:t+"px",width:e+"px"}},{type:"l",style:{height:t+"px"}},{type:"r",style:{left:e+"px",height:t+"px"}}]})),r=Object(h["computed"])((function(){var e=o.value[0]*Od,t=o.value[1]*hd;return{left:e+"px",top:t+"px"}})),l=function(){for(var t=[],n=e.data,c=n.labels,a=n.series,r=c.length,l=a.length,i=0;i.5*Od&&(i+=Od-i%Od),u%hd>.5*hd&&(u+=hd-u%hd);var d=Math.round(u/hd),s=Math.round(i/Od);d<3&&(d=3),s<2&&(s=2),o.value=[s,d],c.value={width:0,height:0}}}};return{tempRangeSize:c,rangeLines:a,resizablePointStyle:r,changeSelectRange:d,selectedRange:o,getTableData:i,closeEditor:u}}});n("7dcf");jd.render=vd,jd.__scopeId="data-v-73892bc6";var gd=jd,yd=Object(h["defineComponent"])({name:"chart-style-panel",components:{ElementOutline:si,ChartDataEditor:gd,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(!1),o=ge(),c=o.addHistorySnapshot,a=Object(h["ref"])(),r=Object(h["ref"])(""),l=Object(h["ref"])(""),i=Object(h["ref"])(!0),u=Object(h["ref"])(!0),d=Object(h["ref"])(!1),s=Object(h["ref"])(!1),f=Object(h["ref"])(!1);Object(h["watch"])(t,(function(){if(t.value&&"chart"===t.value.type){if(a.value=t.value.fill||"#000",t.value.options){var e=t.value.options,n=e.lineSmooth,o=e.showLine,c=e.showArea,p=e.horizontalBars,b=e.donut;void 0!==n&&(i.value=n),void 0!==o&&(u.value=o),void 0!==c&&(d.value=c),void 0!==p&&(s.value=p),void 0!==b&&(f.value=b)}r.value=t.value.themeColor,l.value=t.value.gridColor||"rgba(0, 0, 0, 0.4)"}}),{deep:!0,immediate:!0});var p=function(o){n.value=!1;var a={data:o};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:a}),c()},b=function(n){var o={fill:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()},m=function(n){var o=t.value.options||{},a=Object(P["a"])(Object(P["a"])({},o),n),r={options:a};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:r}),c()},v=function(n){var o={themeColor:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()},O=function(n){var o={gridColor:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),c()};return{chartDataEditorVisible:n,handleElement:t,updateData:p,fill:a,updateFill:b,lineSmooth:i,showLine:u,showArea:d,horizontalBars:s,donut:f,updateOptions:m,themeColor:r,gridColor:l,updateTheme:v,updateGridColor:O}}});n("d1ba");yd.render=id,yd.__scopeId="data-v-0bd1ca02";var kd=yd,Ed=Object(h["withScopeId"])("data-v-63aedd01");Object(h["pushScopeId"])("data-v-63aedd01");var Id={class:"table-style-panel"},Sd={class:"row"},Cd=Object(h["createVNode"])("div",{style:{flex:"2"}},"行数:",-1),xd={class:"row"},Nd=Object(h["createVNode"])("div",{style:{flex:"2"}},"列数:",-1),Td={class:"row theme-switch"},wd=Object(h["createVNode"])("div",{style:{flex:"2"}},"启用主题表格:",-1),Ld={class:"switch-wrapper",style:{flex:"3"}},Vd={class:"row"},_d=Object(h["createTextVNode"])("标题行"),Bd=Object(h["createTextVNode"])("汇总行"),Md={class:"row"},Dd=Object(h["createTextVNode"])("第一列"),Ad=Object(h["createTextVNode"])("最后一列"),Pd={class:"row"},Rd=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题颜色:",-1);Object(h["popScopeId"])();var Fd=Ed((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconFontSize"),l=Object(h["resolveComponent"])("SelectOption"),i=Object(h["resolveComponent"])("Select"),u=Object(h["resolveComponent"])("IconAddText"),d=Object(h["resolveComponent"])("InputGroup"),s=Object(h["resolveComponent"])("ColorPicker"),f=Object(h["resolveComponent"])("IconText"),p=Object(h["resolveComponent"])("Button"),b=Object(h["resolveComponent"])("Tooltip"),m=Object(h["resolveComponent"])("Popover"),v=Object(h["resolveComponent"])("IconFill"),O=Object(h["resolveComponent"])("ButtonGroup"),j=Object(h["resolveComponent"])("IconTextBold"),g=Object(h["resolveComponent"])("CheckboxButton"),y=Object(h["resolveComponent"])("IconTextItalic"),k=Object(h["resolveComponent"])("IconTextUnderline"),E=Object(h["resolveComponent"])("IconStrikethrough"),I=Object(h["resolveComponent"])("CheckboxButtonGroup"),S=Object(h["resolveComponent"])("IconAlignTextLeft"),C=Object(h["resolveComponent"])("RadioButton"),x=Object(h["resolveComponent"])("IconAlignTextCenter"),N=Object(h["resolveComponent"])("IconAlignTextRight"),T=Object(h["resolveComponent"])("RadioGroup"),w=Object(h["resolveComponent"])("Divider"),L=Object(h["resolveComponent"])("ElementOutline"),V=Object(h["resolveComponent"])("InputNumber"),_=Object(h["resolveComponent"])("Switch"),B=Object(h["resolveComponent"])("Checkbox"),M=Object(h["resolveComponent"])("ColorButton");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Id,[Object(h["createVNode"])(d,{compact:"",class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(i,{style:{flex:"3"},value:e.textAttrs.fontname,onChange:t[1]||(t[1]=function(t){return e.updateTextAttrs({fontname:t})})},{suffixIcon:Ed((function(){return[Object(h["createVNode"])(r)]})),default:Ed((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.availableFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:e.en,value:e.en},{default:Ed((function(){return[Object(h["createVNode"])("span",{style:{fontFamily:e.en}},Object(h["toDisplayString"])(e.zh),5)]})),_:2},1032,["value"])})),128))]})),_:1},8,["value"]),Object(h["createVNode"])(i,{style:{flex:"2"},value:e.textAttrs.fontsize,onChange:t[2]||(t[2]=function(t){return e.updateTextAttrs({fontsize:t})})},{suffixIcon:Ed((function(){return[Object(h["createVNode"])(u)]})),default:Ed((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.fontSizeOptions,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:e,value:e},{default:Ed((function(){return[Object(h["createTextVNode"])(Object(h["toDisplayString"])(e),1)]})),_:2},1032,["value"])})),128))]})),_:1},8,["value"])]})),_:1}),Object(h["createVNode"])(O,{class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.textAttrs.color,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.updateTextAttrs({color:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"文字颜色"},{default:Ed((function(){return[Object(h["createVNode"])(p,{class:"text-color-btn",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(f),Object(h["createVNode"])("div",{class:"text-color-block",style:{backgroundColor:e.textAttrs.color}},null,4)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.textAttrs.backcolor,"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.updateTextAttrs({backcolor:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"单元格填充"},{default:Ed((function(){return[Object(h["createVNode"])(p,{class:"text-color-btn",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(v),Object(h["createVNode"])("div",{class:"text-color-block",style:{backgroundColor:e.textAttrs.backcolor}},null,4)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1})]})),_:1}),Object(h["createVNode"])(I,{class:"row"},{default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"加粗"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.bold,onClick:t[5]||(t[5]=function(t){return e.updateTextAttrs({bold:!e.textAttrs.bold})})},{default:Ed((function(){return[Object(h["createVNode"])(j)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"斜体"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.em,onClick:t[6]||(t[6]=function(t){return e.updateTextAttrs({em:!e.textAttrs.em})})},{default:Ed((function(){return[Object(h["createVNode"])(y)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下划线"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.underline,onClick:t[7]||(t[7]=function(t){return e.updateTextAttrs({underline:!e.textAttrs.underline})})},{default:Ed((function(){return[Object(h["createVNode"])(k)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"删除线"},{default:Ed((function(){return[Object(h["createVNode"])(g,{style:{flex:"1"},checked:e.textAttrs.strikethrough,onClick:t[8]||(t[8]=function(t){return e.updateTextAttrs({strikethrough:!e.textAttrs.strikethrough})})},{default:Ed((function(){return[Object(h["createVNode"])(E)]})),_:1},8,["checked"])]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(T,{class:"row","button-style":"solid",value:e.textAttrs.align,onChange:t[9]||(t[9]=function(t){return e.updateTextAttrs({align:t.target.value})})},{default:Ed((function(){return[Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"left",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(S)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"居中"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"center",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(x)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(b,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:Ed((function(){return[Object(h["createVNode"])(C,{value:"right",style:{flex:"1"}},{default:Ed((function(){return[Object(h["createVNode"])(N)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1},8,["value"]),Object(h["createVNode"])(w),Object(h["createVNode"])(L,{fixed:!0}),Object(h["createVNode"])(w),Object(h["createVNode"])("div",Sd,[Cd,Object(h["createVNode"])(V,{min:e.minRowCount,max:20,value:e.rowCount,"onUpdate:value":t[10]||(t[10]=function(t){return e.rowCount=t}),onPressEnter:t[11]||(t[11]=function(t){return e.setTableRow(t)}),onBlur:t[12]||(t[12]=function(t){return e.setTableRow(t)}),style:{flex:"3"}},null,8,["min","value"])]),Object(h["createVNode"])("div",xd,[Nd,Object(h["createVNode"])(V,{min:e.minColCount,max:20,value:e.colCount,"onUpdate:value":t[13]||(t[13]=function(t){return e.colCount=t}),onPressEnter:t[14]||(t[14]=function(t){return e.setTableCol(t)}),onBlur:t[15]||(t[15]=function(t){return e.setTableCol(t)}),style:{flex:"3"}},null,8,["min","value"])]),Object(h["createVNode"])(w),Object(h["createVNode"])("div",Td,[wd,Object(h["createVNode"])("div",Ld,[Object(h["createVNode"])(_,{checked:e.hasTheme,onChange:t[16]||(t[16]=function(t){return e.toggleTheme(t)})},null,8,["checked"])])]),e.hasTheme?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Vd,[Object(h["createVNode"])(B,{onChange:t[17]||(t[17]=function(t){return e.updateTheme({rowHeader:t.target.checked})}),checked:e.theme.rowHeader,style:{flex:"1"}},{default:Ed((function(){return[_d]})),_:1},8,["checked"]),Object(h["createVNode"])(B,{onChange:t[18]||(t[18]=function(t){return e.updateTheme({rowFooter:t.target.checked})}),checked:e.theme.rowFooter,style:{flex:"1"}},{default:Ed((function(){return[Bd]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Md,[Object(h["createVNode"])(B,{onChange:t[19]||(t[19]=function(t){return e.updateTheme({colHeader:t.target.checked})}),checked:e.theme.colHeader,style:{flex:"1"}},{default:Ed((function(){return[Dd]})),_:1},8,["checked"]),Object(h["createVNode"])(B,{onChange:t[20]||(t[20]=function(t){return e.updateTheme({colFooter:t.target.checked})}),checked:e.theme.colFooter,style:{flex:"1"}},{default:Ed((function(){return[Ad]})),_:1},8,["checked"])]),Object(h["createVNode"])("div",Pd,[Rd,Object(h["createVNode"])(m,{trigger:"click"},{content:Ed((function(){return[Object(h["createVNode"])(s,{modelValue:e.theme.color,"onUpdate:modelValue":t[21]||(t[21]=function(t){return e.updateTheme({color:t})})},null,8,["modelValue"])]})),default:Ed((function(){return[Object(h["createVNode"])(M,{color:e.theme.color,style:{flex:"3"}},null,8,["color"])]})),_:1})])],64)):Object(h["createCommentVNode"])("",!0)])})),zd=Object(h["defineComponent"])({name:"table-style-panel",components:{ElementOutline:si,ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])({bold:!1,em:!1,underline:!1,strikethrough:!1,color:"#000",backcolor:"#000",fontsize:"12px",fontname:"微软雅黑",align:"left"}),o=Object(h["ref"])(),c=Object(h["ref"])(!1),a=Object(h["ref"])(0),r=Object(h["ref"])(0),l=Object(h["ref"])(0),i=Object(h["ref"])(0);Object(h["watch"])(t,(function(){t.value&&"table"===t.value.type&&(o.value=t.value.theme,c.value=!!o.value,a.value=t.value.data.length,r.value=t.value.data[0].length,l.value=t.value.data.length,i.value=t.value.data[0].length)}),{deep:!0,immediate:!0});var u=Object(h["ref"])([]),d=function(){if(t.value){var e=0,o=0;if(u.value.length){var c=u.value[0];e=+c.split("_")[0],o=+c.split("_")[1]}var a=t.value.data[e][o].style;n.value=a?{bold:!!a.bold,em:!!a.em,underline:!!a.underline,strikethrough:!!a.strikethrough,color:a.color||"#000",backcolor:a.backcolor||"#000",fontsize:a.fontsize||"12px",fontname:a.fontname||"微软雅黑",align:a.align||"left"}:{bold:!1,em:!1,underline:!1,strikethrough:!1,color:"#000",backcolor:"#000",fontsize:"12px",fontname:"微软雅黑",align:"left"}}},s=function(e){u.value=e,d()};Dt.on(_t.UPDATE_TABLE_SELECTED_CELL,(function(e){return s(e)})),Object(h["onUnmounted"])((function(){Dt.off(_t.UPDATE_TABLE_SELECTED_CELL,(function(e){return s(e)}))}));var f=Object(h["computed"])((function(){return e.state.availableFonts})),p=["12px","14px","16px","18px","20px","22px","24px","28px","32px"],b=ge(),m=b.addHistorySnapshot,v=function(n){for(var o=JSON.parse(JSON.stringify(t.value.data)),c=0;c
X
Y
',1),Kd={class:"row"},$d=Object(h["createVNode"])("div",{style:{flex:"3"}},"大小:",-1),Qd={key:1,style:{flex:"1"}},es=Object(h["createStaticVNode"])('
',1),ts={class:"row"},ns=Object(h["createVNode"])("div",{style:{flex:"3"}},"旋转:",-1),os=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1);Object(h["popScopeId"])();var cs=qd((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconSendToBack"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Tooltip"),u=Object(h["resolveComponent"])("IconBringToFrontOne"),d=Object(h["resolveComponent"])("IconBringToFront"),s=Object(h["resolveComponent"])("IconSentToBack"),f=Object(h["resolveComponent"])("ButtonGroup"),p=Object(h["resolveComponent"])("IconAlignLeft"),b=Object(h["resolveComponent"])("IconAlignVertically"),m=Object(h["resolveComponent"])("IconAlignRight"),v=Object(h["resolveComponent"])("IconAlignTop"),O=Object(h["resolveComponent"])("IconAlignHorizontally"),j=Object(h["resolveComponent"])("IconAlignBottom"),g=Object(h["resolveComponent"])("Divider"),y=Object(h["resolveComponent"])("InputNumber"),k=Object(h["resolveComponent"])("IconLock"),E=Object(h["resolveComponent"])("IconUnlock"),I=Object(h["resolveComponent"])("IconRotate");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Wd,[Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"置顶层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[1]||(t[1]=function(t){return e.orderElement(e.handleElement,"top")})},{default:qd((function(){return[Object(h["createVNode"])(r)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"置底层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[2]||(t[2]=function(t){return e.orderElement(e.handleElement,"bottom")})},{default:qd((function(){return[Object(h["createVNode"])(u)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上移一层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[3]||(t[3]=function(t){return e.orderElement(e.handleElement,"up")})},{default:qd((function(){return[Object(h["createVNode"])(d)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下移一层"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[4]||(t[4]=function(t){return e.orderElement(e.handleElement,"down")})},{default:qd((function(){return[Object(h["createVNode"])(s)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[5]||(t[5]=function(t){return e.alignElementToCanvas("left")})},{default:qd((function(){return[Object(h["createVNode"])(p)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"水平居中"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[6]||(t[6]=function(t){return e.alignElementToCanvas("horizontal")})},{default:qd((function(){return[Object(h["createVNode"])(b)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[7]||(t[7]=function(t){return e.alignElementToCanvas("right")})},{default:qd((function(){return[Object(h["createVNode"])(m)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(f,{class:"row"},{default:qd((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[8]||(t[8]=function(t){return e.alignElementToCanvas("top")})},{default:qd((function(){return[Object(h["createVNode"])(v)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"垂直居中"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[9]||(t[9]=function(t){return e.alignElementToCanvas("vertical")})},{default:qd((function(){return[Object(h["createVNode"])(O)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下对齐"},{default:qd((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[10]||(t[10]=function(t){return e.alignElementToCanvas("bottom")})},{default:qd((function(){return[Object(h["createVNode"])(j)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(g),Object(h["createVNode"])("div",Xd,[Yd,Object(h["createVNode"])(y,{step:5,value:e.left,onChange:t[11]||(t[11]=function(t){return e.updateLeft(t)}),style:{flex:"4"}},null,8,["value"]),Zd,Object(h["createVNode"])(y,{step:5,value:e.top,onChange:t[12]||(t[12]=function(t){return e.updateTop(t)}),style:{flex:"4"}},null,8,["value"])]),Jd,"line"!==e.handleElement.type?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[Object(h["createVNode"])("div",Kd,[$d,Object(h["createVNode"])(y,{min:e.minSize,max:1500,step:5,value:e.width,onChange:t[13]||(t[13]=function(t){return e.updateWidth(t)}),style:{flex:"4"}},null,8,["min","value"]),["image","shape"].includes(e.handleElement.type)?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:0},[e.fixedRatio?(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:0,mouseLeaveDelay:0,mouseEnterDelay:.5,title:"解除宽高比锁定"},{default:qd((function(){return[Object(h["createVNode"])(k,{style:{flex:"1"},class:"icon-btn",onClick:t[14]||(t[14]=function(t){return e.updateFixedRatio(!1)})})]})),_:1},8,["mouseEnterDelay"])):(Object(h["openBlock"])(),Object(h["createBlock"])(i,{key:1,mouseLeaveDelay:0,mouseEnterDelay:.5,title:"宽高比锁定"},{default:qd((function(){return[Object(h["createVNode"])(E,{style:{flex:"1"},class:"icon-btn",onClick:t[15]||(t[15]=function(t){return e.updateFixedRatio(!0)})})]})),_:1},8,["mouseEnterDelay"]))],64)):(Object(h["openBlock"])(),Object(h["createBlock"])("div",Qd)),Object(h["createVNode"])(y,{min:e.minSize,max:800,step:5,disabled:"text"===e.handleElement.type,value:e.height,onChange:t[16]||(t[16]=function(t){return e.updateHeight(t)}),style:{flex:"4"}},null,8,["min","disabled","value"])]),es],64)):Object(h["createCommentVNode"])("",!0),["text","image","shape"].includes(e.handleElement.type)?(Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],{key:1},[Object(h["createVNode"])(g),Object(h["createVNode"])("div",ts,[ns,Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"逆时针旋转"},{default:qd((function(){return[Object(h["createVNode"])(I,{class:"icon-btn",onClick:t[17]||(t[17]=function(t){return e.updateRotate45("-")}),style:{flex:"2"}})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"顺时针旋转"},{default:qd((function(){return[Object(h["createVNode"])(I,{class:"icon-btn",onClick:t[18]||(t[18]=function(t){return e.updateRotate45("+")}),style:{flex:2,transform:"rotateY(180deg)"}},null,8,["style"])]})),_:1},8,["mouseEnterDelay"]),os,Object(h["createVNode"])(y,{min:-180,max:180,step:5,value:e.rotate,onChange:t[19]||(t[19]=function(t){return e.updateRotate(t)}),style:{flex:"4"}},null,8,["value"])])],64)):Object(h["createCommentVNode"])("",!0)])})),as=n("b69c"),rs=n.n(as),ls=Object(h["defineComponent"])({name:"element-positopn-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["ref"])(0),o=Object(h["ref"])(0),c=Object(h["ref"])(0),a=Object(h["ref"])(0),r=Object(h["ref"])(0),l=Object(h["ref"])(!1),i=Object(h["computed"])((function(){return t.value&&Pt[t.value.type]||20}));Object(h["watch"])(t,(function(){t.value&&(n.value=rs()(t.value.left,1),o.value=rs()(t.value.top,1),l.value="fixedRatio"in t.value&&!!t.value.fixedRatio,"line"!==t.value.type&&(c.value=rs()(t.value.width,1),a.value=rs()(t.value.height,1),r.value="rotate"in t.value&&void 0!==t.value.rotate?rs()(t.value.rotate,1):0))}),{deep:!0,immediate:!0});var u=Qt(),d=u.orderElement,s=en(),f=s.alignElementToCanvas,p=ge(),b=p.addHistorySnapshot,m=function(n){var o={left:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},v=function(n){var o={top:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},O=function(n){var o={width:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},j=function(n){var o={height:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},y=function(n){var o={rotate:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},k=function(n){var o={fixedRatio:n};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:o}),b()},E=function(n){var o=45*Math.floor(r.value/45);"+"===n?o+=45:"-"===n&&(o-=45),o<-180&&(o=-180),o>180&&(o=180);var c={rotate:o};e.commit(g.UPDATE_ELEMENT,{id:t.value.id,props:c}),b()};return{handleElement:t,orderElement:d,alignElementToCanvas:f,left:n,top:o,width:c,height:a,rotate:r,fixedRatio:l,minSize:i,updateLeft:m,updateTop:v,updateWidth:O,updateHeight:j,updateRotate:y,updateFixedRatio:k,updateRotate45:E}}});n("e407");ls.render=cs,ls.__scopeId="data-v-1a79147f";var is=ls,us=Object(h["withScopeId"])("data-v-3483fbf2");Object(h["pushScopeId"])("data-v-3483fbf2");var ds={class:"element-animation-panel"},ss={key:0,class:"element-animation"},fs={class:"animation-pool"},ps={class:"type-title"},bs={class:"pool-item-wrapper"},ms={key:1,class:"tip"},vs=Object(h["createTextVNode"])(" 选中画布中的元素添加动画"),Os={class:"index"},hs={class:"text"},js={class:"handler"};Object(h["popScopeId"])();var gs,ys=us((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconEffects"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Popover"),u=Object(h["resolveComponent"])("IconClick"),d=Object(h["resolveComponent"])("Divider"),s=Object(h["resolveComponent"])("IconPlayOne"),f=Object(h["resolveComponent"])("Tooltip"),p=Object(h["resolveComponent"])("IconCloseSmall"),b=Object(h["resolveComponent"])("Draggable");return Object(h["openBlock"])(),Object(h["createBlock"])("div",ds,[e.handleElement?(Object(h["openBlock"])(),Object(h["createBlock"])("div",ss,[Object(h["createVNode"])(i,{trigger:"click",visible:e.animationPoolVisible,"onUpdate:visible":t[2]||(t[2]=function(t){return e.animationPoolVisible=t})},{content:us((function(){return[Object(h["createVNode"])("div",fs,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.animations,(function(n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"pool-type",key:n.name},[Object(h["createVNode"])("div",ps,Object(h["toDisplayString"])(n.name)+":",1),Object(h["createVNode"])("div",bs,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(n.children,(function(n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"pool-item",key:n.name,onMouseenter:function(t){return e.hoverPreviewAnimation=n.value},onMouseleave:t[1]||(t[1]=function(t){return e.hoverPreviewAnimation=""}),onClick:function(t){return e.addAnimation(n.value)}},[Object(h["createVNode"])("div",{class:["animation-box",["animate__animated","animate__faster",e.hoverPreviewAnimation===n.value&&"animate__".concat(n.value)]]},Object(h["toDisplayString"])(n.name),3)],40,["onMouseenter","onClick"])})),128))])])})),128))])]})),default:us((function(){return[Object(h["createVNode"])(l,{class:"element-animation-btn"},{default:us((function(){return[Object(h["createVNode"])(r,{style:{"margin-right":"5px"}}),Object(h["createTextVNode"])(" "+Object(h["toDisplayString"])(e.handleElementAnimation||"点击选择动画"),1)]})),_:1})]})),_:1},8,["visible"])])):(Object(h["openBlock"])(),Object(h["createBlock"])("div",ms,[Object(h["createVNode"])(u),vs])),Object(h["createVNode"])(d),Object(h["createVNode"])(b,{class:"animation-sequence",modelValue:e.animationSequence,animation:300,scroll:!0,scrollSensitivity:50,onEnd:e.handleDragEnd,itemKey:"id"},{item:us((function(t){var n,o=t.element,c=t.index;return[Object(h["createVNode"])("div",{class:["sequence-item",{active:(null===(n=e.handleElement)||void 0===n?void 0:n.id)===o.elId}]},[Object(h["createVNode"])("div",Os,Object(h["toDisplayString"])(c+1),1),Object(h["createVNode"])("div",hs,"【"+Object(h["toDisplayString"])(o.elType)+"】"+Object(h["toDisplayString"])(o.animationType),1),Object(h["createVNode"])("div",js,[Object(h["createVNode"])(f,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"预览"},{default:us((function(){return[Object(h["createVNode"])(s,{class:"handler-btn",onClick:function(t){return e.runAnimation(o.elId,o.type)}},null,8,["onClick"])]})),_:2},1032,["mouseEnterDelay"]),Object(h["createVNode"])(f,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"删除"},{default:us((function(){return[Object(h["createVNode"])(p,{class:"handler-btn",onClick:function(t){return e.deleteAnimation(o.elId)}},null,8,["onClick"])]})),_:2},1032,["mouseEnterDelay"])])],2)]})),_:1},8,["modelValue","onEnd"])])})),ks=[{type:"bounce",name:"弹跳",children:[{name:"弹入",value:"bounceIn"},{name:"向右弹入",value:"bounceInLeft"},{name:"向左弹入",value:"bounceInRight"},{name:"向上弹入",value:"bounceInUp"},{name:"向下弹入",value:"bounceInDown"}]},{type:"fade",name:"浮现",children:[{name:"浮入",value:"fadeIn"},{name:"向下浮入",value:"fadeInDown"},{name:"向下长距浮入",value:"fadeInDownBig"},{name:"向右浮入",value:"fadeInLeft"},{name:"向右长距浮入",value:"fadeInLeftBig"},{name:"向左浮入",value:"fadeInRight"},{name:"向左长距浮入",value:"fadeInRightBig"},{name:"向上浮入",value:"fadeInUp"},{name:"向上长距浮入",value:"fadeInUpBig"},{name:"从左上浮入",value:"fadeInTopLeft"},{name:"从右上浮入",value:"fadeInTopRight"},{name:"从左下浮入",value:"fadeInBottomLeft"},{name:"从右下浮入",value:"fadeInBottomRight"}]},{type:"rotate",name:"旋转",children:[{name:"旋转进入",value:"rotateIn"},{name:"绕左下旋转进入",value:"rotateInDownLeft"},{name:"绕右下旋转进入",value:"rotateInDownRight"},{name:"绕左上旋转进入",value:"rotateInUpLeft"},{name:"绕右上旋转进入",value:"rotateInUpRight"}]},{type:"zoom",name:"缩放",children:[{name:"放大进入",value:"zoomIn"},{name:"向下放大进入",value:"zoomInDown"},{name:"从左放大进入",value:"zoomInLeft"},{name:"从右放大进入",value:"zoomInRight"},{name:"向上放大进入",value:"zoomInUp"}]},{type:"slide",name:"滑入",children:[{name:"向下滑入",value:"slideInDown"},{name:"从右滑入",value:"slideInLeft"},{name:"从左滑入",value:"slideInRight"},{name:"向上滑入",value:"slideInUp"}]},{type:"flip",name:"翻转",children:[{name:"X轴翻转进入",value:"flipInX"},{name:"Y轴翻转进入",value:"flipInY"}]},{type:"back",name:"放大滑入",children:[{name:"向下放大滑入",value:"backInDown"},{name:"从左放大滑入",value:"backInLeft"},{name:"从右放大滑入",value:"backInRight"},{name:"向上放大滑入",value:"backInUp"}]},{type:"lightSpeed",name:"飞入",children:[{name:"从右飞入",value:"lightSpeedInRight"},{name:"从左飞入",value:"lightSpeedInLeft"}]}],Es={},Is=Object(me["a"])(ks);try{for(Is.s();!(gs=Is.n()).done;){var Ss,Cs=gs.value,xs=Object(me["a"])(Cs.children);try{for(xs.s();!(Ss=xs.n()).done;){var Ns=Ss.value;Es[Ns.value]=Ns.name}}catch(cO){xs.e(cO)}finally{xs.f()}}}catch(cO){Is.e(cO)}finally{Is.f()}var Ts=Object(h["defineComponent"])({name:"element-animation-panel",components:{Draggable:Dr.a},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.getters.handleElement})),n=Object(h["computed"])((function(){return e.getters.currentSlideAnimations})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["ref"])(""),a=Object(h["ref"])(!1),r=ge(),l=r.addHistorySnapshot,i=ks,u=Object(h["computed"])((function(){if(!n.value)return[];var e,t=[],c=Object(me["a"])(n.value);try{var a=function(){var n=e.value,c=o.value.elements.find((function(e){return e.id===n.elId}));if(!c)return"continue";var a=At[c.type],r=Es[n.type];t.push(Object(P["a"])(Object(P["a"])({},n),{},{elType:a,animationType:r}))};for(c.s();!(e=c.n()).done;)a()}catch(cO){c.e(cO)}finally{c.f()}return t})),d=Object(h["computed"])((function(){if(!t.value)return null;var e=n.value||[],o=e.find((function(e){return e.elId===t.value.id}));return o?Es[o.type]:null})),s=function(o){var c=n.value.map((function(e){return e.elId===t.value.id?Object(P["a"])(Object(P["a"])({},e),{},{type:o}):e}));e.commit(g.UPDATE_SLIDE,{animations:c}),a.value=!1,l()},f=function(o){if(d.value)s(o);else{var c=n.value?JSON.parse(JSON.stringify(n.value)):[];c.push({elId:t.value.id,type:o,duration:1e3}),e.commit(g.UPDATE_SLIDE,{animations:c}),a.value=!1,l()}},p=function(t){var o=n.value.filter((function(e){return e.elId!==t}));e.commit(g.UPDATE_SLIDE,{animations:o}),l()},b=function(t){var o=t.newIndex,c=t.oldIndex;if(c!==o){var a=JSON.parse(JSON.stringify(n.value)),r=a[c];a.splice(c,1),a.splice(o,0,r),e.commit(g.UPDATE_SLIDE,{animations:a}),l()}},m=function(e,t){var n="animate__",o=document.querySelector("#editable-element-".concat(e," [class^=editable-element-]"));if(o){var c="".concat(n).concat(t);o.classList.add("".concat(n,"animated"),c);var a=function(){o.classList.remove("".concat(n,"animated"),c)};o.addEventListener("animationend",a,{once:!0})}};return{handleElement:t,animationPoolVisible:a,animations:i,animationSequence:u,hoverPreviewAnimation:c,handleElementAnimation:d,addAnimation:f,deleteAnimation:p,handleDragEnd:b,runAnimation:m}}});n("6836");Ts.render=ys,Ts.__scopeId="data-v-3483fbf2";var ws=Ts,Ls=Object(h["withScopeId"])("data-v-52253a56");Object(h["pushScopeId"])("data-v-52253a56");var Vs={class:"slide-style-panel"},_s=Object(h["createVNode"])("div",{class:"title"},"背景填充",-1),Bs={class:"row"},Ms=Object(h["createTextVNode"])("纯色填充"),Ds=Object(h["createTextVNode"])("图片填充"),As=Object(h["createTextVNode"])("渐变填充"),Ps=Object(h["createVNode"])("div",{style:{flex:"1"}},null,-1),Rs=Object(h["createTextVNode"])("原始大小"),Fs=Object(h["createTextVNode"])("缩放"),zs=Object(h["createTextVNode"])("拼贴"),Hs=Object(h["createTextVNode"])("缩放铺满"),Us=Object(h["createTextVNode"])("线性渐变"),Gs=Object(h["createTextVNode"])("径向渐变"),qs={key:0,class:"background-image-wrapper"},Ws={class:"background-image"},Xs={key:1,class:"background-gradient-wrapper"},Ys={class:"row"},Zs=Object(h["createVNode"])("div",{style:{flex:"2"}},"起点颜色:",-1),Js={class:"row"},Ks=Object(h["createVNode"])("div",{style:{flex:"2"}},"终点颜色:",-1),$s={key:0,class:"row"},Qs=Object(h["createVNode"])("div",{style:{flex:"2"}},"渐变角度:",-1),ef={class:"row"},tf=Object(h["createTextVNode"])("应用背景到全部"),nf=Object(h["createVNode"])("div",{class:"title"},"全局主题",-1),of={class:"row"},cf=Object(h["createVNode"])("div",{style:{flex:"2"}},"字体:",-1),af={class:"row"},rf=Object(h["createVNode"])("div",{style:{flex:"2"}},"字体颜色:",-1),lf={class:"row"},uf=Object(h["createVNode"])("div",{style:{flex:"2"}},"背景颜色:",-1),df={class:"row"},sf=Object(h["createVNode"])("div",{style:{flex:"2"}},"主题色:",-1),ff=Object(h["createVNode"])("div",{class:"title",style:{"margin-top":"20px"}},"应用预置主题:",-1),pf={class:"theme-list"},bf={class:"theme-item-content"},mf={class:"row"},vf=Object(h["createTextVNode"])("应用主题到全部");Object(h["popScopeId"])();var Of=Ls((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("SelectOption"),l=Object(h["resolveComponent"])("Select"),i=Object(h["resolveComponent"])("ColorPicker"),u=Object(h["resolveComponent"])("ColorButton"),d=Object(h["resolveComponent"])("Popover"),s=Object(h["resolveComponent"])("IconPlus"),f=Object(h["resolveComponent"])("FileInput"),p=Object(h["resolveComponent"])("Slider"),b=Object(h["resolveComponent"])("Button"),m=Object(h["resolveComponent"])("Divider"),v=Object(h["resolveComponent"])("SelectOptGroup");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Vs,[_s,Object(h["createVNode"])("div",Bs,[Object(h["createVNode"])(l,{style:{flex:"10"},value:e.background.type,onChange:t[1]||(t[1]=function(t){return e.updateBackgroundType(t)})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"solid"},{default:Ls((function(){return[Ms]})),_:1}),Object(h["createVNode"])(r,{value:"image"},{default:Ls((function(){return[Ds]})),_:1}),Object(h["createVNode"])(r,{value:"gradient"},{default:Ls((function(){return[As]})),_:1})]})),_:1},8,["value"]),Ps,"solid"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])(d,{key:0,trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.color,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.updateBackground({color:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.color||"#fff",style:{flex:"10"}},null,8,["color"])]})),_:1})):"image"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:1,style:{flex:"10"},value:e.background.size||"cover",onChange:t[3]||(t[3]=function(t){return e.updateBackground({imageSize:t})})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"initial"},{default:Ls((function(){return[Rs]})),_:1}),Object(h["createVNode"])(r,{value:"contain"},{default:Ls((function(){return[Fs]})),_:1}),Object(h["createVNode"])(r,{value:"repeat"},{default:Ls((function(){return[zs]})),_:1}),Object(h["createVNode"])(r,{value:"cover"},{default:Ls((function(){return[Hs]})),_:1})]})),_:1},8,["value"])):(Object(h["openBlock"])(),Object(h["createBlock"])(l,{key:2,style:{flex:"10"},value:e.background.gradientType,onChange:t[4]||(t[4]=function(t){return e.updateBackground({gradientType:t})})},{default:Ls((function(){return[Object(h["createVNode"])(r,{value:"linear"},{default:Ls((function(){return[Us]})),_:1}),Object(h["createVNode"])(r,{value:"radial"},{default:Ls((function(){return[Gs]})),_:1})]})),_:1},8,["value"]))]),"image"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",qs,[Object(h["createVNode"])(f,{onChange:t[5]||(t[5]=function(t){return e.uploadBackgroundImage(t)})},{default:Ls((function(){return[Object(h["createVNode"])("div",Ws,[Object(h["createVNode"])("div",{class:"content",style:{backgroundImage:"url(".concat(e.background.image,")")}},[Object(h["createVNode"])(s)],4)])]})),_:1})])):Object(h["createCommentVNode"])("",!0),"gradient"===e.background.type?(Object(h["openBlock"])(),Object(h["createBlock"])("div",Xs,[Object(h["createVNode"])("div",Ys,[Zs,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.gradientColor[0],"onUpdate:modelValue":t[6]||(t[6]=function(t){return e.updateBackground({gradientColor:[t,e.background.gradientColor[1]]})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.gradientColor[0],style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",Js,[Ks,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.background.gradientColor[1],"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.updateBackground({gradientColor:[e.background.gradientColor[0],t]})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.background.gradientColor[1],style:{flex:"3"}},null,8,["color"])]})),_:1})]),"linear"===e.background.gradientType?(Object(h["openBlock"])(),Object(h["createBlock"])("div",$s,[Qs,Object(h["createVNode"])(p,{min:0,max:360,step:15,value:e.background.gradientRotate,style:{flex:"3"},onChange:t[8]||(t[8]=function(t){return e.updateBackground({gradientRotate:t})})},null,8,["value"])])):Object(h["createCommentVNode"])("",!0)])):Object(h["createCommentVNode"])("",!0),Object(h["createVNode"])("div",ef,[Object(h["createVNode"])(b,{style:{flex:"1"},onClick:t[9]||(t[9]=function(t){return e.applyBackgroundAllSlide()})},{default:Ls((function(){return[tf]})),_:1})]),Object(h["createVNode"])(m),nf,Object(h["createVNode"])("div",of,[cf,Object(h["createVNode"])(l,{style:{flex:"3"},value:e.theme.fontName,onChange:t[10]||(t[10]=function(t){return e.updateTheme({fontName:t})})},{default:Ls((function(){return[Object(h["createVNode"])(v,{label:"系统字体"},{default:Ls((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.availableFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.en,value:e.en},{default:Ls((function(){return[Object(h["createVNode"])("span",{style:{fontFamily:e.en}},Object(h["toDisplayString"])(e.zh),5)]})),_:2},1032,["value"])})),128))]})),_:1}),Object(h["createVNode"])(v,{label:"在线字体"},{default:Ls((function(){return[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.webFonts,(function(e){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:e.name,value:e.name},{default:Ls((function(){return[Object(h["createVNode"])("span",null,Object(h["toDisplayString"])(e.name),1)]})),_:2},1032,["value"])})),128))]})),_:1})]})),_:1},8,["value"])]),Object(h["createVNode"])("div",af,[rf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.fontColor,"onUpdate:modelValue":t[11]||(t[11]=function(t){return e.updateTheme({fontColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.fontColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",lf,[uf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.backgroundColor,"onUpdate:modelValue":t[12]||(t[12]=function(t){return e.updateTheme({backgroundColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.backgroundColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),Object(h["createVNode"])("div",df,[sf,Object(h["createVNode"])(d,{trigger:"click"},{content:Ls((function(){return[Object(h["createVNode"])(i,{modelValue:e.theme.themeColor,"onUpdate:modelValue":t[13]||(t[13]=function(t){return e.updateTheme({themeColor:t})})},null,8,["modelValue"])]})),default:Ls((function(){return[Object(h["createVNode"])(u,{color:e.theme.themeColor,style:{flex:"3"}},null,8,["color"])]})),_:1})]),ff,Object(h["createVNode"])("div",pf,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.themes,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"theme-item",key:n,style:{backgroundColor:t.background},onClick:function(n){return e.updateTheme({fontColor:t.text,backgroundColor:t.background,themeColor:t.color})}},[Object(h["createVNode"])("div",bf,[Object(h["createVNode"])("div",{class:"text",style:{color:t.text}},"Aa",4),Object(h["createVNode"])("div",{class:"color-block",style:{backgroundColor:t.color}},null,4)])],12,["onClick"])})),128))]),Object(h["createVNode"])("div",mf,[Object(h["createVNode"])(b,{style:{flex:"1"},onClick:t[14]||(t[14]=function(t){return e.applyThemeAllSlide()})},{default:Ls((function(){return[vf]})),_:1})])])})),hf=[{color:"#d14424",background:"#ffffff",text:"#333"},{color:"#42464b",background:"#ffffff",text:"#333"},{color:"#5d82ba",background:"#ffffff",text:"#333"},{color:"#005a6f",background:"#ffffff",text:"#333"},{color:"#d0614c",background:"#dfb044",text:"#333"},{color:"#86a1ad",background:"#dfdbd4",text:"#333"},{color:"#697586",background:"#d5c4a4",text:"#333"},{color:"#333333",background:"#7acfa6",text:"#333"},{color:"#42464b",background:"#415065",text:"#fff"},{color:"#0c5999",background:"#35a2cd",text:"#fff"},{color:"#c49a41",background:"#8c4357",text:"#fff"},{color:"#dfaa00",background:"#2e4e7d",text:"#fff"},{color:"#d1ad88",background:"#f99070",text:"#fff"},{color:"#464d52",background:"#657984",text:"#fff"},{color:"#ffcfb6",background:"#1e4c6f",text:"#fff"},{color:"#c3a043",background:"#43292a",text:"#fff"},{color:"#ffffff",background:"#171925",text:"#fff"},{color:"#df9636",background:"#5b89a0",text:"#fff"},{color:"#b898a4",background:"#93716b",text:"#fff"},{color:"#c47a11",background:"#187db1",text:"#fff"},{color:"#333333",background:"#759564",text:"#fff"},{color:"#355b5e",background:"#424b50",text:"#fff"},{color:"#d29090",background:"#942a32",text:"#fff"},{color:"#00cfdf",background:"#3b434d",text:"#fff"},{color:"#424246",background:"#c70042",text:"#fff"},{color:"#2e4155",background:"#b35d44",text:"#fff"},{color:"#11bfce",background:"#8f98aa",text:"#fff"},{color:"#333333",background:"#549688",text:"#fff"}],jf=hf,gf=H,yf=Object(h["defineComponent"])({name:"slide-style-panel",components:{ColorButton:ui},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.theme})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["computed"])((function(){return e.state.availableFonts})),a=Object(h["computed"])((function(){return o.value.background?o.value.background:{type:"solid",value:"#fff"}})),r=ge(),l=r.addHistorySnapshot,i=function(t){if("solid"===t){var n=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"solid",color:a.value.color||"#fff"});e.commit(g.UPDATE_SLIDE,{background:n})}else if("image"===t){var o=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"image",image:a.value.image||"",imageSize:a.value.imageSize||"cover"});e.commit(g.UPDATE_SLIDE,{background:o})}else{var c=Object(P["a"])(Object(P["a"])({},a.value),{},{type:"gradient",gradientType:a.value.gradientType||"linear",gradientColor:a.value.gradientColor||["#fff","#fff"],gradientRotate:a.value.gradientRotate||0});e.commit(g.UPDATE_SLIDE,{background:c})}l()},u=function(t){e.commit(g.UPDATE_SLIDE,{background:Object(P["a"])(Object(P["a"])({},a.value),t)}),l()},d=function(e){var t=e[0];t&&ke(t).then((function(e){return u({image:e})}))},s=function(){var n=t.value.map((function(e){return Object(P["a"])(Object(P["a"])({},e),{},{background:o.value.background})}));e.commit(g.SET_SLIDES,n),l()},f=function(t){e.commit(g.SET_THEME,t)},p=function(){var o,c=JSON.parse(JSON.stringify(t.value)),a=n.value,r=a.themeColor,i=a.backgroundColor,u=a.fontColor,d=Object(me["a"])(c);try{for(d.s();!(o=d.n()).done;){var s=o.value;s.background&&"image"===s.background.type||(s.background=Object(P["a"])(Object(P["a"])({},s.background),{},{type:"solid",color:i}));var f,p=s.elements,b=Object(me["a"])(p);try{for(b.s();!(f=b.n()).done;){var m=f.value;"shape"===m.type?m.fill=r:"line"===m.type?m.color=r:"text"===m.type?m.fill&&(m.fill=r):"table"===m.type?m.theme&&(m.theme.color=r):"chart"===m.type&&(m.themeColor=r,m.gridColor=u)}}catch(cO){b.e(cO)}finally{b.f()}}}catch(cO){d.e(cO)}finally{d.f()}e.commit(g.SET_SLIDES,c),l()};return{availableFonts:c,background:a,updateBackgroundType:i,updateBackground:u,uploadBackgroundImage:d,applyBackgroundAllSlide:s,themes:jf,theme:n,webFonts:gf,updateTheme:f,applyThemeAllSlide:p}}});n("3639");yf.render=Of,yf.__scopeId="data-v-52253a56";var kf=yf,Ef=Object(h["withScopeId"])("data-v-a3bc22da");Object(h["pushScopeId"])("data-v-a3bc22da");var If={class:"slide-animation-panel"},Sf={class:"animation-pool"},Cf={class:"animation-text"},xf=Object(h["createTextVNode"])("应用到全部");Object(h["popScopeId"])();var Nf=Ef((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Button");return Object(h["openBlock"])(),Object(h["createBlock"])("div",If,[Object(h["createVNode"])("div",Sf,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.animations,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["animation-item",{active:e.currentTurningMode===t.value}],key:t.label,onClick:function(n){return e.updateTurningMode(t.value)}},[Object(h["createVNode"])("div",{class:["animation-block",t.value]},null,2),Object(h["createVNode"])("div",Cf,Object(h["toDisplayString"])(t.label),1)],10,["onClick"])})),128))]),Object(h["createVNode"])(r,{style:{width:"100%"},onClick:t[1]||(t[1]=function(t){return e.applyAllSlide()})},{default:Ef((function(){return[xf]})),_:1})])})),Tf=Object(h["defineComponent"])({name:"slide-animation-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.getters.currentSlide})),o=Object(h["computed"])((function(){return n.value.turningMode||"slideY"})),c=[{label:"无",value:"no"},{label:"淡入淡出",value:"fade"},{label:"左右推移",value:"slideX"},{label:"上下推移",value:"slideY"}],a=ge(),r=a.addHistorySnapshot,l=function(t){t!==o.value&&(e.commit(g.UPDATE_SLIDE,{turningMode:t}),r())},i=function(){var o=t.value.map((function(e){return Object(P["a"])(Object(P["a"])({},e),{},{turningMode:n.value.turningMode})}));e.commit(g.SET_SLIDES,o),r()};return{currentTurningMode:o,animations:c,updateTurningMode:l,applyAllSlide:i}}});n("3f04");Tf.render=Nf,Tf.__scopeId="data-v-a3bc22da";var wf=Tf,Lf=Object(h["withScopeId"])("data-v-1040b5b1");Object(h["pushScopeId"])("data-v-1040b5b1");var Vf={class:"multi-position-panel"},_f=Object(h["createTextVNode"])("组合"),Bf=Object(h["createTextVNode"])("取消组合");Object(h["popScopeId"])();var Mf=Lf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconAlignLeft"),l=Object(h["resolveComponent"])("Button"),i=Object(h["resolveComponent"])("Tooltip"),u=Object(h["resolveComponent"])("IconAlignVertically"),d=Object(h["resolveComponent"])("IconAlignRight"),s=Object(h["resolveComponent"])("ButtonGroup"),f=Object(h["resolveComponent"])("IconAlignTop"),p=Object(h["resolveComponent"])("IconAlignHorizontally"),b=Object(h["resolveComponent"])("IconAlignBottom"),m=Object(h["resolveComponent"])("Divider"),v=Object(h["resolveComponent"])("IconGroup"),O=Object(h["resolveComponent"])("IconUngroup");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Vf,[Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"左对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[1]||(t[1]=function(t){return e.alignActiveElement("left")})},{default:Lf((function(){return[Object(h["createVNode"])(r)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"水平居中"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[2]||(t[2]=function(t){return e.alignActiveElement("horizontal")})},{default:Lf((function(){return[Object(h["createVNode"])(u)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"右对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[3]||(t[3]=function(t){return e.alignActiveElement("right")})},{default:Lf((function(){return[Object(h["createVNode"])(d)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"上对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[4]||(t[4]=function(t){return e.alignActiveElement("top")})},{default:Lf((function(){return[Object(h["createVNode"])(f)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"垂直居中"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[5]||(t[5]=function(t){return e.alignActiveElement("vertical")})},{default:Lf((function(){return[Object(h["createVNode"])(p)]})),_:1})]})),_:1},8,["mouseEnterDelay"]),Object(h["createVNode"])(i,{mouseLeaveDelay:0,mouseEnterDelay:.5,title:"下对齐"},{default:Lf((function(){return[Object(h["createVNode"])(l,{style:{flex:"1"},onClick:t[6]||(t[6]=function(t){return e.alignActiveElement("bottom")})},{default:Lf((function(){return[Object(h["createVNode"])(b)]})),_:1})]})),_:1},8,["mouseEnterDelay"])]})),_:1}),Object(h["createVNode"])(m),Object(h["createVNode"])(s,{class:"row"},{default:Lf((function(){return[Object(h["createVNode"])(l,{disabled:!e.canCombine,onClick:t[7]||(t[7]=function(t){return e.combineElements()}),style:{flex:"1"}},{default:Lf((function(){return[Object(h["createVNode"])(v,{style:{"margin-right":"3px"}}),_f]})),_:1},8,["disabled"]),Object(h["createVNode"])(l,{disabled:e.canCombine,onClick:t[8]||(t[8]=function(t){return e.uncombineElements()}),style:{flex:"1"}},{default:Lf((function(){return[Object(h["createVNode"])(O,{style:{"margin-right":"3px"}}),Bf]})),_:1},8,["disabled"])]})),_:1})])})),Df=Object(h["defineComponent"])({name:"multi-position-panel",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.activeElementIdList})),n=Object(h["computed"])((function(){return e.getters.activeElementList})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=ge(),a=c.addHistorySnapshot,r=we(),l=r.combineElements,i=r.uncombineElements,u=Object(h["computed"])((function(){var e=n.value[0].groupId;if(!e)return!0;var t=n.value.every((function(t){return(t.groupId&&t.groupId)===e}));return!t})),d=function(c){var r,l=xt(n.value),i=l.minX,u=l.maxX,d=l.minY,s=l.maxY,f=JSON.parse(JSON.stringify(o.value.elements)),p={},b=Object(me["a"])(n.value);try{var m=function(){var e=r.value;if(e.groupId&&!p[e.groupId]){var t=n.value.filter((function(t){return t.groupId===e.groupId}));p[e.groupId]=xt(t)}};for(b.s();!(r=b.n()).done;)m()}catch(cO){b.e(cO)}finally{b.f()}if(c===ht.LEFT)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.minX-i;e.left=e.left-o}else e.left=i}));else if(c===ht.RIGHT)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.maxX-u;e.left=e.left-o}else{var c="line"===e.type?Math.max(e.start[0],e.end[0]):e.width;e.left=u-c}}));else if(c===ht.TOP)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.minY-d;e.top=e.top-o}else e.top=d}));else if(c===ht.BOTTOM)f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=n.maxY-s;e.top=e.top-o}else{var c="line"===e.type?Math.max(e.start[1],e.end[1]):e.height;e.top=s-c}}));else if(c===ht.HORIZONTAL){var v=(i+u)/2;f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=(n.maxX+n.minX)/2,c=o-v;e.left=e.left-c}else{var a="line"===e.type?Math.max(e.start[0],e.end[0]):e.width;e.left=v-a/2}}))}else if(c===ht.VERTICAL){var O=(d+s)/2;f.forEach((function(e){if(t.value.includes(e.id))if(e.groupId){var n=p[e.groupId],o=(n.maxY+n.minY)/2,c=o-O;e.top=e.top-c}else{var a="line"===e.type?Math.max(e.start[1],e.end[1]):e.height;e.top=O-a/2}}))}e.commit(g.UPDATE_SLIDE,{elements:f}),a()};return{canCombine:u,combineElements:l,uncombineElements:i,alignActiveElement:d}}});n("50dd");Df.render=Mf,Df.__scopeId="data-v-1040b5b1";var Af=Df,Pf=Object(h["defineComponent"])({name:"toolbar",setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.toolbarState})),n=[{label:"样式",value:xl.EL_STYLE},{label:"位置",value:xl.EL_POSITION},{label:"动画",value:xl.EL_ANIMATION}],o=[{label:"页面样式",value:xl.SLIDE_STYLE},{label:"切换",value:xl.SLIDE_ANIMATION},{label:"动画",value:xl.EL_ANIMATION}],c=[{label:"位置",value:xl.MULTI_POSITION},{label:"样式",value:xl.EL_STYLE}],a=function(t){e.commit(g.SET_TOOLBAR_STATE,t)},r=Object(h["computed"])((function(){return e.state.activeElementIdList})),l=Object(h["computed"])((function(){return r.value.length?r.value.length>1?c:n:o}));Object(h["watch"])(l,(function(){var n=l.value.map((function(e){return e.value}));n.includes(t.value)||e.commit(g.SET_TOOLBAR_STATE,n[0])}));var i=Object(h["computed"])((function(){var e,n=(e={},Object(C["a"])(e,xl.EL_STYLE,Gd),Object(C["a"])(e,xl.EL_POSITION,is),Object(C["a"])(e,xl.EL_ANIMATION,ws),Object(C["a"])(e,xl.SLIDE_STYLE,kf),Object(C["a"])(e,xl.SLIDE_ANIMATION,wf),Object(C["a"])(e,xl.MULTI_POSITION,Af),e);return n[t.value]||null}));return{toolbarState:t,currentTabs:l,setToolbarState:a,currentPanelComponent:i}}});n("3179");Pf.render=Cl,Pf.__scopeId="data-v-8468ba32";var Rf=Pf,Ff=Object(h["defineComponent"])({name:"editor",components:{EditorHeader:bt,Canvas:Fa,CanvasTool:Tr,Thumbnails:yl,Toolbar:Rf},setup:function(){Re(),Fe()}});n("a6cc");Ff.render=Q,Ff.__scopeId="data-v-d5c6b448";var zf=Ff,Hf=Object(h["withScopeId"])("data-v-048f6280");Object(h["pushScopeId"])("data-v-048f6280");var Uf={class:"hamster-ppt-screen"},Gf={class:"tools"};Object(h["popScopeId"])();var qf=Hf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ScreenSlide"),l=Object(h["resolveComponent"])("SlideThumbnails"),i=Object(h["resolveComponent"])("Modal"),u=Object(h["resolveComponent"])("IconLeftC"),d=Object(h["resolveComponent"])("IconRightC"),s=Object(h["resolveComponent"])("IconSearch"),f=Object(h["resolveComponent"])("WritingBoardTool"),p=Object(h["resolveComponent"])("IconWrite"),b=Object(h["resolveComponent"])("Popover"),m=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",Uf,[Object(h["withDirectives"])(Object(h["createVNode"])("div",{class:"slide-list",onMousewheel:t[1]||(t[1]=function(t){return e.mousewheelListener(t)})},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slides,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["slide-item","turning-mode-".concat(t.turningMode||"slideY"),{current:n===e.slideIndex,before:ne.slideIndex,hide:(n===e.slideIndex-1||n===e.slideIndex+1)&&t.turningMode!==e.currentSlide.turningMode}],key:t.id},[Object(h["createVNode"])("div",{class:"slide-content",style:{width:e.slideWidth+"px",height:e.slideHeight+"px"}},[Object(h["createVNode"])(r,{slide:t,scale:e.scale,animationIndex:e.animationIndex},null,8,["slide","scale","animationIndex"])],4)],2)})),128))],544),[[m,e.contextmenus]]),Object(h["createVNode"])(i,{visible:e.slideThumbnailModelVisible,"onUpdate:visible":t[2]||(t[2]=function(t){return e.slideThumbnailModelVisible=t}),footer:null,centered:"",width:1020,bodyStyle:{padding:"50px 20px 20px 20px"}},{default:Hf((function(){return[Object(h["createVNode"])(l,{turnSlideToIndex:e.turnSlideToIndex},null,8,["turnSlideToIndex"])]})),_:1},8,["visible"]),Object(h["createVNode"])("div",Gf,[Object(h["createVNode"])(u,{class:"tool-btn",onClick:t[3]||(t[3]=function(t){return e.execPrev()})}),Object(h["createVNode"])(d,{class:"tool-btn",onClick:t[4]||(t[4]=function(t){return e.execNext()})}),Object(h["createVNode"])(s,{class:"tool-btn",onClick:t[5]||(t[5]=function(t){return e.slideThumbnailModelVisible=!0})}),Object(h["createVNode"])(b,{trigger:"click",visible:e.writingBoardToolVisible,"onUpdate:visible":t[7]||(t[7]=function(t){return e.writingBoardToolVisible=t})},{content:Hf((function(){return[Object(h["createVNode"])(f,{onClose:t[6]||(t[6]=function(t){return e.writingBoardToolVisible=!1})})]})),default:Hf((function(){return[Object(h["createVNode"])(p,{class:"tool-btn"})]})),_:1},8,["visible"])])])})),Wf=Object(h["withScopeId"])("data-v-5e193d56"),Xf=Wf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ScreenElement");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-slide",style:{width:e.VIEWPORT_SIZE+"px",height:e.VIEWPORT_SIZE*e.VIEWPORT_ASPECT_RATIO+"px",transform:"scale(".concat(e.scale,")")}},[Object(h["createVNode"])("div",{class:"background",style:Object(P["a"])({},e.backgroundStyle)},null,4),(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slide.elements,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(r,{id:"screen-element-".concat(t.id),key:t.id,elementInfo:t,elementIndex:n+1,animationIndex:e.animationIndex},null,8,["id","elementInfo","elementIndex","animationIndex"])})),128))],4)}));function Yf(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-element",style:{zIndex:e.elementIndex,color:e.theme.fontColor,fontFamily:e.theme.fontName,visibility:e.needWaitAnimation?"hidden":"visible"}},[(Object(h["openBlock"])(),Object(h["createBlock"])(Object(h["resolveDynamicComponent"])(e.currentElementComponent),{elementInfo:e.elementInfo},null,8,["elementInfo"]))],4)}var Zf=Object(h["withScopeId"])("data-v-1423f8c2"),Jf=Zf((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ElementOutline"),l=Object(h["resolveComponent"])("Chart");return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"screen-element-chart",style:{top:e.elementInfo.top+"px",left:e.elementInfo.left+"px",width:e.elementInfo.width+"px",height:e.elementInfo.height+"px"}},[Object(h["createVNode"])("div",{class:"element-content",style:{backgroundColor:e.elementInfo.fill}},[Object(h["createVNode"])(r,{width:e.elementInfo.width,height:e.elementInfo.height,outline:e.elementInfo.outline},null,8,["width","height","outline"]),Object(h["createVNode"])(l,{width:e.elementInfo.width,height:e.elementInfo.height,type:e.elementInfo.chartType,data:e.elementInfo.data,options:e.elementInfo.options,themeColor:e.elementInfo.themeColor,gridColor:e.elementInfo.gridColor},null,8,["width","height","type","data","options","themeColor","gridColor"])],4)],4)})),Kf=Object(h["defineComponent"])({name:"screen-element-chart",components:{ElementOutline:To,Chart:lc},props:{elementInfo:{type:Object,required:!0}}});n("1539");Kf.render=Jf,Kf.__scopeId="data-v-1423f8c2";var $f=Kf,Qf=Object(h["defineComponent"])({name:"screen-element",props:{elementInfo:{type:Object,required:!0},elementIndex:{type:Number,required:!0},animationIndex:{type:Number,default:-1}},setup:function(e){var t=Object(h["computed"])((function(){var t,n=(t={},Object(C["a"])(t,Jt.IMAGE,Ur),Object(C["a"])(t,Jt.TEXT,Xr),Object(C["a"])(t,Jt.SHAPE,$r),Object(C["a"])(t,Jt.LINE,nl),Object(C["a"])(t,Jt.CHART,$f),Object(C["a"])(t,Jt.TABLE,ml),t);return n[e.elementInfo.type]||null})),n=X(),o=Object(h["computed"])((function(){return n.state.theme})),c=Object(h["computed"])((function(){return n.getters.currentSlide})),a=Object(h["computed"])((function(){var t=c.value.animations||[],n=t.findIndex((function(t){return t.elId===e.elementInfo.id}));return-1!==n&&n>=e.animationIndex}));return{currentElementComponent:t,needWaitAnimation:a,theme:o}}});Qf.render=Yf;var ep=Qf,tp=Object(h["defineComponent"])({name:"screen-slide",components:{ScreenElement:ep},props:{slide:{type:Object,required:!0},scale:{type:Number,required:!0},animationIndex:{type:Number,default:-1}},setup:function(e){var t=Object(h["computed"])((function(){return e.slide.background})),n=Mc(t),o=n.backgroundStyle;return{backgroundStyle:o,VIEWPORT_SIZE:Ee,VIEWPORT_ASPECT_RATIO:Ie}}});n("993a");tp.render=Xf,tp.__scopeId="data-v-5e193d56";var np=tp,op=Object(h["withScopeId"])("data-v-5b8ebe1d");Object(h["pushScopeId"])("data-v-5b8ebe1d");var cp={class:"slide-thumbnails"};Object(h["popScopeId"])();var ap=op((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("ThumbnailSlide");return Object(h["openBlock"])(),Object(h["createBlock"])("div",cp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.slides,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["thumbnail",{active:n===e.slideIndex}],key:t.id,onClick:function(t){return e.turnSlideToIndex(n)}},[Object(h["createVNode"])(r,{slide:t,size:150},null,8,["slide"])],10,["onClick"])})),128))])})),rp=Object(h["defineComponent"])({name:"slide-thumbnails",components:{ThumbnailSlide:jl},props:{turnSlideToIndex:{type:Function}},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.slideIndex}));return{slides:t,slideIndex:n}}});n("add0");rp.render=ap,rp.__scopeId="data-v-5b8ebe1d";var lp=rp,ip=Object(h["withScopeId"])("data-v-0ecab351");Object(h["pushScopeId"])("data-v-0ecab351");var up={class:"writing-board-tool"},dp={class:"tools"},sp={class:"colors"};Object(h["popScopeId"])();var fp=ip((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("WritingBoard"),l=Object(h["resolveDirective"])("contextmenu");return Object(h["openBlock"])(),Object(h["createBlock"])("div",up,[(Object(h["openBlock"])(),Object(h["createBlock"])(h["Teleport"],{to:"body"},[e.writingBoardVisible?Object(h["withDirectives"])((Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:0,ref:"writingBoardRef",color:e.writingBoardColor,model:e.writingBoardModel},null,8,["color","model"])),[[l,e.contextmenus]]):Object(h["createCommentVNode"])("",!0)])),Object(h["createVNode"])("div",dp,[Object(h["createVNode"])("div",{class:"btn",onClick:t[1]||(t[1]=function(t){return e.changePen()})},"画笔"),Object(h["createVNode"])("div",{class:"btn",onClick:t[2]||(t[2]=function(t){return e.changeEraser()})},"橡皮擦"),Object(h["createVNode"])("div",{class:"btn",onClick:t[3]||(t[3]=function(t){return e.clearCanvas()})},"擦除所有墨迹"),Object(h["createVNode"])("div",{class:"btn",onClick:t[4]||(t[4]=function(t){return e.closeWritingBoard()})},"退出画笔"),Object(h["createVNode"])("div",sp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.writingBoardColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:["color",{active:t===e.writingBoardColor}],key:t,style:{backgroundColor:t},onClick:function(n){return e.changeColor(t)}},null,14,["onClick"])})),128))])])])})),pp=Object(h["withScopeId"])("data-v-5b8a1ac6");Object(h["pushScopeId"])("data-v-5b8a1ac6");var bp={class:"writing-board",ref:"writingBoardRef"};Object(h["popScopeId"])();var mp=pp((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("IconWrite"),l=Object(h["resolveComponent"])("IconClearFormat");return Object(h["openBlock"])(),Object(h["createBlock"])("div",bp,[Object(h["createVNode"])("canvas",{class:"canvas",ref:"canvasRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMousedown(t)}),onMousemove:t[2]||(t[2]=function(t){return e.handleMousemove(t)}),onMouseup:t[3]||(t[3]=function(t){return e.handleMouseup()}),onMouseleave:t[4]||(t[4]=function(t){e.handleMouseup(),e.mouseInCanvas=!1}),onMouseenter:t[5]||(t[5]=function(t){return e.mouseInCanvas=!0})},null,544),e.mouseInCanvas&&"pen"===e.model?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:"pen",style:{left:e.mouse.x-e.penSize/2+"px",top:e.mouse.y-36+e.penSize/2+"px",color:e.color}},[Object(h["createVNode"])(r,{class:"icon",size:"36"})],4)):Object(h["createCommentVNode"])("",!0),e.mouseInCanvas&&"eraser"===e.model?(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:1,class:"eraser",style:{left:e.mouse.x-e.rubberSize/2+"px",top:e.mouse.y-e.rubberSize/2+"px",width:e.rubberSize+"px",height:e.rubberSize+"px"}},[Object(h["createVNode"])(l,{class:"icon",size:.6*e.rubberSize},null,8,["size"])],4)):Object(h["createCommentVNode"])("",!0)],512)})),vp=6,Op=80,hp=Object(h["defineComponent"])({name:"writing-board",props:{color:{type:String,default:"#ffcc00"},model:{type:String,default:"pen"}},setup:function(e){var t=null,n=Object(h["ref"])(),o=Object(h["ref"])(),c={x:0,y:0},a=!1,r=0,l=-1,i=Object(h["reactive"])({x:0,y:0}),u=Object(h["ref"])(!1),d=function(){o.value&&n.value&&(t=o.value.getContext("2d"),t&&(o.value.width=n.value.clientWidth,o.value.height=n.value.clientHeight,o.value.style.width=n.value.clientWidth+"px",o.value.style.height=n.value.clientHeight+"px",t.lineCap="round",t.lineJoin="round"))},s=function(e,t){var n=c.x,o=c.y;return Math.sqrt((e-n)*(e-n)+(t-o)*(t-o))},f=function(e,t){var n,o=10,c=.1,a=vp,r=3,i=e/t;return n=i<=c?a:i>=o?r:a-i/o*a,-1===l?n:1*n/3+2*l/3},p=function(n,o,a){if(t){var r=c.x,l=c.y;t.lineWidth=a,t.strokeStyle=e.color,t.beginPath(),t.moveTo(r,l),t.lineTo(n,o),t.stroke(),t.closePath()}},b=function(e,n){var a,r,l,i;if(t&&o.value){var u=c.x,d=c.y,s=Op/2,f=s*Math.sin(Math.atan((n-d)/(e-u))),p=s*Math.cos(Math.atan((n-d)/(e-u))),b=[u+f,d-p],m=[u-f,d+p],v=[e+f,n-p],O=[e-f,n+p];t.save(),t.beginPath(),t.arc(e,n,s,0,2*Math.PI),t.clip(),t.clearRect(0,0,o.value.width,o.value.height),t.restore(),t.save(),t.beginPath(),(a=t).moveTo.apply(a,b),(r=t).lineTo.apply(r,v),(l=t).lineTo.apply(l,O),(i=t).lineTo.apply(i,m),t.closePath(),t.clip(),t.clearRect(0,0,o.value.width,o.value.height),t.restore()}},m=function(e,t){c={x:e,y:t},r=(new Date).getTime()},v=function(t,n){var o=(new Date).getTime();if("pen"===e.model){var a=s(t,n),i=o-r,u=f(a,i);p(t,n,u),l=u}else b(t,n);c={x:t,y:n},r=(new Date).getTime()},O=function(e){a=!0,m(e.offsetX,e.offsetY)},j=function(e){i.x=e.pageX,i.y=e.pageY},g=function(e){j(e),a&&v(e.offsetX,e.offsetY)},y=function(){a&&(a=!1)},k=function(){t&&o.value&&t.clearRect(0,0,o.value.width,o.value.height)};return Object(h["onMounted"])(d),{mouse:i,mouseInCanvas:u,penSize:vp,rubberSize:Op,writingBoardRef:n,canvasRef:o,handleMousedown:O,handleMousemove:g,handleMouseup:y,clearCanvas:k}}});n("45ac");hp.render=mp,hp.__scopeId="data-v-5b8a1ac6";var jp=hp,gp=["#000000","#ffffff","#1e497b","#4e81bb","#e2534d","#9aba60","#8165a0","#47acc5","#f9974c"],yp=Object(h["defineComponent"])({name:"writing-board-tool",components:{WritingBoard:jp},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=Object(h["ref"])(!1),a=Object(h["ref"])("#e2534d"),r=Object(h["ref"])("pen"),l=function(){c.value||(c.value=!0),r.value="pen",n("close")},i=function(){r.value="eraser",n("close")},u=function(){o.value.clearCanvas(),n("close")},d=function(e){"pen"!==r.value&&(r.value="pen"),a.value=e,n("close")},s=function(){c.value=!1,n("close")},f=function(){return[{text:"画笔",handler:l,disable:"pen"===r.value},{text:"橡皮擦",handler:i,disable:"eraser"===r.value},{text:"擦除所有墨迹",handler:u},{text:"退出画笔",handler:s}]};return{writingBoardRef:o,writingBoardVisible:c,writingBoardColors:gp,writingBoardColor:a,writingBoardModel:r,changePen:l,changeEraser:i,clearCanvas:u,changeColor:d,closeWritingBoard:s,contextmenus:f}}});n("8a4a");yp.render=fp,yp.__scopeId="data-v-0ecab351";var kp=yp,Ep=Object(h["defineComponent"])({name:"screen",components:{ScreenSlide:np,SlideThumbnails:lp,WritingBoardTool:kp},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.slides})),n=Object(h["computed"])((function(){return e.state.slideIndex})),o=Object(h["computed"])((function(){return e.getters.currentSlide})),c=Object(h["ref"])(0),a=Object(h["ref"])(0),r=Object(h["computed"])((function(){return c.value/Ee})),l=Object(h["ref"])(!1),i=Object(h["ref"])(!1),u=function(){var e,t,n=document.body.clientWidth,o=document.body.clientHeight;o/n===Ie?(e=n,t=o):o/n>Ie?(e=n,t=n*Ie):(e=o/Ie,t=o),c.value=e,a.value=t},d=Ae(),s=d.exitScreening,f=function(){u(),De()||s()},p=Object(h["ref"])(0),b=Object(h["computed"])((function(){return o.value.animations||[]})),m=function(){var e="animate__",t=b.value[p.value];p.value+=1;var n=document.querySelector("#screen-element-".concat(t.elId," [class^=base-element-]"));if(n){var o="".concat(e).concat(t.type);n.classList.add("".concat(e,"animated"),o);var c=function(){n.classList.remove("".concat(e,"animated"),o)};n.addEventListener("animationend",c,{once:!0})}},v=function(){if(b.value.length&&p.value>0)p.value-=1;else if(n.value>0){e.commit(g.UPDATE_SLIDE_INDEX,n.value-1);var t=b.value?b.value.length:0;p.value=t}},O=function(){b.value.length&&p.value0&&O()}),500,{leading:!0,trailing:!1});Object(h["onMounted"])((function(){window.addEventListener("resize",f),document.addEventListener("keydown",j)})),Object(h["onUnmounted"])((function(){window.removeEventListener("resize",f),document.removeEventListener("keydown",j)}));var k=function(){e.commit(g.UPDATE_SLIDE_INDEX,n.value-1),p.value=0},E=function(){e.commit(g.UPDATE_SLIDE_INDEX,n.value+1),p.value=0},I=function(t){l.value=!1,e.commit(g.UPDATE_SLIDE_INDEX,t),p.value=0},S=function(){return[{text:"上一页",disable:n.value<=0,handler:function(){return k()}},{text:"下一页",disable:n.value>=t.value.length-1,handler:function(){return E()}},{text:"结束放映",subText:"ESC",handler:s}]};return Object(h["provide"])("slideScale",r),{slides:t,slideIndex:n,currentSlide:o,slideWidth:c,slideHeight:a,scale:r,mousewheelListener:y,animationIndex:p,contextmenus:S,execPrev:v,execNext:O,slideThumbnailModelVisible:l,turnSlideToIndex:I,writingBoardToolVisible:i}}});n("2c96");Ep.render=qf,Ep.__scopeId="data-v-048f6280";var Ip=Ep,Sp=Object(h["defineComponent"])({name:"app",components:{Editor:zf,Screen:Ip},setup:function(){var e=X(),t=Object(h["computed"])((function(){return e.state.screening}));return Object(h["onMounted"])((function(){e.commit(g.SET_AVAILABLE_FONTS),e.dispatch(y.INIT_SNAPSHOT_DATABASE)})),{screening:t}}});n("a2af");Sp.render=j;var Cp=Sp;n("793f"),n("41ed"),n("5952"),n("c860"),n("ae3f"),n("8c56"),n("77ed");function xp(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("MenuContent");return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,[Object(h["createVNode"])("div",{class:"mask",onContextmenu:t[1]||(t[1]=Object(h["withModifiers"])((function(t){return e.removeContextMenu()}),["prevent"])),onMousedown:t[2]||(t[2]=function(t){return e.removeContextMenu()})},null,32),Object(h["createVNode"])("div",{class:"contextmenu",style:{left:e.style.left,top:e.style.top},onContextmenu:t[3]||(t[3]=Object(h["withModifiers"])((function(){}),["prevent"]))},[Object(h["createVNode"])(r,{menus:e.menus,subMenuPosition:e.style.subMenuPosition,handleClickMenuItem:e.handleClickMenuItem},null,8,["menus","subMenuPosition","handleClickMenuItem"])],36)],64)}var Np=Object(h["withScopeId"])("data-v-3cad6828");Object(h["pushScopeId"])("data-v-3cad6828");var Tp={class:"menu-content"},wp={class:"text"},Lp={key:0,class:"sub-text"};Object(h["popScopeId"])();var Vp=Np((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("_self");return Object(h["openBlock"])(),Object(h["createBlock"])("ul",Tp,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.menus,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])(h["Fragment"],null,[t.hide?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])("li",{class:["menu-item",{divider:t.divider,disable:t.disable}],key:t.text||n,onClick:Object(h["withModifiers"])((function(n){return e.handleClickMenuItem(t)}),["stop"])},[t.divider?Object(h["createCommentVNode"])("",!0):(Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:0,class:["menu-item-content",{"has-sub-menu":t.children}]},[Object(h["createVNode"])("span",wp,Object(h["toDisplayString"])(t.text),1),t.subText&&!t.children?(Object(h["openBlock"])(),Object(h["createBlock"])("span",Lp,Object(h["toDisplayString"])(t.subText),1)):Object(h["createCommentVNode"])("",!0),t.children&&t.children.length?(Object(h["openBlock"])(),Object(h["createBlock"])(r,{key:1,class:"sub-menu",style:Object(C["a"])({},e.subMenuPosition,"112.5%"),menus:t.children,handleClickMenuItem:e.handleClickMenuItem},null,8,["style","menus","handleClickMenuItem"])):Object(h["createCommentVNode"])("",!0)],2))],10,["onClick"]))],64)})),256))])})),_p=Object(h["defineComponent"])({name:"menu-content",props:{menus:{type:Array,required:!0},subMenuPosition:{type:String,default:"left"},handleClickMenuItem:{type:Function,required:!0}}});n("e344");_p.render=Vp,_p.__scopeId="data-v-3cad6828";var Bp=_p,Mp=160,Dp=30,Ap=11,Pp=120,Rp=Object(h["defineComponent"])({name:"contextmenu",components:{MenuContent:Bp},props:{axis:{type:Object,required:!0},el:{type:Object,required:!0},menus:{type:Array,required:!0},removeContextMenu:{type:Function,required:!0}},setup:function(e){var t=Object(h["computed"])((function(){var t=e.axis,n=t.x,o=t.y,c=e.menus.filter((function(e){return!e.divider&&!e.hide})).length,a=e.menus.filter((function(e){return e.divider})).length,r=10,l=Mp,i=c*Dp+a*Ap+r,u=Mp+Pp-10,d=document.body.clientWidth,s=document.body.clientHeight,f=d<=n+l?n-l:n,p=s<=o+i?o-i:o,b=d<=f+u?"right":"left";return{left:f+"px",top:p+"px",subMenuPosition:b}})),n=function(t){t.disable||t.children||(t.handler&&t.handler(e.el),e.removeContextMenu())};return{style:t,handleClickMenuItem:n}}});n("1c62");Rp.render=xp;var Fp=Rp,zp="CTX_CONTEXTMENU_HANDLER",Hp=function(e,t,n){t.stopPropagation(),t.preventDefault();var o=n.value(e);if(o){var c=null,a=function t(){c&&(document.body.removeChild(c),c=null),e.classList.remove("contextmenu-active"),document.body.removeEventListener("scroll",t),window.removeEventListener("resize",t)},r={axis:{x:t.x,y:t.y},el:e,menus:o,removeContextMenu:a};c=document.createElement("div");var l=Object(h["createVNode"])(Fp,r,null);Object(h["render"])(l,c),document.body.appendChild(c),e.classList.add("contextmenu-active"),document.body.addEventListener("scroll",a),window.addEventListener("resize",a)}},Up={mounted:function(e,t){e[zp]=function(n){return Hp(e,n,t)},e.addEventListener("contextmenu",e[zp])},unmounted:function(e){e&&e[zp]&&(e.removeEventListener("contextmenu",e[zp]),delete e[zp])}},Gp=Up,qp="CTX_CLICK_OUTSIDE_HANDLER",Wp=function(e,t,n){var o=n.value,c=t.composedPath(),a=c?c.indexOf(e)<0:!e.contains(t.target);a&&o(t)},Xp={mounted:function(e,t){e[qp]=function(n){return Wp(e,n,t)},setTimeout((function(){document.addEventListener("click",e[qp])}),0)},unmounted:function(e){e[qp]&&(document.removeEventListener("click",e[qp]),delete e[qp])}},Yp=Xp,Zp=n("a3ef"),Jp=n("8331"),Kp=n("4040"),$p=n("f745"),Qp=n("5d58"),eb=n("2e2d"),tb=n("6010"),nb=n("1fcb"),ob=n("6b77"),cb=n("8db9"),ab=n("0996"),rb=n("a26d"),lb=n("1646"),ib=n("9c0a"),ub=n("622c"),db=n("e5ce"),sb=n("3f19"),fb=n("2dba"),pb=n("10de"),bb=n("fbe7"),mb=n("460f"),vb=n("cfe0"),Ob=n("84e7"),hb=n("1b42"),jb=n("b8af"),gb=n("f59e"),yb=n("bdf8"),kb=n("bf2c"),Eb=n("5168"),Ib=n("1b1c"),Sb=n("e970"),Cb=n("c53e"),xb=n("5a28"),Nb=n("23fa"),Tb=n("fd52"),wb=n("8377"),Lb=n("246f"),Vb=n("4be2"),_b=n("33a2"),Bb=n("fdbcb"),Mb=n("031f"),Db=n("d26b"),Ab=n("a17d"),Pb=n("0ad3"),Rb=n("3a3e"),Fb=n("500e"),zb=n("eac59"),Hb=n("694b"),Ub=n("e9ec"),Gb=n("ea01"),qb=n("74f3"),Wb=n("4bad"),Xb=n("e7f4"),Yb=n("eb50"),Zb=n("0be2"),Jb=n("a90c"),Kb=n("c90a"),$b=n("d41d6"),Qb=n("2c06"),em=n("a5dc"),tm=n("8678"),nm=n("d7fb"),om=n("ce42"),cm=n("7abc"),am=n("5b20"),rm=n("69de"),lm=n("d0c6"),im=n("dcc2"),um=n("5683"),dm=n("69f5"),sm=n("f1d2"),fm=n("d16b"),pm=n("a5f1"),bm=n("df0d"),mm=n("70f2"),vm=n("b7c8"),Om=n("f99d"),hm=n("40bb"),jm=n("ae33"),gm=n("8c1a"),ym=n("b7b3"),km=n("96be"),Em=n("5a69"),Im=n("f9e5"),Sm=n("bbce"),Cm=n("77ad"),xm=n("46cd"),Nm=n("c4a8"),Tm=n("3ee3"),wm=n("dde4"),Lm=n("cead"),Vm=n("a7ac"),_m=n("45b9"),Bm=n("5a81"),Mm=n("0aba"),Dm=n("fa00d"),Am=n("f3c2"),Pm=n("c8bf"),Rm=n("5294b"),Fm=n("9fbc"),zm={install:function(e){e.component("IconFontSize",Fm["a"]),e.component("IconPicture",Rm["a"]),e.component("IconPentagonOne",Pm["a"]),e.component("IconConnection",Am["a"]),e.component("IconInsertTable",Dm["a"]),e.component("IconSymbol",Mm["a"]),e.component("IconCopy",Bm["a"]),e.component("IconClipboard",_m["a"]),e.component("IconCuttingOne",Vm["a"]),e.component("IconLock",Lm["a"]),e.component("IconUnlock",wm["a"]),e.component("IconFullScreen",Tm["a"]),e.component("IconOffScreen",Nm["a"]),e.component("IconBack",xm["a"]),e.component("IconNext",Cm["a"]),e.component("IconAlignTop",Sm["a"]),e.component("IconAlignLeft",Im["a"]),e.component("IconAlignRight",Em["a"]),e.component("IconAlignBottom",km["a"]),e.component("IconAlignVertically",ym["a"]),e.component("IconAlignHorizontally",gm["a"]),e.component("IconBringToFront",jm["a"]),e.component("IconSentToBack",hm["a"]),e.component("IconBringToFrontOne",Om["a"]),e.component("IconSendToBack",vm["a"]),e.component("IconGroup",mm["a"]),e.component("IconUngroup",bm["a"]),e.component("IconFill",pm["a"]),e.component("IconBackgroundColor",fm["a"]),e.component("IconPlatte",sm["a"]),e.component("IconSplitCells",dm["a"]),e.component("IconMergeCells",um["a"]),e.component("IconTailoring",im["a"]),e.component("IconColorFilter",lm["a"]),e.component("IconFlipVertically",rm["a"]),e.component("IconFlipHorizontally",am["a"]),e.component("IconText",cm["a"]),e.component("IconAddText",om["a"]),e.component("IconAlignTextLeft",nm["a"]),e.component("IconAlignTextRight",tm["a"]),e.component("IconAlignTextCenter",em["a"]),e.component("IconRowHeight",Qb["a"]),e.component("IconFullwidth",$b["a"]),e.component("IconCode",Kb["a"]),e.component("IconTextBold",Jb["a"]),e.component("IconTextItalic",Zb["a"]),e.component("IconTextUnderline",Yb["a"]),e.component("IconStrikethrough",Xb["a"]),e.component("IconQuote",Wb["a"]),e.component("IconList",qb["a"]),e.component("IconOrderedList",Gb["a"]),e.component("IconUpOne",Ub["a"]),e.component("IconDownOne",Hb["a"]),e.component("IconFormat",zb["a"]),e.component("IconUp",Fb["a"]),e.component("IconDown",Rb["a"]),e.component("IconLeft",Pb["a"]),e.component("IconRight",Ab["a"]),e.component("IconLeftC",Db["a"]),e.component("IconRightC",Mb["a"]),e.component("IconPlus",Bb["a"]),e.component("IconMinus",_b["a"]),e.component("IconCheck",Vb["a"]),e.component("IconClose",Lb["a"]),e.component("IconCloseSmall",wb["a"]),e.component("IconChartRing",Tb["a"]),e.component("IconChartLine",Nb["a"]),e.component("IconChartHistogramOne",xb["a"]),e.component("IconChartHistogram",Cb["a"]),e.component("IconChartProportion",Sb["a"]),e.component("IconChartScatter",Ib["a"]),e.component("IconHome",Eb["a"]),e.component("IconPlayOne",kb["a"]),e.component("IconSearch",yb["a"]),e.component("IconDelete",gb["a"]),e.component("IconPpt",jb["a"]),e.component("IconSettingOne",hb["a"]),e.component("IconClear",Ob["a"]),e.component("IconLinkOne",vb["a"]),e.component("IconDrag",mb["a"]),e.component("IconHelpcenter",bb["a"]),e.component("IconEnterTheKeyboard",pb["a"]),e.component("IconFind",fb["a"]),e.component("IconFullSelection",sb["a"]),e.component("IconClearFormat",db["a"]),e.component("IconGridFour",ub["a"]),e.component("IconPageTemplate",ib["a"]),e.component("IconGithub",lb["a"]),e.component("IconMore",rb["a"]),e.component("IconWrite",ab["a"]),e.component("IconAddThree",cb["a"]),e.component("IconNewlybuild",ob["a"]),e.component("IconEffects",nb["a"]),e.component("IconRotate",tb["a"]),e.component("IconEdit",eb["a"]),e.component("IconSeoFolder",Qp["a"]),e.component("IconUndo",$p["a"]),e.component("IconTransform",Kp["a"]),e.component("IconClick",Jp["a"]),e.component("IconTheme",Zp["a"])}},Hm=Object(h["withScopeId"])("data-v-59732924"),Um=Hm((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"file-input",onClick:t[2]||(t[2]=function(t){return e.handleClick()})},[Object(h["renderSlot"])(e.$slots,"default"),Object(h["createVNode"])("input",{class:"input",type:"file",name:"upload",ref:"inputRef",accept:e.accept,onChange:t[1]||(t[1]=function(t){return e.handleChange(t)})},null,40,["accept"])])})),Gm=Object(h["defineComponent"])({name:"file-input",props:{accept:{type:String,default:"image/*"}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(),c=function(){o.value&&(o.value.value="",o.value.click())},a=function(e){var t=e.target.files;t&&n("change",t)};return{handleClick:c,handleChange:a,inputRef:o}}});n("6a17");Gm.render=Um,Gm.__scopeId="data-v-59732924";var qm=Gm,Wm={xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",version:"1.1"};function Xm(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("svg",Wm,[Object(h["renderSlot"])(e.$slots,"default")])}var Ym={name:"svg-wrapper"};Ym.render=Xm;var Zm=Ym,Jm=Object(h["withScopeId"])("data-v-7cae2b90"),Km=Jm((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("button",{class:["checkbox-button",{checked:n.checked}]},[Object(h["renderSlot"])(e.$slots,"default")],2)})),$m={name:"checkbox-button",props:{checked:{type:Boolean,default:!1}}};n("782e");$m.render=Km,$m.__scopeId="data-v-7cae2b90";var Qm=$m,ev=Object(h["withScopeId"])("data-v-7dafd0a9");Object(h["pushScopeId"])("data-v-7dafd0a9");var tv={class:"checkbox-button-group"};Object(h["popScopeId"])();var nv=ev((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",tv,[Object(h["renderSlot"])(e.$slots,"default")])})),ov={name:"checkbox-button-group"};n("69d58");ov.render=nv,ov.__scopeId="data-v-7dafd0a9";var cv=ov,av=Object(h["withScopeId"])("data-v-dc0cf132");Object(h["pushScopeId"])("data-v-dc0cf132");var rv={class:"color-picker"},lv={class:"picker-saturation-wrap"},iv={class:"picker-controls"},uv={class:"picker-color-wrap"},dv={class:"picker-sliders"},sv={class:"picker-hue-wrap"},fv={class:"picker-alpha-wrap"},pv={class:"picker-field"},bv={class:"picker-presets"},mv={class:"picker-gradient-presets"},vv={class:"picker-presets"};Object(h["popScopeId"])();var Ov=av((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Saturation"),l=Object(h["resolveComponent"])("Checkboard"),i=Object(h["resolveComponent"])("Hue"),u=Object(h["resolveComponent"])("Alpha"),d=Object(h["resolveComponent"])("EditableInput");return Object(h["openBlock"])(),Object(h["createBlock"])("div",rv,[Object(h["createVNode"])("div",lv,[Object(h["createVNode"])(r,{value:e.color,hue:e.hue,onColorChange:t[1]||(t[1]=function(t){return e.changeColor(t)})},null,8,["value","hue"])]),Object(h["createVNode"])("div",iv,[Object(h["createVNode"])("div",uv,[Object(h["createVNode"])("div",{class:"picker-current-color",style:{background:e.currentColor}},null,4),Object(h["createVNode"])(l)]),Object(h["createVNode"])("div",dv,[Object(h["createVNode"])("div",sv,[Object(h["createVNode"])(i,{value:e.color,hue:e.hue,onColorChange:t[2]||(t[2]=function(t){return e.changeColor(t)})},null,8,["value","hue"])]),Object(h["createVNode"])("div",fv,[Object(h["createVNode"])(u,{value:e.color,onColorChange:t[3]||(t[3]=function(t){return e.changeColor(t)})},null,8,["value"])])])]),Object(h["createVNode"])("div",pv,[Object(h["createVNode"])(d,{value:e.color,onColorChange:t[4]||(t[4]=function(t){return e.changeColor(t)})},null,8,["value"])]),Object(h["createVNode"])("div",bv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.themeColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-presets-color",key:t,style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))]),Object(h["createVNode"])("div",mv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.presetColors,(function(t,n){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-gradient-col",key:n},[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(t,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"picker-gradient-color",key:t,style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))])})),128))]),Object(h["createVNode"])("div",vv,[(Object(h["openBlock"])(!0),Object(h["createBlock"])(h["Fragment"],null,Object(h["renderList"])(e.standardColors,(function(t){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{key:t,class:"picker-presets-color",style:{background:t},onClick:function(n){return e.selectPresetColor(t)}},null,12,["onClick"])})),128))])])})),hv=Object(h["withScopeId"])("data-v-40ed15f5");Object(h["pushScopeId"])("data-v-40ed15f5");var jv={class:"alpha"},gv={class:"alpha-checkboard-wrap"},yv=Object(h["createVNode"])("div",{class:"alpha-picker"},null,-1);Object(h["popScopeId"])();var kv=hv((function(e,t,n,o,c,a){var r=Object(h["resolveComponent"])("Checkboard");return Object(h["openBlock"])(),Object(h["createBlock"])("div",jv,[Object(h["createVNode"])("div",gv,[Object(h["createVNode"])(r)]),Object(h["createVNode"])("div",{class:"alpha-gradient",style:{background:e.gradientColor}},null,4),Object(h["createVNode"])("div",{class:"alpha-container",ref:"alphaRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Object(h["createVNode"])("div",{class:"alpha-pointer",style:{left:100*e.color.a+"%"}},[yv],4)],544)])})),Ev=Object(h["withScopeId"])("data-v-2352ea60"),Iv=Ev((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"checkerboard",style:e.bgStyle},null,4)})),Sv={},Cv=function(e,t,n){var o=document.createElement("canvas");o.width=o.height=2*n;var c=o.getContext("2d");return c?(c.fillStyle=e,c.fillRect(0,0,o.width,o.height),c.fillStyle=t,c.fillRect(0,0,n,n),c.translate(n,n),c.fillRect(0,0,n,n),o.toDataURL()):null},xv=function(e,t,n){var o=e+","+t+","+n;if(Sv[o])return Sv[o];var c=Cv(e,t,n);return Sv[o]=c,c},Nv=Object(h["defineComponent"])({name:"checkboard",props:{size:{type:Number,default:8},white:{type:String,default:"#fff"},grey:{type:String,default:"#e6e6e6"}},setup:function(e){var t=Object(h["computed"])((function(){var t=xv(e.white,e.grey,e.size);return{backgroundImage:"url(".concat(t,")")}}));return{bgStyle:t}}});n("13cd");Nv.render=Iv,Nv.__scopeId="data-v-2352ea60";var Tv=Nv,wv=Object(h["defineComponent"])({name:"alpha",components:{Checkboard:Tv},props:{value:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){return e.value})),c=Object(h["computed"])((function(){var e=[o.value.r,o.value.g,o.value.b].join(",");return"linear-gradient(to right, rgba(".concat(e,", 0) 0%, rgba(").concat(e,", 1) 100%)")})),a=Object(h["ref"])(),r=function(e){if(e.preventDefault(),a.value){var t,c=a.value.clientWidth,r=a.value.getBoundingClientRect().left+window.pageXOffset,l=e.pageX-r;t=l<0?0:l>c?1:Math.round(100*l/c)/100,o.value.a!==t&&n("colorChange",{r:o.value.r,g:o.value.g,b:o.value.b,a:t})}},l=function e(){window.removeEventListener("mousemove",r),window.removeEventListener("mouseup",e)},i=function(e){r(e),window.addEventListener("mousemove",r),window.addEventListener("mouseup",l)};return Object(h["onUnmounted"])(l),{alphaRef:a,gradientColor:c,handleMouseDown:i,color:o}}});n("b295");wv.render=kv,wv.__scopeId="data-v-40ed15f5";var Lv=wv,Vv=Object(h["withScopeId"])("data-v-0cb6d507");Object(h["pushScopeId"])("data-v-0cb6d507");var _v={class:"hue"},Bv=Object(h["createVNode"])("div",{class:"hue-picker"},null,-1);Object(h["popScopeId"])();var Mv=Vv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",_v,[Object(h["createVNode"])("div",{class:"hue-container",ref:"hueRef",onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Object(h["createVNode"])("div",{class:"hue-pointer",style:{left:e.pointerLeft}},[Bv],4)],544)])})),Dv=Object(h["defineComponent"])({name:"hue",props:{value:{type:Object,required:!0},hue:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["ref"])(0),c=Object(h["ref"])(""),a=Object(h["computed"])((function(){var t=oc()(e.value).toHsl();return 0===t.s&&(t.h=e.hue),t})),r=Object(h["computed"])((function(){return 0===a.value.h&&"right"===c.value?"100%":100*a.value.h/360+"%"}));Object(h["watch"])((function(){return e.value}),(function(){var t=oc()(e.value).toHsl(),n=0===t.s?e.hue:t.h;0!==n&&n-o.value>0&&(c.value="right"),0!==n&&n-o.value<0&&(c.value="left"),o.value=n}));var l=Object(h["ref"])(),i=function(e){if(e.preventDefault(),l.value){var t,o,c=l.value.clientWidth,r=l.value.getBoundingClientRect().left+window.pageXOffset,i=e.pageX-r;i<0?t=0:i>c?t=360:(o=100*i/c,t=360*o/100),a.value.h!==t&&n("colorChange",{h:t,l:a.value.l,s:a.value.s,a:a.value.a})}},u=function e(){window.removeEventListener("mousemove",i),window.removeEventListener("mouseup",e)},d=function(e){i(e),window.addEventListener("mousemove",i),window.addEventListener("mouseup",u)};return Object(h["onUnmounted"])(u),{hueRef:l,handleMouseDown:d,pointerLeft:r}}});n("dc91");Dv.render=Mv,Dv.__scopeId="data-v-0cb6d507";var Av=Dv,Pv=Object(h["withScopeId"])("data-v-792755a0");Object(h["pushScopeId"])("data-v-792755a0");var Rv=Object(h["createVNode"])("div",{class:"saturation-white"},null,-1),Fv=Object(h["createVNode"])("div",{class:"saturation-black"},null,-1),zv=Object(h["createVNode"])("div",{class:"saturation-circle"},null,-1);Object(h["popScopeId"])();var Hv=Pv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",{class:"saturation",ref:"saturationRef",style:{background:e.bgColor},onMousedown:t[1]||(t[1]=function(t){return e.handleMouseDown(t)})},[Rv,Fv,Object(h["createVNode"])("div",{class:"saturation-pointer",style:{top:e.pointerTop,left:e.pointerLeft}},[zv],4)],36)})),Uv=n("f678"),Gv=n.n(Uv),qv=Object(h["defineComponent"])({name:"saturation",props:{value:{type:Object,required:!0},hue:{type:Number,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){var t=oc()(e.value).toHsv();return 0===t.s&&(t.h=e.hue),t})),c=Object(h["computed"])((function(){return"hsl(".concat(o.value.h,", 100%, 50%)")})),a=Object(h["computed"])((function(){return-100*o.value.v+1+100+"%"})),r=Object(h["computed"])((function(){return 100*o.value.s+"%"})),l=je()((function(e){n("colorChange",e)}),20,{leading:!0,trailing:!1}),i=Object(h["ref"])(),u=function(e){if(e.preventDefault(),i.value){var t=i.value.clientWidth,n=i.value.clientHeight,c=i.value.getBoundingClientRect().left+window.pageXOffset,a=i.value.getBoundingClientRect().top+window.pageYOffset,r=Gv()(e.pageX-c,0,t),u=Gv()(e.pageY-a,0,n),d=r/t,s=Gv()(-u/n+1,0,1);l({h:o.value.h,s:d,v:s,a:o.value.a})}},d=function e(){window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",e)},s=function(e){u(e),window.addEventListener("mousemove",u),window.addEventListener("mouseup",d)};return Object(h["onUnmounted"])(d),{saturationRef:i,bgColor:c,handleMouseDown:s,pointerTop:a,pointerLeft:r}}});n("97cd");qv.render=Hv,qv.__scopeId="data-v-792755a0";var Wv=qv,Xv=Object(h["withScopeId"])("data-v-67f94aae");Object(h["pushScopeId"])("data-v-67f94aae");var Yv={class:"editable-input"};Object(h["popScopeId"])();var Zv=Xv((function(e,t,n,o,c,a){return Object(h["openBlock"])(),Object(h["createBlock"])("div",Yv,[Object(h["createVNode"])("input",{class:"input-content",value:e.val,onInput:t[1]||(t[1]=function(t){return e.handleInput(t)})},null,40,["value"])])})),Jv=Object(h["defineComponent"])({name:"editable-input",props:{value:{type:Object,required:!0}},setup:function(e,t){var n=t.emit,o=Object(h["computed"])((function(){var t="";return t=e.value.a<1?oc()(e.value).toHex8String().toUpperCase():oc()(e.value).toHexString().toUpperCase(),t.replace("#","")})),c=function(e){var t=e.target.value;t.length>=6&&n("colorChange",oc()(t).toRgb())};return{val:o,handleInput:c}}});n("a73d");Jv.render=Zv,Jv.__scopeId="data-v-67f94aae";var Kv=Jv,$v=[["#7f7f7f","#f2f2f2"],["#0d0d0d","#808080"],["#1c1a10","#ddd8c3"],["#0e243d","#c6d9f0"],["#233f5e","#dae5f0"],["#632623","#f2dbdb"],["#4d602c","#eaf1de"],["#3f3150","#e6e0ec"],["#1e5867","#d9eef3"],["#99490f","#fee9da"]],Qv=function(e,t,n){for(var o=oc()(e).toRgb(),c=oc()(t).toRgb(),a=(c.r-o.r)/n,r=(c.g-o.g)/n,l=(c.b-o.b)/n,i=[],u=0;u\n \n \n\n\n\n\n","export const enum MutationTypes {\r\n\r\n // editor\r\n SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList',\r\n SET_HANDLE_ELEMENT_ID = 'setHandleElementId',\r\n SET_CANVAS_PERCENTAGE = 'setCanvasPercentage',\r\n SET_CANVAS_SCALE = 'setCanvasScale',\r\n SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus',\r\n SET_EDITORAREA_FOCUS = 'setEditorAreaFocus',\r\n SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState',\r\n SET_GRID_LINES_STATE = 'setGridLinesState',\r\n SET_CREATING_ELEMENT = 'setCreatingElement',\r\n SET_AVAILABLE_FONTS = 'setAvailableFonts',\r\n SET_TOOLBAR_STATE = 'setToolbarState',\r\n SET_CLIPING_IMAGE_ELEMENT_ID = 'setClipingImageElementId',\r\n\r\n // slides\r\n SET_THEME = 'setTheme',\r\n SET_SLIDES = 'setSlides',\r\n ADD_SLIDE = 'addSlide',\r\n UPDATE_SLIDE = 'updateSlide',\r\n DELETE_SLIDE = 'deleteSlide',\r\n UPDATE_SLIDE_INDEX = 'updateSlideIndex',\r\n ADD_ELEMENT = 'addElement',\r\n UPDATE_ELEMENT = 'updateElement',\r\n REMOVE_ELEMENT_PROPS = 'removeElementProps',\r\n\r\n // snapshot\r\n SET_SNAPSHOT_CURSOR = 'setSnapshotCursor',\r\n SET_SNAPSHOT_LENGTH = 'setSnapshotLength',\r\n\r\n // keyboard\r\n SET_CTRL_KEY_STATE = 'setCtrlKeyState',\r\n SET_SHIFT_KEY_STATE = 'setShiftKeyState',\r\n\r\n // screen\r\n SET_SCREENING = 'setScreening',\r\n}\r\n\r\nexport const enum ActionTypes {\r\n INIT_SNAPSHOT_DATABASE = 'initSnapshotDatabase',\r\n ADD_SNAPSHOT = 'addSnapshot',\r\n UN_DO = 'undo',\r\n RE_DO = 'redo',\r\n}","import { Slide } from '@/types/slides'\n\nexport const slides: Slide[] = [\n {\n id: 'xsxa123',\n elements: [\n {\n id: 'sdasaxs',\n type: 'chart',\n left: 680,\n top: 20,\n width: 300,\n height: 300,\n chartType: 'line',\n themeColor: '#d70206',\n data: {\n labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],\n series: [\n [5, 2, 4, 2, 10],\n ],\n },\n },\n {\n id: '1213asa',\n type: 'table',\n left: 20,\n top: 20,\n width: 400,\n height: 108,\n colWidths: [0.25, 0.25, 0.25, 0.25],\n outline: {\n width: 1,\n style: 'solid',\n color: '#999',\n },\n data: [\n [\n { id: '1', colspan: 1, rowspan: 1, text: '1' },\n { id: '2', colspan: 1, rowspan: 1, text: '2' },\n { id: '3', colspan: 1, rowspan: 1, text: '3' },\n { id: '4', colspan: 1, rowspan: 1, text: '4' },\n ],\n [\n { id: '6', colspan: 1, rowspan: 1, text: '6' },\n { id: '7', colspan: 1, rowspan: 1, text: '7' },\n { id: '8', colspan: 1, rowspan: 1, text: '8' },\n { id: '9', colspan: 1, rowspan: 1, text: '9' },\n ],\n [\n { id: '11', colspan: 1, rowspan: 1, text: '11' },\n { id: '12', colspan: 1, rowspan: 1, text: '12' },\n { id: '13', colspan: 1, rowspan: 1, text: '13' },\n { id: '14', colspan: 1, rowspan: 1, text: '14' },\n ],\n ],\n },\n ],\n },\n {\n id: 'xxx1',\n background: {\n type: 'solid',\n color: '#fff',\n },\n elements: [\n {\n id: 'xxx1',\n type: 'text',\n left: 190,\n top: 50,\n width: 320,\n height: 104,\n rotate: 0,\n shadow: {\n h: 1,\n v: 1,\n blur: 3,\n color: 'rgba(10, 10, 10, .5)'\n },\n opacity: 1,\n lock: false,\n content: '

一段测试文字,字号固定为28px

',\n },\n {\n id: 'xxx3',\n type: 'image',\n left: 80,\n top: 250,\n width: 180,\n height: 180,\n rotate: 0,\n outline: {\n width: 4,\n style: 'solid',\n color: '#333'\n },\n clip: {\n range: [[30, 0], [100, 70]],\n shape: 'ellipse'\n },\n fixedRatio: false,\n lock: false,\n src: 'https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/1573622467064v2-7aa3ce420052983d91c6d01b47a7441d_hd.jpg',\n },\n {\n id: 'xxx2',\n type: 'image',\n left: 750,\n top: 320,\n width: 150,\n height: 150,\n rotate: 0,\n fixedRatio: true,\n lock: false,\n src: 'https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/62d9adb3-e7a6-4dc4-a352-095cffb49f08/b1be1a2f-f893-47d3-a8a3-eac7d04d395f/1596159381259v2-b2c69096d25ae16bf6ca09e30add3e65_hd.jpg',\n },\n ],\n animations: [\n {\n elId: 'xxx1',\n type: 'rotateIn',\n duration: 1000,\n },\n {\n elId: 'xxx2',\n type: 'zoomIn',\n duration: 1000,\n },\n ],\n },\n {\n id: 'sajd172',\n elements: [\n {\n id: 'yyx1',\n type: 'text',\n left: 590,\n top: 90,\n width: 220,\n height: 188,\n rotate: 0,\n opacity: 1,\n lock: false,\n content: '
😀 😐 😶 😜 🔔 ⭐ ⚡ 🔥 👍 💡 🔰 🎀 🎁 🥇 🏅 🏆 🎈 🎉 💎 🚧 ⛔ 📢 ⌛ ⏰ 🕒 🧩 🎵 📎 🔒 🔑 ⛳ 📌 📍 💬 📅 📈 📋 📜 📁 📱 💻 💾 🌏 🚚 🚡 🚢💧 🌐 🧭 💰 💳 🛒
',\n },\n {\n id: 'xsfdas',\n type: 'line',\n width: 2,\n left: 100,\n top: 400,\n end: [0, 0],\n start: [300, 120],\n style: 'solid',\n color: '#888',\n points: ['', 'arrow'],\n },\n {\n id: 'xxx7',\n type: 'shape',\n left: 130,\n top: 50,\n width: 150,\n height: 150,\n rotate: 0,\n fill: '#eebc29',\n opacity: 0.9,\n fixedRatio: false,\n lock: false,\n viewBox: 1024,\n path: 'M721.35111111 475.59111111H302.64888889c-5.00622222 0-9.10222222 4.096-9.10222222 9.10222222v54.61333334c0 5.00622222 4.096 9.10222222 9.10222222 9.10222222h418.70222222c5.00622222 0 9.10222222-4.096 9.10222222-9.10222222v-54.61333334c0-5.00622222-4.096-9.10222222-9.10222222-9.10222222z M512 2.27555555C230.51377778 2.27555555 2.27555555 230.51377778 2.27555555 512s228.23822222 509.72444445 509.72444445 509.72444445 509.72444445-228.23822222 509.72444445-509.72444445S793.48622222 2.27555555 512 2.27555555z m0 932.97777778c-233.69955555 0-423.25333333-189.55377778-423.25333333-423.25333333s189.55377778-423.25333333 423.25333333-423.25333333 423.25333333 189.55377778 423.25333333 423.25333333-189.55377778 423.25333333-423.25333333 423.25333333z',\n }\n ],\n animations: [\n {\n elId: 'yyx1',\n type: 'flipInX',\n duration: 1000,\n },\n ],\n },\n]","import { Slide, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { ToolbarState } from '@/types/toolbar'\r\nimport { slides } from '@/mocks/index'\r\nimport { SYS_FONTS } from '@/configs/font'\r\n\r\nexport interface State {\r\n activeElementIdList: string[];\r\n handleElementId: string;\r\n canvasPercentage: number;\r\n canvasScale: number;\r\n thumbnailsFocus: boolean;\r\n editorAreaFocus: boolean;\r\n disableHotkeys: boolean;\r\n showGridLines: boolean;\r\n creatingElement: CreatingElement | null;\r\n availableFonts: typeof SYS_FONTS;\r\n toolbarState: ToolbarState;\r\n theme: SlideTheme;\r\n slides: Slide[];\r\n slideIndex: number;\r\n snapshotCursor: number;\r\n snapshotLength: number;\r\n ctrlKeyState: boolean;\r\n shiftKeyState: boolean;\r\n screening: boolean;\r\n clipingImageElementId: string;\r\n}\r\n\r\nexport const state: State = {\r\n activeElementIdList: [],\r\n handleElementId: '',\r\n canvasPercentage: 90,\r\n canvasScale: 1,\r\n thumbnailsFocus: false,\r\n editorAreaFocus: false,\r\n disableHotkeys: false,\r\n showGridLines: false,\r\n creatingElement: null,\r\n availableFonts: [],\r\n toolbarState: 'slideStyle',\r\n theme: {\r\n themeColor: '#d14424',\r\n fontColor: '#333',\r\n fontName: '微软雅黑',\r\n backgroundColor: '#fff',\r\n },\r\n slides: slides,\r\n slideIndex: 0,\r\n snapshotCursor: -1,\r\n snapshotLength: 0,\r\n ctrlKeyState: false,\r\n shiftKeyState: false,\r\n screening: false,\r\n clipingImageElementId: '',\r\n}","import { GetterTree } from 'vuex'\r\nimport { State } from './state'\r\n\r\nexport const getters: GetterTree = {\r\n currentSlide(state) {\r\n return state.slides[state.slideIndex] || null\r\n },\r\n\r\n currentSlideAnimations(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide) return null\r\n const animations = currentSlide.animations\r\n if(!animations) return null\r\n\r\n const els = currentSlide.elements\r\n const elIds = els.map(el => el.id)\r\n return animations.filter(animation => elIds.includes(animation.elId))\r\n },\r\n\r\n activeElementList(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide || !currentSlide.elements) return []\r\n return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))\r\n },\r\n\r\n handleElement(state) {\r\n const currentSlide = state.slides[state.slideIndex]\r\n if(!currentSlide || !currentSlide.elements) return null\r\n return currentSlide.elements.find(element => state.handleElementId === element.id) || null\r\n },\r\n\r\n canUndo(state) {\r\n return state.snapshotCursor > 0\r\n },\r\n\r\n canRedo(state) {\r\n return state.snapshotCursor < state.snapshotLength - 1\r\n },\r\n\r\n ctrlOrShiftKeyActive(state) {\r\n return state.ctrlKeyState || state.shiftKeyState\r\n },\r\n}","import Dexie from 'dexie'\nimport { Slide } from '@/types/slides'\n\nexport interface Snapshot {\n index: number;\n slides: Slide[];\n}\n\nclass SnapshotDatabase extends Dexie {\n public snapshots: Dexie.Table\n\n public constructor() {\n super('SnapshotDatabase')\n this.version(1).stores({\n snapshots: '++id'\n })\n this.snapshots = this.table('snapshots')\n }\n}\n\nexport default new SnapshotDatabase()","import { ActionTree } from 'vuex'\nimport { IndexableTypeArray } from 'dexie'\nimport { State } from './state'\nimport { ActionTypes, MutationTypes } from './constants'\nimport db, { Snapshot } from '@/utils/database'\n\nexport const actions: ActionTree = {\n async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit, state }) {\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const lastSnapshot = snapshots.slice(-1)[0]\n\n if(lastSnapshot) {\n db.snapshots.clear()\n }\n\n const newFirstSnapshot = {\n index: state.slideIndex,\n slides: state.slides,\n }\n await db.snapshots.add(newFirstSnapshot)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, 0)\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, 1)\n },\n\n async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {\n const allKeys = await db.snapshots.orderBy('id').keys()\n\n let needDeleteKeys: IndexableTypeArray = []\n\n if(state.snapshotCursor >= 0 && state.snapshotCursor < allKeys.length - 1) {\n needDeleteKeys = allKeys.slice(state.snapshotCursor + 1)\n }\n\n const snapshot = {\n index: state.slideIndex,\n slides: state.slides,\n }\n await db.snapshots.add(snapshot)\n\n let snapshotLength = allKeys.length - needDeleteKeys.length + 1\n\n if(snapshotLength > 20) {\n needDeleteKeys.push(allKeys[0])\n snapshotLength--\n }\n if(snapshotLength >= 2) {\n db.snapshots.update(allKeys[snapshotLength - 2] as number, { index: state.slideIndex })\n }\n\n await db.snapshots.bulkDelete(needDeleteKeys)\n\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotLength - 1)\n commit(MutationTypes.SET_SNAPSHOT_LENGTH, snapshotLength)\n },\n\n async [ActionTypes.UN_DO]({ state, commit }) {\n if(state.snapshotCursor <= 0) return\n\n const snapshotCursor = state.snapshotCursor - 1\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const snapshot = snapshots[snapshotCursor]\n const { index, slides } = snapshot\n\n commit(MutationTypes.SET_SLIDES, slides)\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n },\n\n async [ActionTypes.RE_DO]({ state, commit }) {\n if(state.snapshotCursor >= state.snapshotLength - 1) return\n\n const snapshotCursor = state.snapshotCursor + 1\n const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()\n const snapshot = snapshots[snapshotCursor]\n const { index, slides } = snapshot\n\n commit(MutationTypes.SET_SLIDES, slides)\n commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)\n commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n },\n}","export const SYS_FONTS = [\n { zh: '微软雅黑', en: 'Microsoft Yahei' },\n { zh: '宋体', en: 'SimSun' },\n { zh: '黑体', en: 'SimHei' },\n { zh: '楷体', en: 'KaiTi' },\n { zh: '新宋体', en: 'NSimSun' },\n { zh: '仿宋', en: 'FangSong' },\n { zh: '苹方', en: 'PingFang SC' },\n { zh: '华文黑体', en: 'STHeiti' },\n { zh: '华文楷体', en: 'STKaiti' },\n { zh: '华文宋体', en: 'STSong' },\n { zh: '华文仿宋', en: 'STFangSong' },\n { zh: '华文中宋', en: 'STZhongSong' },\n { zh: '华文琥珀', en: 'STHupo' },\n { zh: '华文新魏', en: 'STXinwei' },\n { zh: '华文隶书', en: 'STLiti' },\n { zh: '华文行楷', en: 'STXingkai' },\n { zh: '冬青黑体简', en: 'Hiragino Sans GB' },\n { zh: '兰亭黑-简', en: 'Lantinghei SC' },\n { zh: '偏偏体-简', en: 'Hanzipen SC' },\n { zh: '手札体-简', en: 'Hannotate SC' },\n { zh: '宋体-简', en: 'Songti SC' },\n { zh: '娃娃体-简', en: 'Wawati SC' },\n { zh: '行楷-简', en: 'Xingkai SC' },\n { zh: '圆体-简', en: 'Yuanti SC' },\n { zh: '华文细黑', en: 'STXihei' },\n { zh: '幼圆', en: 'YouYuan' },\n { zh: '隶书', en: 'LiSu' },\n { zh: 'Arial', en: 'Arial' },\n]\n\nexport const WEB_FONTS = [\n { name: '仓耳小丸子' },\n { name: '优设标题黑' },\n { name: '峰广明锐体' },\n { name: '摄图摩登小方体' },\n { name: '站酷快乐体' },\n { name: '站酷酷黑体' },\n { name: '素材集市康康体' },\n { name: '联盟起艺卢帅正锐黑体' },\n { name: '谦度手写楷体' },\n { name: '途牛类圆体' },\n { name: '锐字真言体' },\n { name: '问藏书房' },\n]","// 判断用户的操作系统是否安装了某字体\nexport const isSupportFontFamily = (fontFamily: string) => {\n if(typeof fontFamily !== 'string') return false\n const arial = 'Arial'\n if(fontFamily.toLowerCase() === arial.toLowerCase()) return true\n const a = 'a'\n const size = 100\n const width = 100\n const height = 100\n\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n\n if(!ctx) return false\n\n canvas.width = width\n canvas.height = height\n ctx.textAlign = 'center'\n ctx.fillStyle = 'black'\n ctx.textBaseline = 'middle'\n\n const getDotArray = (_fontFamily: string) => {\n ctx.clearRect(0, 0, width, height)\n ctx.font = `${size}px ${_fontFamily}, ${arial}`\n ctx.fillText(a, width / 2, height / 2)\n const imageData = ctx.getImageData(0, 0, width, height).data\n return [].slice.call(imageData).filter(item => item !== 0)\n }\n\n return getDotArray(arial).join('') !== getDotArray(fontFamily).join('')\n}","import { MutationTree } from 'vuex'\r\nimport omit from 'lodash/omit'\r\nimport { MutationTypes } from './constants'\r\nimport { State } from './state'\r\nimport { Slide, PPTElement, SlideTheme } from '@/types/slides'\r\nimport { CreatingElement } from '@/types/edit'\r\nimport { SYS_FONTS } from '@/configs/font'\r\nimport { isSupportFontFamily } from '@/utils/fontFamily'\r\n\r\ninterface RemoveElementPropData {\r\n id: string;\r\n propName: string | string[];\r\n}\r\n\r\ninterface UpdateElementData {\r\n id: string | string[];\r\n props: Partial;\r\n}\r\n\r\nexport const mutations: MutationTree = {\r\n\r\n // editor\r\n\r\n [MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST](state, activeElementIdList: string[]) {\r\n if(activeElementIdList.length === 1) state.handleElementId = activeElementIdList[0]\r\n else state.handleElementId = ''\r\n \r\n state.activeElementIdList = activeElementIdList\r\n },\r\n \r\n [MutationTypes.SET_HANDLE_ELEMENT_ID](state, handleElementId: string) {\r\n state.handleElementId = handleElementId\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_PERCENTAGE](state, percentage: number) {\r\n state.canvasPercentage = percentage\r\n },\r\n\r\n [MutationTypes.SET_CANVAS_SCALE](state, scale: number) {\r\n state.canvasScale = scale\r\n },\r\n\r\n [MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) {\r\n state.thumbnailsFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_EDITORAREA_FOCUS](state, isFocus: boolean) {\r\n state.editorAreaFocus = isFocus\r\n },\r\n\r\n [MutationTypes.SET_DISABLE_HOTKEYS_STATE](state, disable: boolean) {\r\n state.disableHotkeys = disable\r\n },\r\n\r\n [MutationTypes.SET_GRID_LINES_STATE](state, show: boolean) {\r\n state.showGridLines = show\r\n },\r\n\r\n [MutationTypes.SET_CREATING_ELEMENT](state, element: CreatingElement | null) {\r\n state.creatingElement = element\r\n },\r\n\r\n [MutationTypes.SET_AVAILABLE_FONTS](state) {\r\n state.availableFonts = SYS_FONTS.filter(font => isSupportFontFamily(font.en))\r\n },\r\n\r\n [MutationTypes.SET_TOOLBAR_STATE](state, type) {\r\n state.toolbarState = type\r\n },\r\n\r\n [MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID](state, elId) {\r\n state.clipingImageElementId = elId\r\n },\r\n\r\n // slides\r\n\r\n [MutationTypes.SET_THEME](state, themeProps: Partial) {\r\n state.theme = { ...state.theme, ...themeProps }\r\n },\r\n\r\n [MutationTypes.SET_SLIDES](state, slides: Slide[]) {\r\n state.slides = slides\r\n },\r\n\r\n [MutationTypes.ADD_SLIDE](state, slide: Slide) {\r\n const addIndex = state.slideIndex + 1\r\n state.slides.splice(addIndex, 0, slide)\r\n state.slideIndex = addIndex\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE](state, props: Partial) {\r\n const slideIndex = state.slideIndex\r\n state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }\r\n },\r\n\r\n [MutationTypes.DELETE_SLIDE](state, slideId: string) {\r\n const deleteIndex = state.slides.findIndex(item => item.id === slideId)\r\n\r\n if(deleteIndex === state.slides.length - 1) {\r\n state.slideIndex = deleteIndex - 1\r\n }\r\n state.slides.splice(deleteIndex, 1)\r\n },\r\n\r\n [MutationTypes.UPDATE_SLIDE_INDEX](state, index: number) {\r\n state.slideIndex = index\r\n },\r\n\r\n [MutationTypes.ADD_ELEMENT](state, element: PPTElement | PPTElement[]) {\r\n const elements = Array.isArray(element) ? element : [element]\r\n const currentSlideEls = state.slides[state.slideIndex].elements\r\n const newEls = [...currentSlideEls, ...elements]\r\n state.slides[state.slideIndex].elements = newEls\r\n },\r\n\r\n [MutationTypes.UPDATE_ELEMENT](state, data: UpdateElementData) {\r\n const { id, props } = data\r\n const elIdList = typeof id === 'string' ? [id] : id\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return elIdList.includes(el.id) ? { ...el, ...props } : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n [MutationTypes.REMOVE_ELEMENT_PROPS](state, data: RemoveElementPropData) {\r\n const { id, propName } = data\r\n const propsNames = typeof propName === 'string' ? [propName] : propName\r\n\r\n const slideIndex = state.slideIndex\r\n const slide = state.slides[slideIndex]\r\n const elements = slide.elements.map(el => {\r\n return el.id === id ? omit(el, propsNames) : el\r\n })\r\n state.slides[slideIndex].elements = (elements as PPTElement[])\r\n },\r\n\r\n // snapshot\r\n\r\n [MutationTypes.SET_SNAPSHOT_CURSOR](state, cursor: number) {\r\n state.snapshotCursor = cursor\r\n },\r\n\r\n [MutationTypes.SET_SNAPSHOT_LENGTH](state, length: number) {\r\n state.snapshotLength = length\r\n },\r\n\r\n // keyboard\r\n\r\n [MutationTypes.SET_CTRL_KEY_STATE](state, isActive: boolean) {\r\n state.ctrlKeyState = isActive\r\n },\r\n [MutationTypes.SET_SHIFT_KEY_STATE](state, isActive: boolean) {\r\n state.shiftKeyState = isActive\r\n },\r\n\r\n // screen\r\n\r\n [MutationTypes.SET_SCREENING](state, screening) {\r\n state.screening = screening\r\n },\r\n}","import { InjectionKey } from 'vue'\nimport { createStore, Store, useStore as baseUseStore } from 'vuex'\nimport { state, State } from './state'\nimport { getters } from './getters'\nimport { actions } from './actions'\nimport { mutations } from './mutations'\nimport { MutationTypes, ActionTypes } from './constants'\n\nexport { MutationTypes, ActionTypes }\n\nexport const key: InjectionKey> = Symbol()\n\nexport const store = createStore({\n state,\n getters,\n mutations,\n actions,\n})\n\nexport const useStore = () => baseUseStore(key)","\n\n\n\n","export const enum KEYS {\n C = 'C',\n X = 'X',\n Z = 'Z',\n Y = 'Y',\n A = 'A',\n G = 'G',\n L = 'L',\n F = 'F',\n D = 'D',\n MINUS = '-',\n EQUAL = '=',\n DIGIT_0 = '0',\n DELETE = 'DELETE',\n UP = 'ARROWUP',\n DOWN = 'ARROWDOWN',\n LEFT = 'ARROWLEFT',\n RIGHT = 'ARROWRIGHT',\n ENTER = 'ENTER',\n SPACE = ' ',\n TAB = 'TAB',\n}","import padStart from 'lodash/padStart'\n\n// 生成随机码\nexport const createRandomCode = (len = 6) => {\n const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`\n const maxLen = charset.length\n let ret = ''\n for(let i = 0; i < len; i++) {\n const randomIndex = Math.floor(Math.random() * maxLen)\n ret += charset[randomIndex]\n }\n return ret\n}\n\n// 数字补足位数,例如将6补足3位 -> 003\nexport const fillDigit = (digit: number, len: number) => {\n return padStart('' + digit, len, '0')\n}","import Clipboard from 'clipboard'\n\n// 复制文本到剪贴板\nexport const copyText = (text: string) => {\n return new Promise((resolve, reject) => {\n const fakeElement = document.createElement('button')\n const clipboard = new Clipboard(fakeElement, {\n text: () => text,\n action: () => 'copy',\n container: document.body,\n })\n clipboard.on('success', e => {\n clipboard.destroy()\n resolve(e)\n })\n clipboard.on('error', e => {\n clipboard.destroy()\n reject(e)\n })\n document.body.appendChild(fakeElement)\n fakeElement.click()\n document.body.removeChild(fakeElement)\n })\n}\n\n// 读取剪贴板\nexport const readClipboard = (): Promise => {\n return new Promise((resolve, reject) => {\n if(navigator.clipboard) {\n navigator.clipboard.readText().then(text => {\n if(!text) reject('剪贴板为空或者不包含文本')\n return resolve(text)\n })\n }\n else reject('浏览器不支持或禁止访问剪贴板')\n })\n}","import CryptoJS from 'crypto-js'\n\nconst CRYPTO_KEY = 'pptist'\n\n// 加密函数\nexport const encrypt = (msg: string) => {\n return CryptoJS.AES.encrypt(msg, CRYPTO_KEY).toString()\n}\n\n// 解密函数\nexport const decrypt = (ciphertext: string) => {\n const bytes = CryptoJS.AES.decrypt(ciphertext, CRYPTO_KEY)\n return bytes.toString(CryptoJS.enc.Utf8)\n}","import debounce from 'lodash/debounce'\nimport throttle from 'lodash/throttle'\nimport { ActionTypes, useStore } from '@/store'\n\nexport default () => {\n const store = useStore()\n\n const addHistorySnapshot = debounce(function() {\n store.dispatch(ActionTypes.ADD_SNAPSHOT)\n }, 300, { trailing: true })\n\n const redo = throttle(function() {\n store.dispatch(ActionTypes.RE_DO)\n }, 100, { leading: true, trailing: false })\n\n const undo = throttle(function() {\n store.dispatch(ActionTypes.UN_DO)\n }, 100, { leading: true, trailing: false })\n\n return {\n addHistorySnapshot,\n redo,\n undo,\n }\n}","interface ImageSize {\n width: number;\n height: number;\n}\n\n// 获取图片的原始宽高\nexport const getImageSize = (src: string): Promise => {\n return new Promise(resolve => {\n const img = document.createElement('img')\n img.src = src\n img.style.opacity = '0'\n document.body.appendChild(img)\n\n img.onload = () => {\n const imgWidth = img.clientWidth\n const imgHeight = img.clientHeight\n \n img.onload = null\n img.onerror = null\n\n document.body.removeChild(img)\n\n resolve({ width: imgWidth, height: imgHeight })\n }\n\n img.onerror = () => {\n img.onload = null\n img.onerror = null\n }\n })\n}\n\n// 获取图片文件的dataURL\nexport const getImageDataURL = (file: File): Promise => {\n return new Promise(resolve => {\n const reader = new FileReader()\n reader.addEventListener('load', () => {\n resolve(reader.result as string)\n })\n reader.readAsDataURL(file)\n })\n}","export const VIEWPORT_SIZE = 1000\r\nexport const VIEWPORT_ASPECT_RATIO = 0.5625","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { createRandomCode } from '@/utils/common'\nimport { getImageSize } from '@/utils/image'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { ChartType, PPTElement, TableCell } from '@/types/slides'\nimport { ShapePoolItem } from '@/configs/shapes'\nimport { LinePoolItem } from '@/configs/lines'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\ninterface CommonElementPosition {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\ninterface LineElementPosition {\n top: number;\n left: number;\n start: [number, number];\n end: [number, number];\n}\n\nexport default () => {\n const store = useStore()\n const themeColor = computed(() => store.state.theme.themeColor)\n const fontColor = computed(() => store.state.theme.fontColor)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const createElement = (element: PPTElement) => {\n store.commit(MutationTypes.ADD_ELEMENT, element)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.id])\n addHistorySnapshot()\n }\n\n const createImageElement = (src: string) => {\n getImageSize(src).then(({ width, height }) => {\n const scale = height / width\n \n if(scale < VIEWPORT_ASPECT_RATIO && width > VIEWPORT_SIZE) {\n width = VIEWPORT_SIZE\n height = width * scale\n }\n else if(height > VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO) {\n height = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n width = height / scale\n }\n\n createElement({\n type: 'image',\n id: createRandomCode(),\n src,\n width,\n height,\n left: (VIEWPORT_SIZE - width) / 2,\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\n fixedRatio: true,\n })\n })\n }\n \n const createChartElement = (chartType: ChartType) => {\n createElement({\n type: 'chart',\n id: createRandomCode(),\n chartType,\n left: 300,\n top: 81.25,\n width: 400,\n height: 400,\n themeColor: themeColor.value,\n gridColor: fontColor.value,\n data: {\n labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],\n series: [\n [12, 19, 5, 2, 18],\n ],\n },\n })\n }\n \n const createTableElement = (row: number, col: number) => {\n const rowCells: TableCell[] = new Array(col).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n const data: TableCell[][] = new Array(row).fill(rowCells)\n\n const DEFAULT_CELL_WIDTH = 100\n const DEFAULT_CELL_HEIGHT = 36\n\n const colWidths: number[] = new Array(col).fill(1 / col)\n\n const width = col * DEFAULT_CELL_WIDTH\n const height = row * DEFAULT_CELL_HEIGHT\n\n createElement({\n type: 'table',\n id: createRandomCode(),\n width,\n height,\n colWidths,\n data,\n left: (VIEWPORT_SIZE - width) / 2,\n top: (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO - height) / 2,\n outline: {\n width: 2,\n style: 'solid',\n color: '#eeece1',\n },\n theme: {\n color: themeColor.value,\n rowHeader: true,\n rowFooter: false,\n colHeader: false,\n colFooter: false,\n },\n })\n }\n \n const createTextElement = (position: CommonElementPosition, content = '请输入内容') => {\n const { left, top, width, height } = position\n createElement({\n type: 'text',\n id: createRandomCode(),\n left, \n top, \n width, \n height,\n content,\n })\n }\n \n const createShapeElement = (position: CommonElementPosition, data: ShapePoolItem) => {\n const { left, top, width, height } = position\n createElement({\n type: 'shape',\n id: createRandomCode(),\n left, \n top, \n width, \n height,\n viewBox: data.viewBox,\n path: data.path,\n fill: themeColor.value,\n fixedRatio: false,\n })\n }\n \n const createLineElement = (position: LineElementPosition, data: LinePoolItem) => {\n const { left, top, start, end } = position\n createElement({\n type: 'line',\n id: createRandomCode(),\n left, \n top, \n start,\n end,\n points: data.points,\n color: themeColor.value,\n style: 'solid',\n width: 2,\n })\n }\n\n return {\n createImageElement,\n createChartElement,\n createTableElement,\n createTextElement,\n createShapeElement,\n createLineElement,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { decrypt } from '@/utils/crypto'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCreateElement from '@/hooks/useCreateElement'\n\ninterface PasteTextClipboardDataOptions {\n onlySlide?: boolean;\n onlyElements?: boolean;\n}\n\nexport default () => {\n const store = useStore()\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n const { createTextElement } = useCreateElement()\n\n const pasteElement = (elements: PPTElement[]) => {\n const groupIdMap = {}\n const elIdMap = {}\n for(const element of elements) {\n const groupId = element.groupId\n if(groupId && !groupIdMap[groupId]) {\n groupIdMap[groupId] = createRandomCode()\n }\n elIdMap[element.id] = createRandomCode()\n }\n const currentSlideElementIdList = currentSlide.value.elements.map(el => el.id)\n \n for(const element of elements) {\n const inCurrentSlide = currentSlideElementIdList.includes(element.id)\n \n element.id = elIdMap[element.id]\n\n if(inCurrentSlide) {\n element.left = element.left + 10\n element.top = element.top + 10\n }\n\n if(element.groupId) element.groupId = groupIdMap[element.groupId]\n }\n store.commit(MutationTypes.ADD_ELEMENT, elements)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))\n addHistorySnapshot()\n }\n\n const pasteSlide = (slide: Slide) => {\n store.commit(MutationTypes.ADD_SLIDE, slide)\n addHistorySnapshot()\n }\n\n const pasteText = (text: string) => {\n createTextElement({\n left: 0,\n top: 0,\n width: 600,\n height: 50,\n }, text)\n }\n\n const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {\n const onlySlide = options?.onlySlide || false\n const onlyElements = options?.onlyElements || false\n\n let clipboardData\n try {\n clipboardData = JSON.parse(decrypt(text))\n }\n catch {\n clipboardData = text\n }\n\n // 粘贴自定义元素或页面\n if(typeof clipboardData === 'object') {\n const { type, data } = clipboardData\n\n if(type === 'elements' && !onlySlide) pasteElement(data)\n else if(type === 'slide' && !onlyElements) pasteSlide(data)\n }\n\n // 粘贴普通文本\n else if(!onlyElements && !onlySlide) pasteText(clipboardData)\n }\n\n return {\n pasteTextClipboardData,\n }\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { createRandomCode } from '@/utils/common'\r\nimport { copyText, readClipboard } from '@/utils/clipboard'\r\nimport { encrypt } from '@/utils/crypto'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport { message } from 'ant-design-vue'\r\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const slideIndex = computed(() => store.state.slideIndex)\r\n const theme = computed(() => store.state.theme)\r\n const slidesLength = computed(() => store.state.slides.length)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const { pasteTextClipboardData } = usePasteTextClipboardData()\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const updateSlideIndex = (command: string) => {\r\n let targetIndex = 0\r\n if(command === KEYS.UP && slideIndex.value > 0) {\r\n targetIndex = slideIndex.value - 1\r\n }\r\n else if(command === KEYS.DOWN && slideIndex.value < slidesLength.value - 1) {\r\n targetIndex = slideIndex.value + 1\r\n }\r\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)\r\n }\r\n\r\n const copySlide = () => {\r\n const text = encrypt(JSON.stringify({\r\n type: 'slide',\r\n data: currentSlide.value,\r\n }))\r\n\r\n copyText(text).then(() => {\r\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, true)\r\n })\r\n }\r\n\r\n const pasteSlide = () => {\r\n readClipboard().then(text => {\r\n pasteTextClipboardData(text, { onlySlide: true })\r\n }).catch(err => message.warning(err))\r\n }\r\n\r\n const createSlide = () => {\r\n const emptySlide = {\r\n id: createRandomCode(8),\r\n elements: [],\r\n background: {\r\n type: 'solid',\r\n color: theme.value.backgroundColor,\r\n },\r\n }\r\n store.commit(MutationTypes.ADD_SLIDE, emptySlide)\r\n addHistorySnapshot()\r\n }\r\n\r\n const copyAndPasteSlide = () => {\r\n store.commit(MutationTypes.ADD_SLIDE, currentSlide.value)\r\n addHistorySnapshot()\r\n }\r\n\r\n const deleteSlide = () => {\r\n store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)\r\n addHistorySnapshot()\r\n }\r\n\r\n const cutSlide = () => {\r\n copySlide()\r\n deleteSlide()\r\n }\r\n\r\n return {\r\n updateSlideIndex,\r\n copySlide,\r\n pasteSlide,\r\n createSlide,\r\n copyAndPasteSlide,\r\n deleteSlide,\r\n cutSlide,\r\n }\r\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const lockElement = () => {\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n \n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id)) element.lock = true\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n addHistorySnapshot()\n }\n\n const unlockElement = (handleElement: PPTElement) => {\n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n\n if(handleElement.groupId) {\n for(const element of newElementList) {\n if(element.groupId === handleElement.groupId) element.lock = false\n }\n return newElementList\n }\n \n for(const element of newElementList) {\n if(element.id === handleElement.id) {\n element.lock = false\n break\n }\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [handleElement.id])\n addHistorySnapshot()\n }\n\n return {\n lockElement,\n unlockElement,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const deleteElement = () => {\n if(!activeElementIdList.value.length) return\n const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id))\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n const deleteAllElements = () => {\n if(!currentSlide.value.elements.length) return\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })\n addHistorySnapshot()\n }\n\n return {\n deleteElement,\n deleteAllElements,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n // 组合元素(为当前所有激活元素添加一个相同的groupId)\n const combineElements = () => {\n if(!activeElementList.value.length) return\n\n let newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n const groupId = createRandomCode()\n\n const combineElementList: PPTElement[] = []\n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id)) {\n element.groupId = groupId\n combineElementList.push(element)\n }\n }\n\n // 注意,组合元素的层级应该是连续的,所以需要获取该组元素中最顶层的元素,将组内其他成员从原位置移动到最顶层的元素的下面\n const combineElementMaxIndex = newElementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id)\n const combineElementIdList = combineElementList.map(_element => _element.id)\n newElementList = newElementList.filter(_element => !combineElementIdList.includes(_element.id))\n\n const insertIndex = combineElementMaxIndex - combineElementList.length + 1\n newElementList.splice(insertIndex, 0, ...combineElementList)\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n // 取消组合元素(移除所有被激活元素的groupId)\n const uncombineElements = () => {\n if(!activeElementList.value.length) return\n const hasElementInGroup = activeElementList.value.some(item => item.groupId)\n if(!hasElementInGroup) return\n \n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n for(const element of newElementList) {\n if(activeElementIdList.value.includes(element.id) && element.groupId) delete element.groupId\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n return {\n combineElements,\n uncombineElements,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { copyText, readClipboard } from '@/utils/clipboard'\nimport { encrypt } from '@/utils/crypto'\nimport { message } from 'ant-design-vue'\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\nimport useDeleteElement from './useDeleteElement'\n\nexport default () => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n\n const { pasteTextClipboardData } = usePasteTextClipboardData()\n const { deleteElement } = useDeleteElement()\n\n const copyElement = () => {\n if(!activeElementIdList.value.length) return\n\n const text = encrypt(JSON.stringify({\n type: 'elements',\n data: activeElementList.value,\n }))\n\n copyText(text).then(() => {\n store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n })\n }\n\n const cutElement = () => {\n copyElement()\n deleteElement()\n }\n\n const pasteElement = () => {\n readClipboard().then(text => {\n pasteTextClipboardData(text)\n }).catch(err => message.warning(err))\n }\n\n const quickCopyElement = () => {\n copyElement()\n pasteElement()\n }\n\n return {\n copyElement,\n cutElement,\n pasteElement,\n quickCopyElement,\n }\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const selectAllElement = () => {\r\n const unlockedElements = currentSlide.value.elements.filter(el => !el.lock)\r\n const newActiveElementIdList = unlockedElements.map(el => el.id)\r\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\r\n }\r\n\r\n return {\r\n selectAllElement,\r\n }\r\n}","import { computed } from 'vue'\r\nimport { MutationTypes, useStore } from '@/store'\r\nimport { Slide } from '@/types/slides'\r\nimport { KEYS } from '@/configs/hotkey'\r\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\r\n\r\nexport default () => {\r\n const store = useStore()\r\n const activeElementIdList = computed(() => store.state.activeElementIdList)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const { addHistorySnapshot } = useHistorySnapshot()\r\n\r\n const moveElement = (command: string) => {\r\n const newElementList = currentSlide.value.elements.map(el => {\r\n if(activeElementIdList.value.includes(el.id)) {\r\n let { left, top } = el\r\n switch(command) {\r\n case KEYS.LEFT: \r\n left = left - 1\r\n break\r\n case KEYS.RIGHT: \r\n left = left + 1\r\n break\r\n case KEYS.UP: \r\n top = top - 1\r\n break\r\n case KEYS.DOWN: \r\n top = top + 1\r\n break\r\n default: break\r\n }\r\n return { ...el, left, top }\r\n }\r\n return el\r\n })\r\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\r\n addHistorySnapshot()\r\n }\r\n\r\n return {\r\n moveElement,\r\n }\r\n}","// 进入全屏\nexport const enterFullscreen = () => {\n const docElm = document.documentElement\n if(docElm.requestFullscreen) docElm.requestFullscreen() \n else if(docElm.mozRequestFullScreen) docElm.mozRequestFullScreen() \n else if(docElm.webkitRequestFullScreen) docElm.webkitRequestFullScreen()\n}\n\n// 退出全屏\nexport const exitFullscreen = () => {\n if(document.exitFullscreen) document.exitFullscreen()\n else if(document.mozCancelFullScreen) document.mozCancelFullScreen()\n else if(document.webkitCancelFullScreen) document.webkitCancelFullScreen()\n}\n\n// 判断是否全屏\nexport const isFullscreen = () => (\n document.mozFullScreen || \n document.webkitIsFullScreen || \n document.webkitFullScreen\n)","import { MutationTypes, useStore } from '@/store'\nimport { enterFullscreen, exitFullscreen, isFullscreen } from '@/utils/fullscreen'\n\nexport default () => {\n const store = useStore()\n\n const enterScreening = () => {\n enterFullscreen()\n store.commit(MutationTypes.SET_SCREENING, true)\n }\n\n const enterScreeningFromStart = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)\n enterScreening()\n }\n\n const exitScreening = () => {\n store.commit(MutationTypes.SET_SCREENING, false)\n if(isFullscreen()) exitFullscreen()\n }\n\n return {\n enterScreening,\n enterScreeningFromStart,\n exitScreening,\n }\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\n\nexport default () => {\n const store = useStore()\n const canvasPercentage = computed(() => store.state.canvasPercentage)\n\n const scaleCanvas = (command: '+' | '-') => {\n let percentage = canvasPercentage.value\n const step = 5\n const max = 120\n const min = 60\n if(command === '+' && percentage <= max) percentage += step\n if(command === '-' && percentage >= min) percentage -= step\n \n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\n }\n\n const setCanvasPercentage = (percentage: number) => {\n store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)\n }\n \n return {\n scaleCanvas,\n setCanvasPercentage,\n }\n}","import { computed, onMounted, onUnmounted } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { KEYS } from '@/configs/hotkey'\n\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useLockElement from '@/hooks/useLockElement'\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCombineElement from '@/hooks/useCombineElement'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\nimport useMoveElement from '@/hooks/useMoveElement'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useScreening from '@/hooks/useScreening'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\n\nexport default () => {\n const store = useStore()\n\n const ctrlKeyActive = computed(() => store.state.ctrlKeyState)\n const shiftKeyActive = computed(() => store.state.shiftKeyState)\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n\n const {\n updateSlideIndex,\n copySlide,\n createSlide,\n deleteSlide,\n cutSlide,\n copyAndPasteSlide,\n } = useSlideHandler()\n\n const { combineElements, uncombineElements } = useCombineElement()\n const { deleteElement } = useDeleteElement()\n const { lockElement } = useLockElement()\n const { copyElement, cutElement, quickCopyElement } = useCopyAndPasteElement()\n const { selectAllElement } = useSelectAllElement()\n const { moveElement } = useMoveElement()\n const { redo, undo } = useHistorySnapshot()\n const { enterScreening } = useScreening()\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\n\n const copy = () => {\n if(activeElementIdList.value.length) copyElement()\n else if(thumbnailsFocus.value) copySlide()\n }\n\n const cut = () => {\n if(activeElementIdList.value.length) cutElement()\n else if(thumbnailsFocus.value) cutSlide()\n }\n\n const quickCopy = () => {\n if(activeElementIdList.value.length) quickCopyElement()\n else if(thumbnailsFocus.value) copyAndPasteSlide()\n }\n\n const selectAll = () => {\n if(!editorAreaFocus.value) return\n selectAllElement()\n }\n\n const lock = () => {\n if(!editorAreaFocus.value) return\n lockElement()\n }\n const combine = () => {\n if(!editorAreaFocus.value) return\n combineElements()\n }\n\n const uncombine = () => {\n if(!editorAreaFocus.value) return\n uncombineElements()\n }\n\n const remove = () => {\n if(activeElementIdList.value.length) deleteElement()\n else if(thumbnailsFocus.value) deleteSlide()\n }\n\n const move = (key: string) => {\n if(activeElementIdList.value.length) moveElement(key)\n else if(key === KEYS.UP || key === KEYS.DOWN) updateSlideIndex(key)\n }\n\n const create = () => {\n if(!thumbnailsFocus.value) return\n createSlide()\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const { ctrlKey, shiftKey, metaKey } = e\n\n const key = e.key.toUpperCase()\n\n if(ctrlKey && !ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, true)\n if(shiftKey && !shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, true)\n\n if(ctrlKey && key === KEYS.F) {\n e.preventDefault()\n enterScreening()\n store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\n }\n \n if(!editorAreaFocus.value && !thumbnailsFocus.value) return \n\n if((ctrlKey || metaKey) && key === KEYS.C) {\n if(disableHotkeys.value) return\n e.preventDefault()\n copy()\n }\n if(ctrlKey && key === KEYS.X) {\n if(disableHotkeys.value) return\n e.preventDefault()\n cut()\n }\n if(ctrlKey && key === KEYS.D) {\n if(disableHotkeys.value) return\n e.preventDefault()\n quickCopy()\n }\n if(ctrlKey && key === KEYS.Z) {\n if(disableHotkeys.value) return\n e.preventDefault()\n undo()\n }\n if(ctrlKey && key === KEYS.Y) {\n if(disableHotkeys.value) return\n e.preventDefault()\n redo()\n }\n if(ctrlKey && key === KEYS.A) {\n if(disableHotkeys.value) return\n e.preventDefault()\n selectAll()\n }\n if(ctrlKey && key === KEYS.L) {\n if(disableHotkeys.value) return\n e.preventDefault()\n lock()\n }\n if(!shiftKey && ctrlKey && key === KEYS.G) {\n if(disableHotkeys.value) return\n e.preventDefault()\n combine()\n }\n if(shiftKey && ctrlKey && key === KEYS.G) {\n if(disableHotkeys.value) return\n e.preventDefault()\n uncombine()\n }\n if(key === KEYS.DELETE) {\n if(disableHotkeys.value) return\n e.preventDefault()\n remove()\n }\n if(key === KEYS.UP) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.UP)\n }\n if(key === KEYS.DOWN) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.DOWN)\n }\n if(key === KEYS.LEFT) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.LEFT)\n }\n if(key === KEYS.RIGHT) {\n if(disableHotkeys.value) return\n e.preventDefault()\n move(KEYS.RIGHT)\n }\n if(key === KEYS.ENTER) {\n if(disableHotkeys.value) return\n e.preventDefault()\n create()\n }\n if(key === KEYS.MINUS) {\n if(disableHotkeys.value) return\n e.preventDefault()\n scaleCanvas('-')\n }\n if(key === KEYS.EQUAL) {\n if(disableHotkeys.value) return\n e.preventDefault()\n scaleCanvas('+')\n }\n if(key === KEYS.DIGIT_0) {\n if(disableHotkeys.value) return\n e.preventDefault()\n setCanvasPercentage(90)\n }\n }\n \n const keyupListener = () => {\n if(ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)\n if(shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, false)\n }\n\n onMounted(() => {\n document.addEventListener('keydown', keydownListener)\n document.addEventListener('keyup', keyupListener)\n window.addEventListener('blur', keyupListener)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keydownListener)\n document.removeEventListener('keyup', keyupListener)\n window.removeEventListener('blur', keyupListener)\n })\n}","import { computed, onMounted, onUnmounted } from 'vue'\nimport { useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default () => {\n const store = useStore()\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n\n const { pasteTextClipboardData } = usePasteTextClipboardData()\n const { createImageElement } = useCreateElement()\n\n const pasteImageFile = (imageFile: File) => {\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n\n const pasteListener = (e: ClipboardEvent) => {\n if(!editorAreaFocus.value && !thumbnailsFocus.value) return\n if(disableHotkeys.value) return\n\n if(!e.clipboardData) return\n\n const clipboardDataItems = e.clipboardData.items\n const clipboardDataFirstItem = clipboardDataItems[0]\n\n if(!clipboardDataFirstItem) return\n\n for(const item of clipboardDataItems) {\n if(item.kind === 'file' && item.type.indexOf('image') !== -1) {\n const imageFile = item.getAsFile()\n if(imageFile) pasteImageFile(imageFile)\n return\n }\n }\n\n if(clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\n clipboardDataFirstItem.getAsString(text => pasteTextClipboardData(text))\n }\n }\n\n onMounted(() => {\n document.addEventListener('paste', pasteListener)\n })\n onUnmounted(() => {\n document.removeEventListener('paste', pasteListener)\n })\n}","\n\n\n\n","\nimport { computed, defineComponent, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { createRandomCode } from '@/utils/common'\nimport useScreening from '@/hooks/useScreening'\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport { message } from 'ant-design-vue'\n\nconst hotkeys = [\n {\n type: '通用',\n children: [\n { label: '剪切', value: 'Ctrl + X' },\n { label: '复制', value: 'Ctrl + C' },\n { label: '粘贴', value: 'Ctrl + V' },\n { label: '快速复制粘贴', value: 'Ctrl + D' },\n { label: '全选', value: 'Ctrl + A' },\n { label: '撤销', value: 'Ctrl + Z' },\n { label: '恢复', value: 'Ctrl + Y' },\n { label: '删除', value: 'Delete' },\n ],\n },\n {\n type: '幻灯片放映',\n children: [\n { label: '开始放映幻灯片', value: 'Ctrl + F' },\n { label: '切换上一页', value: '↑ / ←' },\n { label: '切换下一页', value: '↓ / → / Enter / Space' },\n { label: '退出放映', value: 'ESC' },\n ],\n },\n {\n type: '幻灯片编辑',\n children: [\n { label: '新建幻灯片', value: 'Enter' },\n { label: '缩放画布', value: 'Ctrl + 鼠标滚动' },\n { label: '放大画布', value: 'Ctrl + =' },\n { label: '缩小画布', value: 'Ctrl + -' },\n { label: '缩放画布到合适大小', value: 'Ctrl + 0' },\n { label: '编辑上一页', value: '↑ / ←' },\n { label: '编辑下一页', value: '↓ / →' },\n ],\n },\n {\n type: '元素操作',\n children: [\n { label: '移动', value: '↑ / ← / ↓ / →' },\n { label: '锁定', value: 'Ctrl + L' },\n { label: '组合', value: 'Ctrl + G' },\n { label: '取消组合', value: 'Ctrl + Shift + G' },\n { label: '多选', value: '按住 Ctrl 或 Shift' },\n { label: '锁定宽高比例', value: '按住 Ctrl 或 Shift' },\n { label: '创建水平 / 垂直线条', value: '按住 Ctrl 或 Shift' },\n { label: '确认图片裁剪', value: 'Enter' },\n ],\n },\n {\n type: '表格编辑',\n children: [\n { label: '聚焦到下一个单元格', value: 'Tab' },\n ],\n },\n {\n type: '文本编辑',\n children: [\n { label: '加粗', value: 'Ctrl + B' },\n { label: '斜体', value: 'Ctrl + I' },\n { label: '下划线', value: 'Ctrl + U' },\n { label: '删除线', value: 'Ctrl + D' },\n ],\n },\n]\n\nexport default defineComponent({\n name: 'editor-header',\n setup() {\n const store = useStore()\n\n const { enterScreening, enterScreeningFromStart } = useScreening()\n const { createSlide, deleteSlide } = useSlideHandler()\n const { redo, undo } = useHistorySnapshot()\n\n const showGridLines = computed(() => store.state.showGridLines)\n const toggleGridLines = () => {\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\n }\n\n const resetSlides = () => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n store.commit(MutationTypes.SET_SLIDES, [{\n id: createRandomCode(),\n elements: [],\n }])\n }\n\n const openDoc = () => {\n message.warning('作者努力编写中...')\n }\n\n const hotkeyDrawerVisible = ref(false)\n\n return {\n enterScreening,\n enterScreeningFromStart,\n createSlide,\n deleteSlide,\n redo,\n undo,\n toggleGridLines,\n showGridLines,\n resetSlides,\n openDoc,\n hotkeyDrawerVisible,\n hotkeys,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=2accc3e9&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=2accc3e9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2accc3e9\"\n\nexport default script","\n\n\n\n","import { ShapePoolItem } from '@/configs/shapes'\r\nimport { LinePoolItem } from '@/configs/lines'\r\n\r\nexport type ElementOrderCommand = 'up' | 'down' | 'top' | 'bottom'\r\n\r\nexport const enum ElementOrderCommands {\r\n UP = 'up',\r\n DOWN = 'down',\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n}\r\n\r\nexport type ElementAlignCommand = 'top'| 'bottom' | 'left' | 'right' | 'vertical' | 'horizontal'\r\n\r\nexport const enum ElementAlignCommands {\r\n TOP = 'top',\r\n BOTTOM = 'bottom',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n VERTICAL = 'vertical',\r\n HORIZONTAL = 'horizontal',\r\n}\r\n\r\nexport type OperateBorderLine = 'top' | 'bottom' | 'left' | 'right'\r\n\r\nexport const enum OperateBorderLines {\r\n T = 'top',\r\n B = 'bottom',\r\n L = 'left',\r\n R = 'right',\r\n}\r\n\r\nexport type OperateResizeHandler = '' | 'left-top' | 'top' | 'right-top' | 'left' | 'right' | 'left-bottom' | 'bottom' | 'right-bottom'\r\n\r\nexport const enum OperateResizeHandlers {\r\n LEFT_TOP = 'left-top',\r\n TOP = 'top',\r\n RIGHT_TOP = 'right-top',\r\n LEFT = 'left',\r\n RIGHT = 'right',\r\n LEFT_BOTTOM = 'left-bottom',\r\n BOTTOM = 'bottom',\r\n RIGHT_BOTTOM = 'right-bottom',\r\n}\r\n\r\nexport type OperateLineHandler = 'start' | 'end'\r\n\r\nexport const enum OperateLineHandlers {\r\n START = 'start',\r\n END = 'end,'\r\n}\r\n\r\nexport interface AlignmentLineAxis {\r\n x: number; \r\n y: number;\r\n}\r\n\r\nexport interface AlignmentLineProps {\r\n type: 'vertical' | 'horizontal';\r\n axis: AlignmentLineAxis;\r\n length: number;\r\n}\r\n\r\nexport interface MultiSelectRange {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n}\r\n\r\nexport type ImageClipDataRange = [[number, number], [number, number]]\r\n\r\nexport interface ImageClipData {\r\n range: ImageClipDataRange;\r\n path: string;\r\n}\r\n\r\nexport interface ImageClipedEmitData {\r\n range: ImageClipDataRange;\r\n position: {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n };\r\n}\r\n\r\nexport interface CreateElementSelectionData {\r\n start: [number, number];\r\n end: [number, number];\r\n}\r\n\r\nexport interface CreatingTextElement {\r\n type: 'text';\r\n}\r\nexport interface CreatingShapeElement {\r\n type: 'shape';\r\n data: ShapePoolItem;\r\n}\r\nexport interface CreatingLineElement {\r\n type: 'line';\r\n data: LinePoolItem;\r\n}\r\nexport type CreatingElement = CreatingTextElement | CreatingShapeElement | CreatingLineElement","export const removeAllRanges = () => {\n const selection = window.getSelection()\n selection && selection.removeAllRanges()\n}","import { ref, computed, onMounted, onUnmounted, Ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\n\nexport default (canvasRef: Ref) => {\n const viewportLeft = ref(0)\n const viewportTop = ref(0)\n\n const store = useStore()\n const canvasPercentage = computed(() => store.state.canvasPercentage)\n\n const setViewportSize = () => {\n if(!canvasRef.value) return\n const canvasWidth = canvasRef.value.clientWidth\n const canvasHeight = canvasRef.value.clientHeight\n\n if(canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {\n const viewportActualWidth = canvasWidth * (canvasPercentage.value / 100)\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualWidth / VIEWPORT_SIZE)\n viewportLeft.value = (canvasWidth - viewportActualWidth) / 2\n viewportTop.value = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2\n }\n else {\n const viewportActualHeight = canvasHeight * (canvasPercentage.value / 100)\n store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO))\n viewportLeft.value = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2\n viewportTop.value = (canvasHeight - viewportActualHeight) / 2\n }\n }\n\n watch(canvasPercentage, setViewportSize)\n\n const viewportStyles = computed(() => ({\n width: VIEWPORT_SIZE,\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\n left: viewportLeft.value,\n top: viewportTop.value,\n }))\n\n const resizeObserver = new ResizeObserver(setViewportSize)\n\n onMounted(() => {\n if(canvasRef.value) resizeObserver.observe(canvasRef.value)\n })\n onUnmounted(() => {\n if(canvasRef.value) resizeObserver.unobserve(canvasRef.value)\n })\n\n return {\n viewportStyles,\n }\n}","import { PPTElement } from '@/types/slides'\r\n\r\n// 获取矩形旋转后在画布中的位置范围\r\ninterface RotatedElementData {\r\n left: number;\r\n top: number;\r\n width: number;\r\n height: number;\r\n rotate: number;\r\n}\r\nexport const getRectRotatedRange = (element: RotatedElementData) => {\r\n const { left, top, width, height, rotate = 0 } = element\r\n\r\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\r\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\r\n\r\n const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180\r\n const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180\r\n\r\n const halfWidth = width / 2\r\n const halfHeight = height / 2\r\n\r\n const middleLeft = left + halfWidth\r\n const middleTop = top + halfHeight\r\n\r\n const xAxis = [\r\n middleLeft + radius * Math.cos(tlbraRadian),\r\n middleLeft + radius * Math.cos(trblaRadian),\r\n middleLeft - radius * Math.cos(tlbraRadian),\r\n middleLeft - radius * Math.cos(trblaRadian),\r\n ]\r\n const yAxis = [\r\n middleTop - radius * Math.sin(tlbraRadian),\r\n middleTop - radius * Math.sin(trblaRadian),\r\n middleTop + radius * Math.sin(tlbraRadian),\r\n middleTop + radius * Math.sin(trblaRadian),\r\n ]\r\n\r\n return {\r\n xRange: [Math.min(...xAxis), Math.max(...xAxis)],\r\n yRange: [Math.min(...yAxis), Math.max(...yAxis)],\r\n }\r\n}\r\n\r\n// 获取元素在画布中的位置范围\r\nexport const getElementRange = (element: PPTElement) => {\r\n let minX, maxX, minY, maxY\r\n\r\n if(element.type === 'line') {\r\n minX = element.left\r\n maxX = element.left + Math.max(element.start[0], element.end[0])\r\n minY = element.top\r\n maxY = element.top + Math.max(element.start[1], element.end[1])\r\n }\r\n else if('rotate' in element && element.rotate) {\r\n const { left, top, width, height, rotate } = element\r\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\r\n minX = xRange[0]\r\n maxX = xRange[1]\r\n minY = yRange[0]\r\n maxY = yRange[1]\r\n }\r\n else {\r\n minX = element.left\r\n maxX = element.left + element.width\r\n minY = element.top\r\n maxY = element.top + element.height\r\n }\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\n// 获取元素集合在画布中的位置范围\r\nexport const getElementListRange = (elementList: PPTElement[]) => {\r\n const leftValues: number[] = []\r\n const topValues: number[] = []\r\n const rightValues: number[] = []\r\n const bottomValues: number[] = []\r\n\r\n elementList.forEach(element => {\r\n const { minX, maxX, minY, maxY } = getElementRange(element)\r\n leftValues.push(minX)\r\n topValues.push(minY)\r\n rightValues.push(maxX)\r\n bottomValues.push(maxY)\r\n })\r\n\r\n const minX = Math.min(...leftValues)\r\n const maxX = Math.max(...rightValues)\r\n const minY = Math.min(...topValues)\r\n const maxY = Math.max(...bottomValues)\r\n\r\n return { minX, maxX, minY, maxY }\r\n}\r\n\r\nexport interface AlignLine {\r\n value: number;\r\n range: [number, number];\r\n}\r\n\r\n// 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条\r\nexport const uniqAlignLines = (lines: AlignLine[]) => {\r\n const uniqLines: AlignLine[] = []\r\n lines.forEach(line => {\r\n const index = uniqLines.findIndex(_line => _line.value === line.value)\r\n if(index === -1) uniqLines.push(line)\r\n else {\r\n const uniqLine = uniqLines[index]\r\n const rangeMin = Math.min(uniqLine.range[0], line.range[0])\r\n const rangeMax = Math.max(uniqLine.range[1], line.range[1])\r\n const range: [number, number] = [rangeMin, rangeMax]\r\n const _line = { value: line.value, range }\r\n uniqLines[index] = _line\r\n }\r\n })\r\n return uniqLines\r\n}","import { Ref, reactive, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { getElementRange } from '@/utils/element'\n\nexport default (elementList: Ref, viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const mouseSelectionState = reactive({\n isShow: false,\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n quadrant: 1,\n })\n\n const updateMouseSelection = (e: MouseEvent) => {\n if(!viewportRef.value) return\n\n let isMouseDown = true\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const minSelectionRange = 5\n \n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const left = (startPageX - viewportRect.x) / canvasScale.value\n const top = (startPageY - viewportRect.y) / canvasScale.value\n\n mouseSelectionState.isShow = false\n mouseSelectionState.quadrant = 4\n mouseSelectionState.top = top\n mouseSelectionState.left = left\n mouseSelectionState.width = 0\n mouseSelectionState.height = 0\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const offsetWidth = (currentPageX - startPageX) / canvasScale.value\n const offsetHeight = (currentPageY - startPageY) / canvasScale.value\n\n const width = Math.abs(offsetWidth)\n const height = Math.abs(offsetHeight)\n\n if( width < minSelectionRange || height < minSelectionRange ) return\n \n let quadrant = 0\n if( offsetWidth > 0 && offsetHeight > 0 ) quadrant = 4\n else if( offsetWidth < 0 && offsetHeight < 0 ) quadrant = 1\n else if( offsetWidth > 0 && offsetHeight < 0 ) quadrant = 2\n else if( offsetWidth < 0 && offsetHeight > 0 ) quadrant = 3\n\n mouseSelectionState.isShow = true\n mouseSelectionState.quadrant = quadrant\n mouseSelectionState.width = width\n mouseSelectionState.height = height\n }\n\n document.onmouseup = () => {\n document.onmousemove = null\n document.onmouseup = null\n isMouseDown = false\n\n // 计算当前页面中的每一个元素是否处在鼠标选择范围中(必须完全包裹)\n // 将选择范围中的元素添加为激活元素\n let inRangeElementList: PPTElement[] = []\n for(let i = 0; i < elementList.value.length; i++) {\n const element = elementList.value[i]\n const mouseSelectionLeft = mouseSelectionState.left\n const mouseSelectionTop = mouseSelectionState.top\n const mouseSelectionWidth = mouseSelectionState.width\n const mouseSelectionHeight = mouseSelectionState.height\n\n const quadrant = mouseSelectionState.quadrant\n\n const { minX, maxX, minY, maxY } = getElementRange(element)\n\n let isInclude = false\n if(quadrant === 4) {\n isInclude = minX > mouseSelectionLeft && \n maxX < mouseSelectionLeft + mouseSelectionWidth && \n minY > mouseSelectionTop && \n maxY < mouseSelectionTop + mouseSelectionHeight\n }\n else if(quadrant === 1) {\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \n minY > (mouseSelectionTop - mouseSelectionHeight) && \n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\n }\n else if(quadrant === 2) {\n isInclude = minX > mouseSelectionLeft && \n maxX < mouseSelectionLeft + mouseSelectionWidth && \n minY > (mouseSelectionTop - mouseSelectionHeight) && \n maxY < (mouseSelectionTop - mouseSelectionHeight) + mouseSelectionHeight\n }\n else if(quadrant === 3) {\n isInclude = minX > (mouseSelectionLeft - mouseSelectionWidth) && \n maxX < (mouseSelectionLeft - mouseSelectionWidth) + mouseSelectionWidth && \n minY > mouseSelectionTop && \n maxY < mouseSelectionTop + mouseSelectionHeight\n }\n\n // 被锁定的元素除外\n if(isInclude && !element.lock) inRangeElementList.push(element)\n }\n\n // 对于组合元素成员,必须所有成员都在选择范围中才算被选中\n inRangeElementList = inRangeElementList.filter(inRangeElement => {\n if(inRangeElement.groupId) {\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\n const groupElementList = elementList.value.filter(element => element.groupId === inRangeElement.groupId)\n return groupElementList.every(groupElement => inRangeElementIdList.includes(groupElement.id))\n }\n return true\n })\n const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)\n if(inRangeElementIdList.length) store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, inRangeElementIdList)\n\n mouseSelectionState.isShow = false\n }\n }\n\n return {\n mouseSelectionState,\n updateMouseSelection,\n }\n}","import { computed, onMounted, onUnmounted, Ref } from 'vue'\nimport { useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default (elementRef: Ref) => {\n const store = useStore()\n const disableHotkeys = computed(() => store.state.disableHotkeys)\n\n const { createImageElement, createTextElement } = useCreateElement()\n\n const handleDrop = (e: DragEvent) => {\n if(!e.dataTransfer) return\n const dataTransferItem = e.dataTransfer.items[0]\n\n if(dataTransferItem.kind === 'file' && dataTransferItem.type.indexOf('image') !== -1) {\n const imageFile = dataTransferItem.getAsFile()\n if(imageFile) {\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n }\n else if(dataTransferItem.kind === 'string' && dataTransferItem.type === 'text/plain') {\n dataTransferItem.getAsString(text => {\n if(disableHotkeys.value) return\n createTextElement({\n left: 0,\n top: 0,\n width: 600,\n height: 50,\n }, text)\n })\n }\n }\n\n onMounted(() => {\n elementRef.value && elementRef.value.addEventListener('drop', handleDrop)\n\n document.ondragleave = e => e.preventDefault()\n document.ondrop = e => e.preventDefault()\n document.ondragenter = e => e.preventDefault()\n document.ondragover = e => e.preventDefault()\n })\n onUnmounted(() => {\n elementRef.value && elementRef.value.removeEventListener('drop', handleDrop)\n\n document.ondragleave = null\n document.ondrop = null\n document.ondragenter = null\n document.ondragover = null\n })\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\n// 给定一个坐标,计算该坐标到(0, 0)点连线的弧度值\n// 注意,Math.atan2的一般用法是Math.atan2(y, x)返回的是原点(0,0)到(x,y)点的线段与X轴正方向之间的弧度值\n// 这里将使用时将x与y的传入顺序交换了,为的是获取原点(0,0)到(x,y)点的线段与Y轴正方向之间的弧度值\nconst getAngleFromCoordinate = (x: number, y: number) => {\n const radian = Math.atan2(x, y)\n const angle = 180 / Math.PI * radian\n return angle\n}\n\nexport default (elementList: Ref, viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {\n let isMouseDown = true\n let angle = 0\n const elOriginRotate = element.rotate || 0\n\n // 计算元素中心(旋转的中心,坐标原点)\n const elLeft = element.left\n const elTop = element.top\n const elWidth = element.width\n const elHeight = element.height\n const centerX = elLeft + elWidth / 2\n const centerY = elTop + elHeight / 2\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n // 计算鼠标基于旋转中心的坐标\n const mouseX = (e.pageX - viewportRect.left) / canvasScale.value\n const mouseY = (e.pageY - viewportRect.top) / canvasScale.value\n const x = mouseX - centerX\n const y = centerY - mouseY\n\n angle = getAngleFromCoordinate(x, y)\n\n // 45°的倍数位置有吸附效果\n const sorptionRange = 5\n if( Math.abs(angle) <= sorptionRange ) angle = 0\n else if( angle > 0 && Math.abs(angle - 45) <= sorptionRange ) angle -= (angle - 45)\n else if( angle < 0 && Math.abs(angle + 45) <= sorptionRange ) angle -= (angle + 45)\n else if( angle > 0 && Math.abs(angle - 90) <= sorptionRange ) angle -= (angle - 90)\n else if( angle < 0 && Math.abs(angle + 90) <= sorptionRange ) angle -= (angle + 90)\n else if( angle > 0 && Math.abs(angle - 135) <= sorptionRange ) angle -= (angle - 135)\n else if( angle < 0 && Math.abs(angle + 135) <= sorptionRange ) angle -= (angle + 135)\n else if( angle > 0 && Math.abs(angle - 180) <= sorptionRange ) angle -= (angle - 180)\n else if( angle < 0 && Math.abs(angle + 180) <= sorptionRange ) angle -= (angle + 180)\n\n // 修改元素角度\n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, rotate: angle } : el)\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n if(elOriginRotate === angle) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n rotateElement,\n }\n}","import mitt, { Emitter } from 'mitt'\n\nexport const enum EmitterEvents {\n UPDATE_TEXT_STATE = 'UPDATE_TEXT_STATE',\n EXEC_TEXT_COMMAND = 'EXEC_TEXT_COMMAND',\n UPDATE_TABLE_SELECTED_CELL = 'UPDATE_TABLE_SELECTED_CELL',\n SCALE_ELEMENT_STATE = 'SCALE_ELEMENT_STATE',\n}\n\nconst emitter: Emitter = mitt()\n\nexport default emitter","export const ELEMENT_TYPE_ZH = {\n text: '文本',\n image: '图片',\n shape: '形状',\n line: '线条',\n chart: '图表',\n table: '表格',\n}\n\nexport const MIN_SIZE = {\n text: 20,\n image: 20,\n shape: 15,\n chart: 200,\n table: 20,\n}","import { computed, Ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandlers, AlignmentLineProps, MultiSelectRange } from '@/types/edit'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { MIN_SIZE } from '@/configs/element'\nimport { AlignLine, uniqAlignLines } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\n// 计算元素被旋转一定角度后,八个操作点的新坐标\ninterface RotateElementData {\n left: number;\n top: number;\n width: number;\n height: number;\n}\nconst getRotateElementPoints = (element: RotateElementData, angle: number) => {\n const { left, top, width, height } = element\n\n const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2\n const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI\n\n const tlbraRadian = (180 - angle - auxiliaryAngle) * Math.PI / 180\n const trblaRadian = (auxiliaryAngle - angle) * Math.PI / 180\n const taRadian = (90 - angle) * Math.PI / 180\n const raRadian = angle * Math.PI / 180\n\n const halfWidth = width / 2\n const halfHeight = height / 2\n\n const middleLeft = left + halfWidth\n const middleTop = top + halfHeight\n\n const leftTopPoint = {\n left: middleLeft + radius * Math.cos(tlbraRadian),\n top: middleTop - radius * Math.sin(tlbraRadian),\n }\n const topPoint = {\n left: middleLeft + halfHeight * Math.cos(taRadian),\n top: middleTop - halfHeight * Math.sin(taRadian),\n }\n const rightTopPoint = {\n left: middleLeft + radius * Math.cos(trblaRadian),\n top: middleTop - radius * Math.sin(trblaRadian),\n }\n const rightPoint = {\n left: middleLeft + halfWidth * Math.cos(raRadian),\n top: middleTop + halfWidth * Math.sin(raRadian),\n }\n const rightBottomPoint = {\n left: middleLeft - radius * Math.cos(tlbraRadian),\n top: middleTop + radius * Math.sin(tlbraRadian),\n }\n const bottomPoint = {\n left: middleLeft - halfHeight * Math.sin(raRadian),\n top: middleTop + halfHeight * Math.cos(raRadian),\n }\n const leftBottomPoint = {\n left: middleLeft - radius * Math.cos(trblaRadian),\n top: middleTop + radius * Math.sin(trblaRadian),\n }\n const leftPoint = {\n left: middleLeft - halfWidth * Math.cos(raRadian),\n top: middleTop - halfWidth * Math.sin(raRadian),\n }\n\n return { leftTopPoint, topPoint, rightTopPoint, rightPoint, rightBottomPoint, bottomPoint, leftBottomPoint, leftPoint }\n}\n\n// 获取元素某个操作点对角线上另一端的操作点坐标(例如:左上 <-> 右下)\nconst getOppositePoint = (direction: string, points: ReturnType): { left: number; top: number } => {\n const oppositeMap = {\n [OperateResizeHandlers.RIGHT_BOTTOM]: points.leftTopPoint,\n [OperateResizeHandlers.LEFT_BOTTOM]: points.rightTopPoint,\n [OperateResizeHandlers.LEFT_TOP]: points.rightBottomPoint,\n [OperateResizeHandlers.RIGHT_TOP]: points.leftBottomPoint,\n [OperateResizeHandlers.TOP]: points.bottomPoint,\n [OperateResizeHandlers.BOTTOM]: points.topPoint,\n [OperateResizeHandlers.LEFT]: points.rightPoint,\n [OperateResizeHandlers.RIGHT]: points.leftPoint,\n }\n return oppositeMap[direction]\n}\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n alignmentLines: Ref,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const scaleElement = (e: MouseEvent, element: Exclude, command: OperateResizeHandlers) => {\n let isMouseDown = true\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, true)\n\n const elOriginLeft = element.left\n const elOriginTop = element.top\n const elOriginWidth = element.width\n const elOriginHeight = element.height\n\n const fixedRatio = ctrlOrShiftKeyActive.value || ('fixedRatio' in element && element.fixedRatio)\n const aspectRatio = elOriginWidth / elOriginHeight\n \n const elRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n const rotateRadian = Math.PI * elRotate / 180\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const minSize = MIN_SIZE[element.type] || 20\n const getSizeWithinRange = (size: number) => size < minSize ? minSize : size\n\n let points: ReturnType\n let baseLeft = 0\n let baseTop = 0\n let horizontalLines: AlignLine[] = []\n let verticalLines: AlignLine[] = []\n\n if('rotate' in element && element.rotate) {\n // 元素旋转后的各点坐标以及对角坐标\n const { left, top, width, height } = element\n points = getRotateElementPoints({ left, top, width, height }, elRotate)\n const oppositePoint = getOppositePoint(command, points)\n\n // 基点坐标(以操作点相对的点为基点,例如拖动右下角,实际上是保持左上角不变的前提下修改其他信息)\n baseLeft = oppositePoint.left\n baseTop = oppositePoint.top\n }\n else {\n const edgeWidth = VIEWPORT_SIZE\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n const isActiveGroupElement = element.id === activeGroupElementId.value\n \n for(const el of elementList.value) {\n if('rotate' in el && el.rotate) continue\n if(el.type === 'line') continue\n if(isActiveGroupElement && el.id === element.id) continue\n if(!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\n\n const left = el.left\n const top = el.top\n const width = el.width\n const height = el.height\n const right = left + width\n const bottom = top + height\n\n const topLine: AlignLine = { value: top, range: [left, right] }\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\n\n horizontalLines.push(topLine, bottomLine)\n verticalLines.push(leftLine, rightLine)\n }\n\n // 页面边界、水平和垂直的中心位置\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\n\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\n \n horizontalLines = uniqAlignLines(horizontalLines)\n verticalLines = uniqAlignLines(verticalLines)\n }\n \n // 对齐吸附方法\n const alignedAdsorption = (currentX: number | null, currentY: number | null) => {\n const sorptionRange = 5\n\n const _alignmentLines: AlignmentLineProps[] = []\n let isVerticalAdsorbed = false\n let isHorizontalAdsorbed = false\n const correctionVal = { offsetX: 0, offsetY: 0 }\n \n if(currentY || currentY === 0) {\n for(let i = 0; i < horizontalLines.length; i++) {\n const { value, range } = horizontalLines[i]\n const min = Math.min(...range, currentX || 0)\n const max = Math.max(...range, currentX || 0)\n \n if(Math.abs(currentY - value) < sorptionRange && !isHorizontalAdsorbed) {\n correctionVal.offsetY = currentY - value\n isHorizontalAdsorbed = true\n _alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })\n }\n }\n }\n if(currentX || currentX === 0) {\n for(let i = 0; i < verticalLines.length; i++) {\n const { value, range } = verticalLines[i]\n const min = Math.min(...range, (currentY || 0))\n const max = Math.max(...range, (currentY || 0))\n\n if(Math.abs(currentX - value) < sorptionRange && !isVerticalAdsorbed) {\n correctionVal.offsetX = currentX - value\n isVerticalAdsorbed = true\n _alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })\n }\n }\n }\n alignmentLines.value = _alignmentLines\n return correctionVal\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const x = currentPageX - startPageX\n const y = currentPageY - startPageY\n\n let width = elOriginWidth\n let height = elOriginHeight\n let left = elOriginLeft\n let top = elOriginTop\n \n // 元素被旋转的情况下\n if(elRotate) {\n // 根据元素旋转的角度,修正鼠标按下后移动的距离(因为拖动的方向发生了改变)\n const revisedX = (Math.cos(rotateRadian) * x + Math.sin(rotateRadian) * y) / canvasScale.value\n let revisedY = (Math.cos(rotateRadian) * y - Math.sin(rotateRadian) * x) / canvasScale.value\n\n // 锁定宽高比例\n if(fixedRatio) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) revisedY = revisedX / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) revisedY = -revisedX / aspectRatio\n }\n\n // 根据不同的操作点分别计算元素缩放后的大小和位置\n // 这里计算的位置是错误的,因为旋转后缩放实际上也改变了元素的位置,需要在后面进行矫正\n // 这里计算的大小是正确的,因为上面修正鼠标按下后移动的距离时其实已经进行过了矫正\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n height = getSizeWithinRange(elOriginHeight + revisedY)\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n height = getSizeWithinRange(elOriginHeight + revisedY)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n height = getSizeWithinRange(elOriginHeight - revisedY)\n left = elOriginLeft - (width - elOriginWidth)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n height = getSizeWithinRange(elOriginHeight - revisedY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.TOP) {\n height = getSizeWithinRange(elOriginHeight - revisedY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n height = getSizeWithinRange(elOriginHeight + revisedY)\n }\n else if(command === OperateResizeHandlers.LEFT) {\n width = getSizeWithinRange(elOriginWidth - revisedX)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n width = getSizeWithinRange(elOriginWidth + revisedX)\n }\n\n // 获取当前元素基点坐标,与初始状态的基点坐标进行对比并矫正差值\n const currentPoints = getRotateElementPoints({ width, height, left, top }, elRotate)\n const currentOppositePoint = getOppositePoint(command, currentPoints)\n const currentBaseLeft = currentOppositePoint.left\n const currentBaseTop = currentOppositePoint.top\n\n const offsetX = currentBaseLeft - baseLeft\n const offsetY = currentBaseTop - baseTop\n\n left = left - offsetX\n top = top - offsetY\n }\n\n // 元素未被旋转的情况下,根据所操纵点的位置添加对齐吸附\n else {\n let moveX = x / canvasScale.value\n let moveY = y / canvasScale.value\n\n if(fixedRatio) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) moveY = moveX / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) moveY = -moveX / aspectRatio\n }\n\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + elOriginHeight + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = moveY * aspectRatio\n else moveY = moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth + moveX)\n height = getSizeWithinRange(elOriginHeight + moveY)\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + elOriginHeight + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = -moveY * aspectRatio\n else moveY = -moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth - moveX)\n height = getSizeWithinRange(elOriginHeight + moveY)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + moveX, elOriginTop + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = moveY * aspectRatio\n else moveY = moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth - moveX)\n height = getSizeWithinRange(elOriginHeight - moveY)\n left = elOriginLeft - (width - elOriginWidth)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n const { offsetX, offsetY } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, elOriginTop + moveY)\n moveX = moveX - offsetX\n moveY = moveY - offsetY\n if(fixedRatio) {\n if(offsetY) moveX = -moveY * aspectRatio\n else moveY = -moveX / aspectRatio\n }\n width = getSizeWithinRange(elOriginWidth + moveX)\n height = getSizeWithinRange(elOriginHeight - moveY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.LEFT) {\n const { offsetX } = alignedAdsorption(elOriginLeft + moveX, null)\n moveX = moveX - offsetX\n width = getSizeWithinRange(elOriginWidth - moveX)\n left = elOriginLeft - (width - elOriginWidth)\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n const { offsetX } = alignedAdsorption(elOriginLeft + elOriginWidth + moveX, null)\n moveX = moveX - offsetX\n width = getSizeWithinRange(elOriginWidth + moveX)\n }\n else if(command === OperateResizeHandlers.TOP) {\n const { offsetY } = alignedAdsorption(null, elOriginTop + moveY)\n moveY = moveY - offsetY\n height = getSizeWithinRange(elOriginHeight - moveY)\n top = elOriginTop - (height - elOriginHeight)\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n const { offsetY } = alignedAdsorption(null, elOriginTop + elOriginHeight + moveY)\n moveY = moveY - offsetY\n height = getSizeWithinRange(elOriginHeight + moveY)\n }\n }\n \n elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, left, top, width, height } : el)\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n alignmentLines.value = []\n \n if(startPageX === e.pageX && startPageY === e.pageY) return\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n emitter.emit(EmitterEvents.SCALE_ELEMENT_STATE, false)\n \n addHistorySnapshot()\n }\n }\n\n const scaleMultiElement = (e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandlers) => {\n let isMouseDown = true\n \n const { minX, maxX, minY, maxY } = range\n const operateWidth = maxX - minX\n const operateHeight = maxY - minY\n const aspectRatio = operateWidth / operateHeight\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 鼠标按下后移动的距离\n const x = (currentPageX - startPageX) / canvasScale.value\n let y = (currentPageY - startPageY) / canvasScale.value\n\n // 锁定宽高比例\n if(ctrlOrShiftKeyActive.value) {\n if(command === OperateResizeHandlers.RIGHT_BOTTOM || command === OperateResizeHandlers.LEFT_TOP) y = x / aspectRatio\n if(command === OperateResizeHandlers.LEFT_BOTTOM || command === OperateResizeHandlers.RIGHT_TOP) y = -x / aspectRatio\n }\n\n // 获取鼠标缩放时当前所有激活元素的范围\n let currentMinX = minX\n let currentMaxX = maxX\n let currentMinY = minY\n let currentMaxY = maxY\n\n if(command === OperateResizeHandlers.RIGHT_BOTTOM) {\n currentMaxX = maxX + x\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT_BOTTOM) {\n currentMinX = minX + x\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT_TOP) {\n currentMinX = minX + x\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.RIGHT_TOP) {\n currentMaxX = maxX + x\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.TOP) {\n currentMinY = minY + y\n }\n else if(command === OperateResizeHandlers.BOTTOM) {\n currentMaxY = maxY + y\n }\n else if(command === OperateResizeHandlers.LEFT) {\n currentMinX = minX + x\n }\n else if(command === OperateResizeHandlers.RIGHT) {\n currentMaxX = maxX + x\n }\n\n // 多选下所有元素整体宽高\n const currentOppositeWidth = currentMaxX - currentMinX\n const currentOppositeHeight = currentMaxY - currentMinY\n\n // 所有元素的整体宽高与被操作元素宽高的比例\n let widthScale = currentOppositeWidth / operateWidth\n let heightScale = currentOppositeHeight / operateHeight\n\n if(widthScale <= 0) widthScale = 0\n if(heightScale <= 0) heightScale = 0\n \n // 根据上面计算的比例,修改所有被激活元素的位置大小\n // 宽高通过乘以对应的比例得到,位置通过将被操作元素在所有元素整体中的相对位置乘以对应比例获得\n elementList.value = elementList.value.map(el => {\n if((el.type === 'image' || el.type === 'shape') && activeElementIdList.value.includes(el.id)) {\n const originElement = originElementList.find(originEl => originEl.id === el.id) as PPTImageElement | PPTShapeElement\n return {\n ...el,\n width: originElement.width * widthScale,\n height: originElement.height * heightScale,\n left: currentMinX + (originElement.left - minX) * widthScale,\n top: currentMinY + (originElement.top - minY) * heightScale,\n }\n }\n return el\n })\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n if(startPageX === e.pageX && startPageY === e.pageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n scaleElement,\n scaleMultiElement,\n }\n}","import { Ref, computed } from 'vue'\nimport uniq from 'lodash/uniq'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n moveElement: (e: MouseEvent, element: PPTElement) => void,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const handleElementId = computed(() => store.state.handleElementId)\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n\n const selectElement = (e: MouseEvent, element: PPTElement, canMove = true) => {\n if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n\n // 如果被点击的元素处于未激活状态,则将他设置为激活元素(单选),或者加入到激活元素中(多选)\n if(!activeElementIdList.value.includes(element.id)) {\n let newActiveIdList: string[] = []\n\n if(ctrlOrShiftKeyActive.value) {\n newActiveIdList = [...activeElementIdList.value, element.id]\n }\n else newActiveIdList = [element.id]\n \n // 同时如果该元素是分组成员,需要将和他同组的元素一起激活\n if(element.groupId) {\n const groupMembersId: string[] = []\n elementList.value.forEach((el: PPTElement) => {\n if(el.groupId === element.groupId) groupMembersId.push(el.id)\n })\n newActiveIdList = [...newActiveIdList, ...groupMembersId]\n }\n\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, uniq(newActiveIdList))\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\n }\n\n // 如果被点击的元素已激活,且按下了多选按钮,则取消其激活状态(除非该元素或分组是最后的一个激活元素)\n else if(ctrlOrShiftKeyActive.value) {\n let newActiveIdList: string[] = []\n\n // 同时如果该元素是分组成员,需要将和他同组的元素一起取消\n if(element.groupId) {\n const groupMembersId: string[] = []\n elementList.value.forEach((el: PPTElement) => {\n if(el.groupId === element.groupId) groupMembersId.push(el.id)\n })\n newActiveIdList = activeElementIdList.value.filter(id => !groupMembersId.includes(id))\n }\n else {\n newActiveIdList = activeElementIdList.value.filter(id => id !== element.id)\n }\n\n if(newActiveIdList.length > 0) {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveIdList)\n }\n }\n\n // 如果被点击的元素已激活,且没有按下多选按钮,且该元素不是当前操作元素,则将其设置为当前操作元素\n else if(handleElementId.value !== element.id) {\n store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)\n }\n\n // 如果被点击的元素是当前操作元素,且没有按下多选按钮,则该元素下次保持该状态再次被点击时,将被设置为多选元素中的激活成员\n else if(activeGroupElementId.value !== element.id) {\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n ;(e.target as HTMLElement).onmouseup = (e: MouseEvent) => {\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n if(startPageX === currentPageX && startPageY === currentPageY) {\n activeGroupElementId.value = element.id\n ;(e.target as HTMLElement).onmouseup = null\n }\n }\n }\n\n if(canMove) moveElement(e, element)\n }\n\n const selectAllElement = () => {\n const unlockedElements = elementList.value.filter(el => !el.lock)\n const newActiveElementIdList = unlockedElements.map(el => el.id)\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)\n }\n\n return {\n selectElement,\n selectAllElement,\n }\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { AlignmentLineProps } from '@/types/edit'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default (\n elementList: Ref,\n activeGroupElementId: Ref,\n alignmentLines: Ref,\n) => {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const dragElement = (e: MouseEvent, element: PPTElement) => {\n if(!activeElementIdList.value.includes(element.id)) return\n let isMouseDown = true\n\n // 可视范围宽高,用于边缘对齐吸附\n const edgeWidth = VIEWPORT_SIZE\n const edgeHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n\n const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))\n const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))\n\n const sorptionRange = 5\n const elOriginLeft = element.left\n const elOriginTop = element.top\n const elOriginWidth = element.width\n const elOriginHeight = ('height' in element && element.height) ? element.height : 0\n const elOriginRotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n let isMisoperation: boolean | null = null\n\n const isActiveGroupElement = element.id === activeGroupElementId.value\n\n // 收集对齐参考线\n // 包括页面内出被操作元素以外的所有元素在页面内水平和垂直方向的范围和中心位置、页面边界和水平和垂直的中心位置\n let horizontalLines: AlignLine[] = []\n let verticalLines: AlignLine[] = []\n\n // 元素在页面内水平和垂直方向的范围和中心位置(需要特殊计算线条和被旋转的元素)\n for(const el of elementList.value) {\n if(el.type === 'line') continue\n if(isActiveGroupElement && el.id === element.id) continue\n if(!isActiveGroupElement && activeElementIdList.value.includes(el.id)) continue\n\n let left, top, width, height\n if('rotate' in el && el.rotate) {\n const { xRange, yRange } = getRectRotatedRange({\n left: el.left,\n top: el.top,\n width: el.width,\n height: el.height,\n rotate: el.rotate,\n })\n left = xRange[0]\n top = yRange[0]\n width = xRange[1] - xRange[0]\n height = yRange[1] - yRange[0]\n }\n else {\n left = el.left\n top = el.top\n width = el.width\n height = el.height\n }\n \n const right = left + width\n const bottom = top + height\n const centerX = top + height / 2\n const centerY = left + width / 2\n\n const topLine: AlignLine = { value: top, range: [left, right] }\n const bottomLine: AlignLine = { value: bottom, range: [left, right] }\n const horizontalCenterLine: AlignLine = { value: centerX, range: [left, right] }\n const leftLine: AlignLine = { value: left, range: [top, bottom] }\n const rightLine: AlignLine = { value: right, range: [top, bottom] }\n const verticalCenterLine: AlignLine = { value: centerY, range: [top, bottom] }\n\n horizontalLines.push(topLine, bottomLine, horizontalCenterLine)\n verticalLines.push(leftLine, rightLine, verticalCenterLine)\n }\n\n // 页面边界、水平和垂直的中心位置\n const edgeTopLine: AlignLine = { value: 0, range: [0, edgeWidth] }\n const edgeBottomLine: AlignLine = { value: edgeHeight, range: [0, edgeWidth] }\n const edgeHorizontalCenterLine: AlignLine = { value: edgeHeight / 2, range: [0, edgeWidth] }\n const edgeLeftLine: AlignLine = { value: 0, range: [0, edgeHeight] }\n const edgeRightLine: AlignLine = { value: edgeWidth, range: [0, edgeHeight] }\n const edgeVerticalCenterLine: AlignLine = { value: edgeWidth / 2, range: [0, edgeHeight] }\n\n horizontalLines.push(edgeTopLine, edgeBottomLine, edgeHorizontalCenterLine)\n verticalLines.push(edgeLeftLine, edgeRightLine, edgeVerticalCenterLine)\n \n // 参考线去重\n horizontalLines = uniqAlignLines(horizontalLines)\n verticalLines = uniqAlignLines(verticalLines)\n\n document.onmousemove = e => {\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对于鼠标第一次滑动距离过小的操作判定为误操作\n // 这里仅在误操作标记未被赋值(null,第一次触发移动),以及被标记为误操作时(true,当前处于误操作范围,但可能会脱离该范围转变成正常操作),才会去计算\n // 已经被标记为非误操作时(false),不需要再次计算(因为不可能从非误操作转变成误操作)\n if(isMisoperation !== false) {\n isMisoperation = Math.abs(startPageX - currentPageX) < sorptionRange && \n Math.abs(startPageY - currentPageY) < sorptionRange\n }\n if(!isMouseDown || isMisoperation) return\n\n // 鼠标按下后移动的距离\n const moveX = (currentPageX - startPageX) / canvasScale.value\n const moveY = (currentPageY - startPageY) / canvasScale.value\n\n // 被操作元素需要移动到的位置\n let targetLeft = elOriginLeft + moveX\n let targetTop = elOriginTop + moveY\n\n // 计算被操作元素在页面中的范围(用于吸附对齐)\n // 需要区分计算:多选状态、线条、被旋转的元素\n // 注意这里需要用元素的原始信息结合移动信息来计算\n let targetMinX: number, targetMaxX: number, targetMinY: number, targetMaxY: number\n\n if(activeElementIdList.value.length === 1 || isActiveGroupElement) {\n if(elOriginRotate) {\n const { xRange, yRange } = getRectRotatedRange({\n left: targetLeft,\n top: targetTop,\n width: elOriginWidth,\n height: elOriginHeight,\n rotate: elOriginRotate,\n })\n targetMinX = xRange[0]\n targetMaxX = xRange[1]\n targetMinY = yRange[0]\n targetMaxY = yRange[1]\n }\n else if(element.type === 'line') {\n targetMinX = targetLeft\n targetMaxX = targetLeft + Math.max(element.start[0], element.end[0])\n targetMinY = targetTop\n targetMaxY = targetTop + Math.max(element.start[1], element.end[1])\n }\n else {\n targetMinX = targetLeft\n targetMaxX = targetLeft + elOriginWidth\n targetMinY = targetTop\n targetMaxY = targetTop + elOriginHeight\n }\n }\n else {\n const leftValues = []\n const topValues = []\n const rightValues = []\n const bottomValues = []\n \n for(let i = 0; i < originActiveElementList.length; i++) {\n const element = originActiveElementList[i]\n const left = element.left + moveX\n const top = element.top + moveY\n const width = element.width\n const height = ('height' in element && element.height) ? element.height : 0\n const rotate = ('rotate' in element && element.rotate) ? element.rotate : 0\n\n if('rotate' in element && element.rotate) {\n const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })\n leftValues.push(xRange[0])\n topValues.push(yRange[0])\n rightValues.push(xRange[1])\n bottomValues.push(yRange[1])\n }\n else if(element.type === 'line') {\n leftValues.push(left)\n topValues.push(top)\n rightValues.push(left + Math.max(element.start[0], element.end[0]))\n bottomValues.push(top + Math.max(element.start[1], element.end[1]))\n }\n else {\n leftValues.push(left)\n topValues.push(top)\n rightValues.push(left + width)\n bottomValues.push(top + height)\n }\n }\n\n targetMinX = Math.min(...leftValues)\n targetMaxX = Math.max(...rightValues)\n targetMinY = Math.min(...topValues)\n targetMaxY = Math.max(...bottomValues)\n }\n \n const targetCenterX = targetMinX + (targetMaxX - targetMinX) / 2\n const targetCenterY = targetMinY + (targetMaxY - targetMinY) / 2\n\n // 根据收集到的参考线,分别执行垂直和水平两个方向的对齐吸附\n const _alignmentLines: AlignmentLineProps[] = []\n let isVerticalAdsorbed = false\n let isHorizontalAdsorbed = false\n for(let i = 0; i < horizontalLines.length; i++) {\n const { value, range } = horizontalLines[i]\n const min = Math.min(...range, targetMinX, targetMaxX)\n const max = Math.max(...range, targetMinX, targetMaxX)\n \n if(Math.abs(targetMinY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetMinY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n if(Math.abs(targetMaxY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetMaxY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n if(Math.abs(targetCenterY - value) < sorptionRange && !isHorizontalAdsorbed) {\n targetTop = targetTop - (targetCenterY - value)\n isHorizontalAdsorbed = true\n _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})\n }\n }\n for(let i = 0; i < verticalLines.length; i++) {\n const { value, range } = verticalLines[i]\n const min = Math.min(...range, targetMinY, targetMaxY)\n const max = Math.max(...range, targetMinY, targetMaxY)\n\n if(Math.abs(targetMinX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetMinX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n if(Math.abs(targetMaxX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetMaxX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n if(Math.abs(targetCenterX - value) < sorptionRange && !isVerticalAdsorbed) {\n targetLeft = targetLeft - (targetCenterX - value)\n isVerticalAdsorbed = true\n _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})\n }\n }\n alignmentLines.value = _alignmentLines\n \n // 非多选,或者当前操作的元素时激活的组合元素\n if(activeElementIdList.value.length === 1 || isActiveGroupElement) {\n elementList.value = elementList.value.map(el => {\n return el.id === element.id ? { ...el, left: targetLeft, top: targetTop } : el\n })\n }\n\n // 修改元素位置,如果需要修改位置的元素不是被操作的元素(例如多选下的操作)\n // 那么其他非操作元素要移动的位置通过操作元素的移动偏移量计算\n else {\n const handleElement = elementList.value.find(el => el.id === element.id)\n if(!handleElement) return\n\n elementList.value = elementList.value.map(el => {\n if(activeElementIdList.value.includes(el.id)) {\n if(el.id === element.id) {\n return {\n ...el,\n left: targetLeft,\n top: targetTop,\n }\n }\n return {\n ...el,\n left: el.left + (targetLeft - handleElement.left),\n top: el.top + (targetTop - handleElement.top),\n }\n }\n return el\n })\n }\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n alignmentLines.value = []\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对比初始位置,没有实际的位移不更新数据\n if(startPageX === currentPageX && startPageY === currentPageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n dragElement,\n }\n}","import { Ref, computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTLineElement } from '@/types/slides'\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\ninterface AdsorptionPoint {\n x: number;\n y: number;\n}\n\nexport default (elementList: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {\n let isMouseDown = true\n\n const sorptionRange = 8\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const adsorptionPoints: AdsorptionPoint[] = []\n\n // 获取全部非线条且未旋转元素的8个点作为吸附点\n for(let i = 0; i < elementList.value.length; i++) {\n const _element = elementList.value[i]\n if(_element.type === 'line' || ('rotate' in _element && _element.rotate)) continue\n\n const left = _element.left\n const top = _element.top\n const width = _element.width\n const height = _element.height\n \n const right = left + width\n const bottom = top + height\n const centerX = top + height / 2\n const centerY = left + width / 2\n\n const topPoint = { x: centerY, y: top }\n const bottomPoint = { x: centerY, y: bottom }\n const leftPoint = { x: left, y: centerX }\n const rightPoint = { x: right, y: centerX }\n\n const leftTopPoint = { x: left, y: top }\n const rightTopPoint = { x: right, y: top }\n const leftBottomPoint = { x: left, y: bottom }\n const rightBottomPoint = { x: right, y: bottom }\n\n adsorptionPoints.push(\n topPoint,\n bottomPoint,\n leftPoint,\n rightPoint,\n leftTopPoint,\n rightTopPoint,\n leftBottomPoint,\n rightBottomPoint,\n )\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 鼠标按下后移动的距离\n const moveX = (currentPageX - startPageX) / canvasScale.value\n const moveY = (currentPageY - startPageY) / canvasScale.value\n \n // 线条两个端点(起点和终点)基于编辑区域的位置\n let startX = element.left + element.start[0]\n let startY = element.top + element.start[1]\n let endX = element.left + element.end[0]\n let endY = element.top + element.end[1]\n\n // 根据拖拽的点,选择修改起点或终点的位置\n // 两点在水平和垂直方向上有对齐吸附\n // 靠近其他元素的吸附点有对齐吸附\n if(command === OperateLineHandlers.START) {\n startX = startX + moveX\n startY = startY + moveY\n\n if(Math.abs(startX - endX) < sorptionRange) startX = endX\n if(Math.abs(startY - endY) < sorptionRange) startY = endY\n\n for(const adsorptionPoint of adsorptionPoints) {\n const { x, y } = adsorptionPoint\n if(Math.abs(x - startX) < sorptionRange && Math.abs(y - startY) < sorptionRange) {\n startX = x\n startY = y\n break\n }\n }\n }\n else {\n endX = endX + moveX\n endY = endY + moveY\n\n if(Math.abs(startX - endX) < sorptionRange) endX = startX\n if(Math.abs(startY - endY) < sorptionRange) endY = startY\n\n for(const adsorptionPoint of adsorptionPoints) {\n const { x, y } = adsorptionPoint\n if(Math.abs(x - endX) < sorptionRange && Math.abs(y - endY) < sorptionRange) {\n endX = x\n endY = y\n break\n }\n }\n }\n\n // 计算两个端点基于自身元素位置的坐标\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n const start: [number, number] = [0, 0]\n const end: [number, number] = [maxX - minX, maxY - minY]\n if(startX > endX) {\n start[0] = maxX - minX\n end[0] = 0\n }\n if(startY > endY) {\n start[1] = maxY - minY\n end[1] = 0\n }\n\n // 修改线条的位置和两点的坐标\n elementList.value = elementList.value.map(el => {\n if(el.id === element.id) {\n return {\n ...el,\n left: minX,\n top: minY,\n start: start,\n end: end,\n }\n }\n return el\n })\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n // 对比原始鼠标位置,没有实际的位移不更新数据\n if(startPageX === currentPageX && startPageY === currentPageY) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })\n addHistorySnapshot()\n }\n }\n\n return {\n dragLineElement,\n }\n}","import { computed, Ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { CreateElementSelectionData, CreatingLineElement, CreatingShapeElement } from '@/types/edit'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nexport default (viewportRef: Ref) => {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const creatingElement = computed(() => store.state.creatingElement)\n\n const formatCreateSelection = (selectionData: CreateElementSelectionData) => {\n const { start, end } = selectionData\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const [startX, startY] = start\n const [endX, endY] = end\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const left = (minX - viewportRect.x) / canvasScale.value\n const top = (minY - viewportRect.y) / canvasScale.value\n const width = (maxX - minX) / canvasScale.value\n const height = (maxY - minY) / canvasScale.value\n\n return { left, top, width, height }\n }\n\n const formatCreateSelectionForLine = (selectionData: CreateElementSelectionData) => {\n const { start, end } = selectionData\n\n if(!viewportRef.value) return\n const viewportRect = viewportRef.value.getBoundingClientRect()\n\n const [startX, startY] = start\n const [endX, endY] = end\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const left = (minX - viewportRect.x) / canvasScale.value\n const top = (minY - viewportRect.y) / canvasScale.value\n const width = (maxX - minX) / canvasScale.value\n const height = (maxY - minY) / canvasScale.value\n\n const _start: [number, number] = [\n startX === minX ? 0 : width,\n startY === minY ? 0 : height,\n ]\n const _end: [number, number] = [\n endX === minX ? 0 : width,\n endY === minY ? 0 : height,\n ]\n\n return {\n left,\n top,\n start: _start,\n end: _end,\n }\n }\n\n const { createTextElement, createShapeElement, createLineElement } = useCreateElement()\n\n const insertElementFromCreateSelection = (selectionData: CreateElementSelectionData) => {\n if(!creatingElement.value) return\n\n const type = creatingElement.value.type\n if(type === 'text') {\n const position = formatCreateSelection(selectionData)\n position && createTextElement(position)\n }\n else if(type === 'shape') {\n const position = formatCreateSelection(selectionData)\n position && createShapeElement(position, (creatingElement.value as CreatingShapeElement).data)\n }\n else if(type === 'line') {\n const position = formatCreateSelectionForLine(selectionData)\n position && createLineElement(position, (creatingElement.value as CreatingLineElement).data)\n }\n store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\n }\n\n return {\n insertElementFromCreateSelection,\n }\n}","\n\n","import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\n\nexport interface PPTElementShadow {\n h: number;\n v: number;\n blur: number;\n color: string;\n}\n\nexport const enum ElementTypes {\n TEXT = 'text',\n IMAGE = 'image',\n SHAPE = 'shape',\n LINE = 'line',\n CHART = 'chart',\n TABLE = 'table',\n}\n\nexport interface PPTElementOutline {\n style?: 'dashed' | 'solid';\n width?: number;\n color?: string;\n}\n\nexport interface PPTTextElement {\n type: 'text';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n content: string;\n rotate?: number;\n outline?: PPTElementOutline;\n fill?: string;\n lineHeight?: number;\n wordSpace?: number;\n opacity?: number;\n shadow?: PPTElementShadow;\n}\n\nexport interface ImageElementFilters {\n 'blur'?: string;\n 'brightness'?: string;\n 'contrast'?: string;\n 'grayscale'?: string;\n 'saturate'?: string;\n 'hue-rotate'?: string;\n 'opacity'?: string;\n}\nexport interface PPTImageElement {\n type: 'image';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n fixedRatio: boolean;\n src: string;\n rotate?: number;\n outline?: PPTElementOutline;\n filters?: ImageElementFilters;\n clip?: {\n range: [[number, number], [number, number]];\n shape: 'rect' | 'roundRect' | 'ellipse' | 'triangle' | 'pentagon' | 'rhombus' | 'star';\n };\n flip?: { x?: number; y?: number };\n shadow?: PPTElementShadow;\n}\n\nexport interface ShapeGradient {\n type: 'linear' | 'radial';\n color: [string, string];\n rotate: number;\n}\nexport interface PPTShapeElement {\n type: 'shape';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n viewBox: number;\n path: string;\n fixedRatio: boolean;\n fill: string;\n gradient?: ShapeGradient;\n rotate?: number;\n outline?: PPTElementOutline;\n opacity?: number;\n shadow?: PPTElementShadow;\n}\n\nexport interface PPTLineElement {\n type: 'line';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n start: [number, number];\n end: [number, number];\n width: number;\n style: string;\n color: string;\n points: [string, string];\n shadow?: PPTElementShadow;\n}\n\nexport type ChartType = 'bar' | 'line' | 'pie'\nexport interface ChartData {\n labels: string[];\n series: number[][];\n}\nexport interface PPTChartElement {\n type: 'chart';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n fill?: string;\n chartType: ChartType;\n data: ChartData;\n options?: ILineChartOptions & IBarChartOptions & IPieChartOptions;\n outline?: PPTElementOutline;\n themeColor: string;\n gridColor?: string;\n}\n\nexport interface TableCellStyle {\n bold?: boolean;\n em?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n color?: string;\n backcolor?: string;\n fontsize?: string;\n fontname?: string;\n align?: string;\n}\nexport interface TableCell {\n id: string;\n colspan: number;\n rowspan: number;\n text: string;\n style?: TableCellStyle;\n}\nexport interface TableTheme {\n color: string;\n rowHeader: boolean;\n rowFooter: boolean;\n colHeader: boolean;\n colFooter: boolean;\n} \nexport interface PPTTableElement {\n type: 'table';\n id: string;\n left: number;\n top: number;\n lock?: boolean;\n groupId?: string;\n width: number;\n height: number;\n outline: PPTElementOutline;\n theme?: TableTheme;\n colWidths: number[];\n data: TableCell[][];\n}\n\nexport type PPTElement = PPTTextElement | PPTImageElement | PPTShapeElement | PPTLineElement | PPTChartElement | PPTTableElement\n\nexport interface PPTAnimation {\n elId: string;\n type: string;\n duration: number;\n}\n\nexport interface SlideBackground {\n type: 'solid' | 'image' | 'gradient';\n color?: string;\n image?: string;\n imageSize?: 'cover' | 'contain' | 'repeat' | 'initial';\n gradientType?: 'linear' | 'radial';\n gradientColor?: [string, string];\n gradientRotate?: number;\n}\n\nexport interface Slide {\n id: string;\n elements: PPTElement[];\n background?: SlideBackground;\n animations?: PPTAnimation[];\n turningMode?: 'no' | 'fade' | 'slideX' | 'slideY';\n}\n\nexport interface SlideTheme {\n backgroundColor: string;\n themeColor: string;\n fontColor: string;\n fontName: string;\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default () => {\n const store = useStore()\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n // 获取组合元素层级范围(组合成员中的最大层级和最小层级)\n const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {\n const minIndex = elementList.findIndex(_element => _element.id === combineElementList[0].id)\n const maxIndex = elementList.findIndex(_element => _element.id === combineElementList[combineElementList.length - 1].id)\n return { minIndex, maxIndex }\n }\n\n // 上移一层,返回移动后新的元素列表(下移一层逻辑类似)\n const moveUpElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n // 被操作的元素是组合元素成员\n if(element.groupId) {\n\n // 获取该组合元素全部成员,以及组合元素层级范围\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex, maxIndex } = getCombineElementIndexRange(elementList, combineElementList)\n\n // 无法移动(已经处在顶层)\n if(maxIndex === elementList.length - 1) return null\n\n // 该组合元素上一层的元素,以下简称为【元素next】\n const nextElement = copyOfElementList[maxIndex + 1]\n\n // 从元素列表中移除该组合元素全部成员\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n\n // 如果【元素next】也是组合元素成员(另一个组合,不是上面被移除的那一组,以下简称为【组合next】)\n // 需要获取【组合next】全部成员的长度,将上面移除的组合元素全部成员添加到【组合next】全部成员的上方\n if(nextElement.groupId) {\n const nextCombineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\n copyOfElementList.splice(minIndex + nextCombineElementList.length, 0, ...movedElementList)\n }\n\n // 如果【元素next】是单独的元素(非组合成员),将上面移除的组合元素全部成员添加到【元素next】上方\n else copyOfElementList.splice(minIndex + 1, 0, ...movedElementList)\n }\n\n // 被操作的元素是单独的元素(非组合成员)\n else {\n\n // 元素在元素列表中的层级\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n\n // 无法移动(已经处在顶层)\n if(elementIndex === elementList.length - 1) return null\n\n // 上一层的元素,以下简称为【元素next】\n const nextElement = copyOfElementList[elementIndex + 1]\n\n // 从元素列表中移除被操作的元素\n const movedElement = copyOfElementList.splice(elementIndex, 1)[0]\n\n // 如果【元素next】是组合元素成员\n // 需要获取该组合全部成员的长度,将上面移除的元素添加到该组合全部成员的上方\n if(nextElement.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === nextElement.groupId)\n copyOfElementList.splice(elementIndex + combineElementList.length, 0, movedElement)\n }\n\n // 如果【元素next】是单独的元素(非组合成员),将上面移除的元素添加到【元素next】上方\n else copyOfElementList.splice(elementIndex + 1, 0, movedElement)\n }\n\n return copyOfElementList\n }\n\n // 下移一层\n const moveDownElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n if(element.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex } = getCombineElementIndexRange(elementList, combineElementList)\n if(minIndex === 0) return null\n const prevElement = copyOfElementList[minIndex - 1]\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n if(prevElement.groupId) {\n const prevCombineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\n copyOfElementList.splice(minIndex - prevCombineElementList.length, 0, ...movedElementList)\n }\n else copyOfElementList.splice(minIndex - 1, 0, ...movedElementList)\n }\n\n else {\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n if(elementIndex === 0) return null\n const prevElement = copyOfElementList[elementIndex - 1]\n const movedElement = copyOfElementList.splice(elementIndex, 1)[0]\n if(prevElement.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === prevElement.groupId)\n copyOfElementList.splice(elementIndex - combineElementList.length, 0, movedElement)\n }\n else copyOfElementList.splice(elementIndex - 1, 0, movedElement)\n }\n\n return copyOfElementList\n }\n\n // 置顶层,返回移动后新的元素列表(置底层逻辑类似)\n const moveTopElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n // 被操作的元素是组合元素成员\n if(element.groupId) {\n\n // 获取该组合元素全部成员,以及组合元素层级范围\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex, maxIndex } = getCombineElementIndexRange(elementList, combineElementList)\n\n // 无法移动(已经处在顶层)\n if(maxIndex === elementList.length - 1) return null\n\n // 从元素列表中移除该组合元素全部成员,然后添加到元素列表最上方\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n copyOfElementList.push(...movedElementList)\n }\n\n // 被操作的元素是单独的元素(非组合成员)\n else {\n\n // 元素在元素列表中的层级\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n\n // 无法移动(已经处在顶层)\n if(elementIndex === elementList.length - 1) return null\n\n // 从元素列表中移除该元素,然后添加到元素列表最上方\n copyOfElementList.splice(elementIndex, 1)\n copyOfElementList.push(element)\n }\n\n return copyOfElementList\n }\n\n // 置底层\n const moveBottomElement = (elementList: PPTElement[], element: PPTElement) => {\n const copyOfElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))\n\n if(element.groupId) {\n const combineElementList = copyOfElementList.filter(_element => _element.groupId === element.groupId)\n const { minIndex } = getCombineElementIndexRange(elementList, combineElementList)\n if(minIndex === 0) return null\n const movedElementList = copyOfElementList.splice(minIndex, combineElementList.length)\n copyOfElementList.unshift(...movedElementList)\n }\n\n else {\n const elementIndex = elementList.findIndex(item => item.id === element.id)\n if(elementIndex === 0) return null\n copyOfElementList.splice(elementIndex, 1)\n copyOfElementList.unshift(element)\n }\n\n return copyOfElementList\n }\n\n const orderElement = (element: PPTElement, command: ElementOrderCommand) => {\n let newElementList = null\n \n if(command === ElementOrderCommands.UP) newElementList = moveUpElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.DOWN) newElementList = moveDownElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.TOP) newElementList = moveTopElement(currentSlide.value.elements, element)\n else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)\n\n if(!newElementList) return\n\n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n addHistorySnapshot()\n }\n\n return {\n orderElement,\n }\n}","export const enum ClipPathTypes {\n RECT = 'rect',\n ELLIPSE = 'ellipse',\n POLYGON = 'polygon',\n}\n\nexport const enum ClipPaths {\n RECT = 'rect',\n ROUNDRECT = 'roundRect',\n ELLIPSE = 'ellipse',\n TRIANGLE = 'triangle',\n PENTAGON = 'pentagon',\n RHOMBUS = 'rhombus',\n STAR = 'star',\n}\n\nexport const CLIPPATHS = {\n rect: {\n name: '矩形',\n type: ClipPathTypes.RECT,\n radius: '0',\n style: '',\n },\n rect2: {\n name: '矩形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 0 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L 0 ${height} Z`\n },\n },\n rect3: {\n name: '矩形3',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 80% 0%, 100% 20%, 100% 100%, 20% 100%, 0% 80%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width * 0.8} 0 L ${width} ${height * 0.2} L ${width} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.8} Z`\n },\n },\n roundRect: {\n name: '圆角矩形',\n type: ClipPathTypes.RECT,\n radius: '10%',\n style: 'inset(0 0 0 0 round 10% 10% 10% 10%)',\n },\n ellipse: {\n name: '圆形',\n type: ClipPathTypes.ELLIPSE,\n style: 'ellipse(50% 50% at 50% 50%)',\n },\n triangle: {\n name: '三角形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 0% 100%, 100% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L 0 ${height} L ${width} ${height} Z`\n },\n },\n triangle2: {\n name: '三角形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 100%, 0% 0%, 100% 0%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} ${height} L 0 0 L ${width} 0 Z`\n },\n },\n triangle3: {\n name: '三角形3',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 0% 100%, 100% 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L 0 ${height} L ${width} ${height} Z`\n },\n },\n rhombus: {\n name: '菱形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L ${width} ${height * 0.5} L ${width * 0.5} ${height} L 0 ${height * 0.5} Z`\n },\n },\n hexagon: {\n name: '六边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.2} 0 L ${width * 0.8} 0 L ${width} ${height * 0.5} L ${width * 0.8} ${height} L ${width * 0.2} ${height} L 0 ${height * 0.5} Z`\n },\n },\n pentagon: {\n name: '五边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.5} 0 L ${width} ${0.38 * height} L ${0.82 * width} ${height} L ${0.18 * width} ${height} L 0 ${0.38 * height} Z`\n },\n },\n parallelogram: {\n name: '平行四边形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(30% 0%, 100% 0%, 70% 100%, 0% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.3} 0 L ${width} 0 L ${width * 0.7} ${height} L 0 ${height} Z`\n },\n },\n parallelogram2: {\n name: '平行四边形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(30% 100%, 100% 100%, 70% 0%, 0% 0%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.3} ${height} L ${width} ${height} L ${width * 0.7} 0 L 0 0 Z`\n },\n },\n trapezoid: {\n name: '梯形',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(25% 0%, 75% 0%, 100% 100%, 0% 100%)',\n createPath: (width: number, height: number) => {\n return `M ${width * 0.25} 0 L ${width * 0.75} 0 L ${width} ${height} L 0 ${height} Z`\n },\n },\n trapezoid2: {\n name: '梯形2',\n type: ClipPathTypes.POLYGON,\n style: 'polygon(0% 0%, 100% 0%, 75% 100%, 25% 100%)',\n createPath: (width: number, height: number) => {\n return `M 0 0 L ${width} 0 L ${width * 0.75} ${height} L ${width * 0.25} ${height} Z`\n },\n },\n}","import { computed } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\nimport { getElementListRange } from '@/utils/element'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\n\nexport default () => {\n const store = useStore()\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const alignElementToCanvas = (command: ElementAlignCommand) => {\n const viewportWidth = VIEWPORT_SIZE\n const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\n \n const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n for(const element of newElementList) {\n if(!activeElementIdList.value.includes(element.id)) continue\n \n if(command === ElementAlignCommands.TOP) {\n const offsetY = minY - 0\n element.top = element.top - offsetY \n }\n else if(command === ElementAlignCommands.VERTICAL) {\n const offsetY = minY + (maxY - minY) / 2 - viewportHeight / 2\n element.top = element.top - offsetY \n }\n else if(command === ElementAlignCommands.BOTTOM) {\n const offsetY = maxY - viewportHeight\n element.top = element.top - offsetY \n }\n \n else if(command === ElementAlignCommands.LEFT) {\n const offsetX = minX - 0\n element.left = element.left - offsetX \n }\n else if(command === ElementAlignCommands.HORIZONTAL) {\n const offsetX = minX + (maxX - minX) / 2 - viewportWidth / 2\n element.left = element.left - offsetX \n }\n else if(command === ElementAlignCommands.RIGHT) {\n const offsetX = maxX - viewportWidth\n element.left = element.left - offsetX \n }\n }\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })\n }\n\n return {\n alignElementToCanvas,\n }\n}","\n\n\n\n\n","import { ref, Ref, watchEffect } from 'vue'\nimport { PPTElementShadow } from '@/types/slides'\n\nexport default (shadow: Ref) => {\n const shadowStyle = ref('')\n\n watchEffect(() => {\n if(shadow.value) {\n const { h, v, blur, color } = shadow.value\n shadowStyle.value = `${h}px ${v}px ${blur}px ${color}`\n }\n else shadowStyle.value = ''\n })\n\n return {\n shadowStyle,\n }\n}","\n\n\n\n","import { computed, Ref } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\n\nexport default (outline: Ref) => {\n const outlineWidth = computed(() => (outline.value && outline.value.width !== undefined) ? outline.value.width : 0)\n const outlineStyle = computed(() => (outline.value && outline.value.style !== undefined) ? outline.value.style : 'solid')\n const outlineColor = computed(() => (outline.value && outline.value.color !== undefined) ? outline.value.color : '#d14424')\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n}","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-rect-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n radius: {\n type: String,\n default: '0',\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImageRectOutline.vue?vue&type=template&id=4efc595a&scoped=true\"\nimport script from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageRectOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageRectOutline.vue?vue&type=style&index=0&id=4efc595a&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4efc595a\"\n\nexport default script","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-ellipse-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImageEllipseOutline.vue?vue&type=template&id=4a286c0d&scoped=true\"\nimport script from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageEllipseOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageEllipseOutline.vue?vue&type=style&index=0&id=4a286c0d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4a286c0d\"\n\nexport default script","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'image-polygon-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n createPath: {\n type: Function,\n required: true,\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ImagePolygonOutline.vue?vue&type=template&id=0a37b709&scoped=true\"\nimport script from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ImagePolygonOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ImagePolygonOutline.vue?vue&type=style&index=0&id=0a37b709&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0a37b709\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'\nimport { useStore } from '@/store'\nimport { KEYS } from '@/configs/hotkey'\nimport { ImageClipData, ImageClipDataRange, ImageClipedEmitData } from '@/types/edit'\n\ntype ScaleClipRangeType = 't-l' | 't-r' | 'b-l' | 'b-r'\n\nexport default defineComponent({\n name: 'image-clip-handler',\n props: {\n src: {\n type: String,\n required: true,\n },\n clipData: {\n type: Object as PropType,\n },\n clipPath: {\n type: String,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n top: {\n type: Number,\n required: true,\n },\n left: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const topImgWrapperPosition = reactive({\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n })\n const clipWrapperPositionStyle = reactive({\n top: '0',\n left: '0',\n })\n const isSettingClipRange = ref(false)\n const currentRange = ref(null)\n\n const getClipDataTransformInfo = () => {\n const [start, end] = props.clipData ? props.clipData.range : [[0, 0], [100, 100]]\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return { widthScale, heightScale, left, top }\n }\n\n const imgPosition = computed(() => {\n const { widthScale, heightScale, left, top } = getClipDataTransformInfo()\n return {\n left: -left,\n top: -top,\n width: 100 / widthScale,\n height: 100 / heightScale,\n }\n })\n\n const bottomImgPositionStyle = computed(() => {\n return {\n top: imgPosition.value.top + '%',\n left: imgPosition.value.left + '%',\n width: imgPosition.value.width + '%',\n height: imgPosition.value.height + '%',\n }\n })\n\n const topImgWrapperPositionStyle = computed(() => {\n return {\n top: topImgWrapperPosition.top + '%',\n left: topImgWrapperPosition.left + '%',\n width: topImgWrapperPosition.width + '%',\n height: topImgWrapperPosition.height + '%',\n }\n })\n\n const topImgPositionStyle = computed(() => {\n const bottomWidth = imgPosition.value.width\n const bottomHeight = imgPosition.value.height\n \n const topLeft = topImgWrapperPosition.left\n const topTop = topImgWrapperPosition.top\n const topWidth = topImgWrapperPosition.width\n const topHeight = topImgWrapperPosition.height\n \n return {\n left: -topLeft * (100 / topWidth) + '%',\n top: -topTop * (100 / topHeight) + '%',\n width: bottomWidth / topWidth * 100 + '%',\n height: bottomHeight / topHeight * 100 + '%',\n }\n })\n\n const initClipPosition = () => {\n const { left, top } = getClipDataTransformInfo()\n topImgWrapperPosition.left = left\n topImgWrapperPosition.top = top\n topImgWrapperPosition.width = 100\n topImgWrapperPosition.height = 100\n \n clipWrapperPositionStyle.top = -top + '%'\n clipWrapperPositionStyle.left = -left + '%'\n }\n\n const handleClip = () => {\n if(isSettingClipRange.value) return\n\n if(!currentRange.value) {\n emit('clip', null)\n return\n }\n\n const { left, top } = getClipDataTransformInfo()\n\n const position = {\n left: (topImgWrapperPosition.left - left) / 100 * props.width,\n top: (topImgWrapperPosition.top - top) / 100 * props.height,\n width: (topImgWrapperPosition.width - 100) / 100 * props.width,\n height: (topImgWrapperPosition.height - 100) / 100 * props.height,\n }\n\n const clipedEmitData: ImageClipedEmitData = {\n range: currentRange.value,\n position,\n }\n emit('clip', clipedEmitData)\n }\n\n const keyboardClip = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(key === KEYS.ENTER) handleClip()\n }\n\n onMounted(() => {\n initClipPosition()\n document.addEventListener('keydown', keyboardClip)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keyboardClip)\n })\n\n const getRange = () => {\n const retPosition = {\n left: parseInt(topImgPositionStyle.value.left),\n top: parseInt(topImgPositionStyle.value.top),\n width: parseInt(topImgPositionStyle.value.width),\n height: parseInt(topImgPositionStyle.value.height),\n }\n\n const widthScale = 100 / retPosition.width\n const heightScale = 100 / retPosition.height\n\n const start: [number, number] = [\n -retPosition.left * widthScale,\n -retPosition.top * heightScale,\n ]\n const end: [number, number] = [\n widthScale * 100 + start[0],\n heightScale * 100 + start[1],\n ]\n\n currentRange.value = [start, end]\n }\n\n const moveClipRange = (e: MouseEvent) => {\n isSettingClipRange.value = true\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n const bottomPosition = imgPosition.value\n const originPositopn = {\n left: topImgWrapperPosition.left,\n top: topImgWrapperPosition.top,\n width: topImgWrapperPosition.width,\n height: topImgWrapperPosition.height,\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\n const moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\n\n let targetLeft = originPositopn.left + moveX\n let targetTop = originPositopn.top + moveY\n\n // 范围限制\n if(targetLeft < 0) targetLeft = 0\n else if(targetLeft + originPositopn.width > bottomPosition.width) {\n targetLeft = bottomPosition.width - originPositopn.width\n }\n if(targetTop < 0) targetTop = 0\n else if(targetTop + originPositopn.height > bottomPosition.height) {\n targetTop = bottomPosition.height - originPositopn.height\n }\n \n topImgWrapperPosition.left = targetLeft\n topImgWrapperPosition.top = targetTop\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n getRange()\n\n setTimeout(() => {\n isSettingClipRange.value = false\n }, 0)\n }\n }\n\n const scaleClipRange = (e: MouseEvent, type: ScaleClipRangeType) => {\n isSettingClipRange.value = true\n let isMouseDown = true\n\n const minWidth = 50 / props.width * 100\n const minHeight = 50 / props.height * 100\n \n const startPageX = e.pageX\n const startPageY = e.pageY\n const bottomPosition = imgPosition.value\n const originPositopn = {\n left: topImgWrapperPosition.left,\n top: topImgWrapperPosition.top,\n width: topImgWrapperPosition.width,\n height: topImgWrapperPosition.height,\n }\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n let moveX = (currentPageX - startPageX) / canvasScale.value / props.width * 100\n let moveY = (currentPageY - startPageY) / canvasScale.value / props.height * 100\n\n let targetLeft, targetTop, targetWidth, targetHeight\n\n // 根据不同缩放点,计算目标大小和位置,同时做大小和范围的限制\n if(type === 't-l') {\n if(originPositopn.left + moveX < 0) {\n moveX = -originPositopn.left\n }\n if(originPositopn.top + moveY < 0) {\n moveY = -originPositopn.top\n }\n if(originPositopn.width - moveX < minWidth) {\n moveX = originPositopn.width - minWidth\n }\n if(originPositopn.height - moveY < minHeight) {\n moveY = originPositopn.height - minHeight\n }\n targetWidth = originPositopn.width - moveX\n targetHeight = originPositopn.height - moveY\n targetLeft = originPositopn.left + moveX\n targetTop = originPositopn.top + moveY\n }\n else if(type === 't-r') {\n if(originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\n }\n if(originPositopn.top + moveY < 0) {\n moveY = -originPositopn.top\n }\n if(originPositopn.width + moveX < minWidth) {\n moveX = minWidth - originPositopn.width\n }\n if(originPositopn.height - moveY < minHeight) {\n moveY = originPositopn.height - minHeight\n }\n targetWidth = originPositopn.width + moveX\n targetHeight = originPositopn.height - moveY\n targetLeft = originPositopn.left\n targetTop = originPositopn.top + moveY\n }\n else if(type === 'b-l') {\n if(originPositopn.left + moveX < 0) {\n moveX = -originPositopn.left\n }\n if(originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\n }\n if(originPositopn.width - moveX < minWidth) {\n moveX = originPositopn.width - minWidth\n }\n if(originPositopn.height + moveY < minHeight) {\n moveY = minHeight - originPositopn.height\n }\n targetWidth = originPositopn.width - moveX\n targetHeight = originPositopn.height + moveY\n targetLeft = originPositopn.left + moveX\n targetTop = originPositopn.top\n }\n else {\n if(originPositopn.left + originPositopn.width + moveX > bottomPosition.width) {\n moveX = bottomPosition.width - (originPositopn.left + originPositopn.width)\n }\n if(originPositopn.top + originPositopn.height + moveY > bottomPosition.height) {\n moveY = bottomPosition.height - (originPositopn.top + originPositopn.height)\n }\n if(originPositopn.width + moveX < minWidth) {\n moveX = minWidth - originPositopn.width\n }\n if(originPositopn.height + moveY < minHeight) {\n moveY = minHeight - originPositopn.height\n }\n targetWidth = originPositopn.width + moveX\n targetHeight = originPositopn.height + moveY\n targetLeft = originPositopn.left\n targetTop = originPositopn.top\n }\n \n topImgWrapperPosition.left = targetLeft\n topImgWrapperPosition.top = targetTop\n topImgWrapperPosition.width = targetWidth\n topImgWrapperPosition.height = targetHeight\n }\n\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n getRange()\n\n setTimeout(() => isSettingClipRange.value = false, 0)\n }\n }\n\n return {\n clipWrapperPositionStyle,\n bottomImgPositionStyle,\n topImgWrapperPositionStyle,\n topImgPositionStyle,\n handleClip,\n moveClipRange,\n scaleClipRange,\n }\n },\n})\n","import { render } from \"./ImageClipHandler.vue?vue&type=template&id=1e41275c&scoped=true\"\nimport script from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageClipHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageClipHandler.vue?vue&type=style&index=0&id=1e41275c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1e41275c\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTImageElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport ImageRectOutline from './ImageRectOutline.vue'\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\nimport ImageClipHandler from './ImageClipHandler.vue'\nimport { ImageClipedEmitData } from '@/types/edit'\n\nexport default defineComponent({\n name: 'editable-element-image',\n components: {\n ImageRectOutline,\n ImageEllipseOutline,\n ImagePolygonOutline,\n ImageClipHandler,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\n\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n props.selectElement(e, props.elementInfo)\n }\n const clipShape = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect\n const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT\n\n return CLIPPATHS[shape]\n })\n\n const imgPosition = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) {\n return {\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n }\n }\n\n const [start, end] = props.elementInfo.clip.range\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return {\n left: -left + '%',\n top: -top + '%',\n width: 100 / widthScale + '%',\n height: 100 / heightScale + '%',\n }\n })\n\n const filter = computed(() => {\n if(!props.elementInfo.filters) return ''\n let filter = ''\n for(const key of Object.keys(props.elementInfo.filters)) {\n filter += `${key}(${props.elementInfo.filters[key]}) `\n }\n return filter\n })\n\n const flip = computed(() => {\n if(!props.elementInfo.flip) return ''\n const { x, y } = props.elementInfo.flip\n if(x && y) return `rotateX(${x}deg) rotateY(${y}deg)`\n else if(x) return `rotateX(${x}deg)`\n else if(y) return `rotateY(${y}deg)`\n return ''\n })\n\n const clip = (data: ImageClipedEmitData) => {\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, '')\n \n if(!data) return\n\n const { range, position } = data\n const originClip = props.elementInfo.clip || {}\n \n const _props = {\n clip: { ...originClip, range },\n left: props.elementInfo.left + position.left,\n top: props.elementInfo.top + position.top,\n width: props.elementInfo.width + position.width,\n height: props.elementInfo.height + position.height,\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: props.elementInfo.id, props: _props })\n }\n\n return {\n isCliping,\n clip,\n clipingImageElementId,\n shadowStyle,\n handleSelectElement,\n clipShape,\n imgPosition,\n filter,\n flip,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=c9d8ae3c&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=c9d8ae3c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-c9d8ae3c\"\n\nexport default script","\n\n\n\n\n","import { splitListItem, liftListItem, sinkListItem } from 'prosemirror-schema-list'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { undo, redo } from 'prosemirror-history'\r\nimport { undoInputRule } from 'prosemirror-inputrules'\r\nimport {\r\n toggleMark,\r\n selectParentNode,\r\n joinUp,\r\n joinDown,\r\n Command,\r\n} from 'prosemirror-commands'\r\n\r\nexport const buildKeymap = (schema: Schema) => {\r\n const keys = {}\r\n const bind = (key: string, cmd: Command) => keys[key] = cmd\r\n\r\n bind('Alt-ArrowUp', joinUp)\r\n bind('Alt-ArrowDown', joinDown)\r\n bind('Ctrl-z', undo)\r\n bind('Ctrl-y', redo)\r\n bind('Backspace', undoInputRule)\r\n bind('Escape', selectParentNode)\r\n bind('Ctrl-b', toggleMark(schema.marks.strong))\r\n bind('Ctrl-i', toggleMark(schema.marks.em))\r\n bind('Ctrl-u', toggleMark(schema.marks.underline))\r\n bind('Ctrl-d', toggleMark(schema.marks.strikethrough))\r\n\r\n bind('Enter', splitListItem(schema.nodes.list_item))\r\n bind('Mod-[', liftListItem(schema.nodes.list_item))\r\n bind('Mod-]', sinkListItem(schema.nodes.list_item))\r\n\r\n return keys\r\n}","import { NodeType, Schema } from 'prosemirror-model'\r\nimport {\r\n inputRules,\r\n wrappingInputRule,\r\n textblockTypeInputRule,\r\n smartQuotes,\r\n emDash,\r\n ellipsis,\r\n} from 'prosemirror-inputrules'\r\n\r\nconst blockQuoteRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*>\\s$/, nodeType)\r\n\r\nconst orderedListRule = (nodeType: NodeType) => (\r\n wrappingInputRule(\r\n /^(\\d+)\\.\\s$/, \r\n nodeType, \r\n match => ({order: +match[1]}),\r\n (match, node) => node.childCount + node.attrs.order === +match[1],\r\n )\r\n)\r\n\r\nconst bulletListRule = (nodeType: NodeType) => wrappingInputRule(/^\\s*([-+*])\\s$/, nodeType)\r\n\r\nconst codeBlockRule = (nodeType: NodeType) => textblockTypeInputRule(/^```$/, nodeType)\r\n\r\nexport const buildInputRules = (schema: Schema) => {\r\n const rules = [\r\n ...smartQuotes,\r\n ellipsis,\r\n emDash,\r\n ]\r\n rules.push(blockQuoteRule(schema.nodes.blockquote))\r\n rules.push(orderedListRule(schema.nodes.ordered_list))\r\n rules.push(bulletListRule(schema.nodes.bullet_list))\r\n rules.push(codeBlockRule(schema.nodes.code_block))\r\n\r\n return inputRules({ rules })\r\n}","import { keymap } from 'prosemirror-keymap'\r\nimport { Schema } from 'prosemirror-model'\r\nimport { history } from 'prosemirror-history'\r\nimport { baseKeymap } from 'prosemirror-commands'\r\nimport { dropCursor } from 'prosemirror-dropcursor'\r\nimport { gapCursor } from 'prosemirror-gapcursor'\r\n\r\nimport { buildKeymap } from './keymap'\r\nimport { buildInputRules } from './inputrules'\r\n\r\nexport const buildPlugins = (schema: Schema) => {\r\n return [\r\n buildInputRules(schema),\r\n keymap(buildKeymap(schema)),\r\n keymap(baseKeymap),\r\n dropCursor(),\r\n gapCursor(),\r\n history(),\r\n ]\r\n}","import { nodes } from 'prosemirror-schema-basic'\r\nimport { Node, NodeSpec } from 'prosemirror-model'\r\nimport { orderedList, bulletList, listItem } from 'prosemirror-schema-list'\r\n\r\nconst _orderedList: NodeSpec = {\r\n ...orderedList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _bulletList: NodeSpec = {\r\n ...bulletList,\r\n content: 'list_item+',\r\n group: 'block',\r\n}\r\n\r\nconst _listItem: NodeSpec = {\r\n ...listItem,\r\n content: 'paragraph block*',\r\n group: 'block',\r\n}\r\n\r\nconst paragraph: NodeSpec = {\r\n attrs: {\r\n align: {\r\n default: '',\r\n },\r\n },\r\n content: 'inline*',\r\n group: 'block',\r\n parseDOM: [\r\n {\r\n tag: 'p',\r\n getAttrs: dom => {\r\n const { textAlign } = (dom as HTMLElement).style\r\n let align = (dom as HTMLElement).getAttribute('align') || textAlign || ''\r\n align = /(left|right|center|justify)/.test(align) ? align : ''\r\n \r\n return { align }\r\n }\r\n }\r\n ],\r\n toDOM: (node: Node) => {\r\n const { align } = node.attrs\r\n let style = ''\r\n if(align && align !== 'left') style += `text-align: ${align};`\r\n\r\n return ['p', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...nodes,\r\n 'ordered_list': _orderedList,\r\n 'bullet_list': _bulletList,\r\n 'list_item': _listItem,\r\n paragraph,\r\n}\r\n","import { marks } from 'prosemirror-schema-basic'\r\nimport { MarkSpec } from 'prosemirror-model'\r\n\r\nconst subscript: MarkSpec = {\r\n excludes: 'subscript',\r\n parseDOM: [\r\n { tag: 'sub' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'sub' && null\r\n },\r\n ],\r\n toDOM: () => ['sub', 0],\r\n}\r\n\r\nconst superscript: MarkSpec = {\r\n excludes: 'superscript',\r\n parseDOM: [\r\n { tag: 'sup' },\r\n {\r\n style: 'vertical-align',\r\n getAttrs: value => value === 'super' && null\r\n },\r\n ],\r\n toDOM: () => ['sup', 0],\r\n}\r\n\r\nconst strikethrough: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'strike' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'line-through' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration-line: line-through' }, 0],\r\n}\r\n\r\nconst underline: MarkSpec = {\r\n parseDOM: [\r\n { tag: 'u' },\r\n {\r\n style: 'text-decoration',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n {\r\n style: 'text-decoration-line',\r\n getAttrs: value => value === 'underline' && null\r\n },\r\n ],\r\n toDOM: () => ['span', { style: 'text-decoration: underline' }, 0],\r\n}\r\n\r\nconst forecolor: MarkSpec = {\r\n attrs: {\r\n color: {},\r\n },\r\n parseDOM: [\r\n {\r\n style: 'color',\r\n getAttrs: color => color ? { color } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { color } = mark.attrs\r\n let style = ''\r\n if(color) style += `color: ${color};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst backcolor: MarkSpec = {\r\n attrs: {\r\n backcolor: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n tag: 'span[style*=background-color]',\r\n getAttrs: backcolor => backcolor ? { backcolor } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { backcolor } = mark.attrs\r\n let style = ''\r\n if(backcolor) style += `background-color: ${backcolor};`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontsize: MarkSpec = {\r\n attrs: {\r\n fontsize: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-size',\r\n getAttrs: fontsize => fontsize ? { fontsize } : {}\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontsize } = mark.attrs\r\n let style = ''\r\n if(fontsize) style += `font-size: ${fontsize}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nconst fontname: MarkSpec = {\r\n attrs: {\r\n fontname: {},\r\n },\r\n inline: true,\r\n group: 'inline',\r\n parseDOM: [\r\n {\r\n style: 'font-family',\r\n getAttrs: fontname => {\r\n return { fontname: fontname && typeof fontname === 'string' ? fontname.replace(/[\\\"\\']/g, '') : '' }\r\n }\r\n },\r\n ],\r\n toDOM: mark => {\r\n const { fontname } = mark.attrs\r\n let style = ''\r\n if(fontname) style += `font-family: ${fontname}`\r\n return ['span', { style }, 0]\r\n },\r\n}\r\n\r\nexport default {\r\n ...marks,\r\n subscript,\r\n superscript,\r\n strikethrough,\r\n underline,\r\n forecolor,\r\n backcolor,\r\n fontsize,\r\n fontname,\r\n}","import nodes from './nodes'\r\nimport marks from './marks'\r\n\r\nexport const schemaNodes = nodes\r\nexport const schemaMarks = marks\r\n","import { EditorState } from 'prosemirror-state'\nimport { EditorView } from 'prosemirror-view'\nimport { Schema, DOMParser } from 'prosemirror-model'\n\nimport { buildPlugins } from './plugins/index'\nimport { schemaNodes, schemaMarks } from './schema/index'\n\nconst schema = new Schema({\n nodes: schemaNodes,\n marks: schemaMarks,\n})\n\nconst createDocument = (content: string) => {\n const htmlString = `
${content}
`\n const parser = new window.DOMParser()\n const element = parser.parseFromString(htmlString, 'text/html').body.firstElementChild\n return DOMParser.fromSchema(schema).parse(element as Element)\n}\n\nexport const initProsemirrorEditor = (dom: Element, content: string, props = {}) => {\n return new EditorView(dom, {\n state: EditorState.create({\n doc: createDocument(content),\n plugins: buildPlugins(schema),\n }),\n ...props,\n })\n}","import { Node, NodeType, ResolvedPos } from 'prosemirror-model'\nimport { EditorState, Selection } from 'prosemirror-state'\nimport { EditorView } from 'prosemirror-view'\n\nconst equalNodeType = (nodeType: NodeType, node: Node) => {\n return Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1 || node.type === nodeType\n}\n\nconst findParentNodeClosestToPos = ($pos: ResolvedPos, predicate: (node: Node) => boolean) => {\n for(let i = $pos.depth; i > 0; i--) {\n const node = $pos.node(i)\n if(predicate(node)) {\n return {\n pos: i > 0 ? $pos.before(i) : 0,\n start: $pos.start(i),\n depth: i,\n node,\n }\n }\n }\n}\n\nexport const findParentNode = (predicate: (node: Node) => boolean) => {\n return (_ref: Selection) => findParentNodeClosestToPos(_ref.$from, predicate)\n}\n\nexport const findParentNodeOfType = (nodeType: NodeType) => {\n return (selection: Selection) => {\n return findParentNode((node: Node) => {\n return equalNodeType(nodeType, node)\n })(selection)\n }\n}\n\nexport const isActiveOfParentNodeType = (nodeType: string, state: EditorState) => {\n const node = state.schema.nodes[nodeType]\n return !!findParentNodeOfType(node)(state.selection)\n}\n\nexport const getMarkAttrs = (view: EditorView) => {\n const { selection, doc } = view.state\n const { from } = selection\n const node = doc.nodeAt(from)\n return node?.marks || []\n}\n\nexport const getAttrValue = (view: EditorView, markType: string, attr: string) => {\n const marks = getMarkAttrs(view)\n for(const mark of marks) {\n if(mark.type.name === markType && mark.attrs[attr]) return mark.attrs[attr]\n }\n return null\n}\n\nexport const isActiveMark = (view: EditorView, markType: string) => {\n const marks = getMarkAttrs(view)\n for(const mark of marks) {\n if(mark.type.name === markType) return true\n }\n return false\n}\n\nexport const getAttrValueInSelection = (view: EditorView, attr: string) => {\n const { selection, doc } = view.state\n const { from, to } = selection\n\n let keepChecking = true\n let value = ''\n doc.nodesBetween(from, to, node => {\n if(keepChecking && node.attrs[attr]) {\n keepChecking = false\n value = node.attrs[attr]\n }\n return keepChecking\n })\n return value\n}\n\nexport const getTextAttrs = (view: EditorView) => {\n const isBold = isActiveMark(view, 'strong')\n const isEm = isActiveMark(view, 'em')\n const isUnderline = isActiveMark(view, 'underline')\n const isStrikethrough = isActiveMark(view, 'strikethrough')\n const isSuperscript = isActiveMark(view, 'superscript')\n const isSubscript = isActiveMark(view, 'subscript')\n const isCode = isActiveMark(view, 'code')\n const color = getAttrValue(view, 'forecolor', 'color') || '#000'\n const backcolor = getAttrValue(view, 'backcolor', 'backcolor') || '#000'\n const fontsize = getAttrValue(view, 'fontsize', 'fontsize') || '12px'\n const fontname = getAttrValue(view, 'fontname', 'fontname') || '微软雅黑'\n const align = getAttrValueInSelection(view, 'align') || 'left'\n const isBulletList = isActiveOfParentNodeType('bullet_list', view.state)\n const isOrderedList = isActiveOfParentNodeType('ordered_list', view.state)\n const isBlockquote = isActiveOfParentNodeType('blockquote', view.state)\n\n return {\n bold: isBold,\n em: isEm,\n underline: isUnderline,\n strikethrough: isStrikethrough,\n superscript: isSuperscript,\n subscript: isSubscript,\n code: isCode,\n color: color,\n backcolor: backcolor,\n fontsize: fontsize,\n fontname: fontname,\n align: align,\n bulletList: isBulletList,\n orderedList: isOrderedList,\n blockquote: isBlockquote,\n }\n}\n\nexport type TextAttrs = ReturnType","import { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction } from 'prosemirror-state'\r\nimport { EditorView } from 'prosemirror-view'\r\n\r\nexport const setTextAlign = (tr: Transaction, schema: Schema, alignment: string) => {\r\n const { selection, doc } = tr\r\n if(!selection || !doc) return tr\r\n\r\n const { from, to } = selection\r\n const { nodes } = schema\r\n\r\n const blockquote = nodes.blockquote\r\n const listItem = nodes.list_item\r\n const paragraph = nodes.paragraph\r\n\r\n interface Task {\r\n node: Node;\r\n pos: number;\r\n nodeType: NodeType;\r\n }\r\n\r\n const tasks: Task[] = []\r\n alignment = alignment || ''\r\n\r\n const allowedNodeTypes = new Set([blockquote, listItem, paragraph])\r\n\r\n doc.nodesBetween(from, to, (node, pos) => {\r\n const nodeType = node.type\r\n const align = node.attrs.align || ''\r\n if(align !== alignment && allowedNodeTypes.has(nodeType)) {\r\n tasks.push({\r\n node,\r\n pos,\r\n nodeType,\r\n })\r\n }\r\n return true\r\n })\r\n\r\n if(!tasks.length) return tr\r\n\r\n tasks.forEach(task => {\r\n const { node, pos, nodeType } = task\r\n let { attrs } = node\r\n if(alignment) attrs = { ...attrs, align: alignment }\r\n else attrs = { ...attrs, align: null }\r\n tr = tr.setNodeMarkup(pos, nodeType, attrs, node.marks)\r\n })\r\n\r\n return tr\r\n}\r\n\r\nexport const alignmentCommand = (view: EditorView, alignment: string) => {\r\n const { state } = view\r\n const { schema, selection } = state\r\n const tr = setTextAlign(\r\n state.tr.setSelection(selection),\r\n schema,\r\n alignment,\r\n )\r\n view.dispatch(tr)\r\n}","import { wrapInList, liftListItem } from 'prosemirror-schema-list'\r\nimport { Schema, Node, NodeType } from 'prosemirror-model'\r\nimport { Transaction, EditorState } from 'prosemirror-state'\r\nimport { findParentNode } from '../utils'\r\n\r\nconst isList = (node: Node, schema: Schema) => {\r\n return (\r\n node.type === schema.nodes.bullet_list ||\r\n node.type === schema.nodes.ordered_list\r\n )\r\n}\r\n\r\nexport const toggleList = (listType: NodeType, itemType: NodeType) => {\r\n return (state: EditorState, dispatch: (tr: Transaction) => void) => {\r\n const { schema, selection } = state\r\n const { $from, $to } = selection\r\n const range = $from.blockRange($to)\r\n\r\n if(!range) return false\r\n\r\n const parentList = findParentNode((node: Node) => isList(node, schema))(selection)\r\n\r\n if(range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {\r\n if(parentList.node.type === listType) {\r\n return liftListItem(itemType)(state, dispatch)\r\n }\r\n\r\n if(isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {\r\n const { tr } = state\r\n tr.setNodeMarkup(parentList.pos, listType)\r\n\r\n if(dispatch) dispatch(tr)\r\n\r\n return false\r\n }\r\n }\r\n\r\n return wrapInList(listType)(state, dispatch)\r\n }\r\n}\r\n","\n\n\n\n","\nimport { PropType, defineComponent, toRef } from 'vue'\nimport { PPTElementOutline } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\n\nexport default defineComponent({\n name: 'element-outline',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n outline: {\n type: Object as PropType\n },\n },\n setup(props) {\n const {\n outlineWidth,\n outlineStyle,\n outlineColor,\n } = useElementOutline(toRef(props, 'outline'))\n\n return {\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=59365834&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=59365834&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-59365834\"\n\nexport default script","\nimport { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport debounce from 'lodash/debounce'\nimport { MutationTypes, useStore } from '@/store'\nimport { EditorView } from 'prosemirror-view'\nimport { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'\nimport { PPTTextElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { initProsemirrorEditor } from '@/prosemirror/'\nimport { getTextAttrs } from '@/prosemirror/utils'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\nimport { alignmentCommand } from '@/prosemirror/commands/setTextAlign'\nimport { toggleList } from '@/prosemirror/commands/toggleList'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\n\ninterface CommandPayload {\n command: string;\n value?: string;\n}\n\nexport default defineComponent({\n name: 'editable-element-text',\n components: {\n ElementOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const elementRef = ref()\n\n const isScaling = ref(false)\n const realHeightCache = ref(-1)\n\n const scaleElementStateListener = (state: boolean) => {\n isScaling.value = state\n\n if(!state && realHeightCache.value !== -1) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeightCache.value },\n })\n realHeightCache.value = -1\n }\n }\n\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n onUnmounted(() => {\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n })\n\n const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {\n const contentRect = entries[0].contentRect\n if(!elementRef.value) return\n\n const realHeight = contentRect.height\n\n if(props.elementInfo.height !== realHeight) {\n if(!isScaling.value) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeight },\n })\n }\n else realHeightCache.value = realHeight\n }\n }\n const resizeObserver = new ResizeObserver(updateTextElementHeight)\n\n onMounted(() => {\n if(elementRef.value) resizeObserver.observe(elementRef.value)\n })\n onUnmounted(() => {\n if(elementRef.value) resizeObserver.unobserve(elementRef.value)\n })\n \n const editorViewRef = ref()\n let editorView: EditorView\n\n const handleFocus = () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, true)\n }\n const handleBlur = () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, false)\n }\n const handleInput = debounce(function() {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { content: editorView.dom.innerHTML },\n })\n addHistorySnapshot()\n }, 300, { trailing: true })\n\n const handleClick = debounce(function() {\n const attr = getTextAttrs(editorView)\n emitter.emit(EmitterEvents.UPDATE_TEXT_STATE, attr)\n }, 30, { trailing: true })\n\n const handleKeydown = () => {\n handleInput()\n handleClick()\n }\n\n const textContent = computed(() => props.elementInfo.content)\n watch(textContent, () => {\n if(!editorView) return\n if(editorView.hasFocus()) return\n editorView.dom.innerHTML = textContent.value\n })\n\n const editable = computed(() => !props.elementInfo.lock)\n watch(editable, () => {\n editorView.setProps({ editable: () => editable.value })\n })\n\n onMounted(() => {\n editorView = initProsemirrorEditor((editorViewRef.value as Element), textContent.value, {\n handleDOMEvents: {\n focus: handleFocus,\n blur: handleBlur,\n keydown: handleKeydown,\n click: handleClick,\n },\n editable: () => editable.value,\n })\n })\n onUnmounted(() => {\n editorView && editorView.destroy()\n })\n\n const handleSelectElement = (e: MouseEvent, canMove = true) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo, canMove)\n }\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const handleElementId = computed(() => store.state.handleElementId)\n \n const execCommand = (payload: CommandPayload | CommandPayload[]) => {\n if(handleElementId.value !== props.elementInfo.id) return\n\n const commands = ('command' in payload) ? [payload] : payload\n\n for(const item of commands) {\n if(item.command === 'fontname' && item.value) {\n const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'fontsize' && item.value) {\n const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'color' && item.value) {\n const mark = editorView.state.schema.marks.forecolor.create({ color: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'backcolor' && item.value) {\n const mark = editorView.state.schema.marks.backcolor.create({ backcolor: item.value })\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))\n }\n else if(item.command === 'bold') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'em') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'underline') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'strikethrough') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'subscript') {\n toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'superscript') {\n toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'blockquote') {\n wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'code') {\n toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'align' && item.value) {\n alignmentCommand(editorView, item.value)\n }\n else if(item.command === 'bulletList') {\n const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes\n toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'orderedList') {\n const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes\n toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)\n }\n else if(item.command === 'clear') {\n const { empty } = editorView.state.selection\n if(empty) selectAll(editorView.state, editorView.dispatch)\n const { $from, $to } = editorView.state.selection\n editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))\n }\n }\n\n editorView.focus()\n handleInput()\n handleClick()\n }\n\n emitter.on(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\n onUnmounted(() => {\n emitter.off(EmitterEvents.EXEC_TEXT_COMMAND, payload => execCommand(payload))\n })\n\n return {\n elementRef,\n editorViewRef,\n handleSelectElement,\n shadowStyle,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=092f3d4e&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=092f3d4e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-092f3d4e\"\n\nexport default script","\n\n\n\n\n","\r\n\r\n","\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nexport default defineComponent({\r\n name: 'gradient-defs',\r\n props: {\r\n id: {\r\n type: String,\r\n required: true,\r\n },\r\n type: {\r\n type: String as PropType<'linear' | 'radial'>,\r\n },\r\n color1: {\r\n type: String,\r\n required: true,\r\n },\r\n color2: {\r\n type: String,\r\n required: true,\r\n },\r\n rotate: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n})\r\n","import { render } from \"./GradientDefs.vue?vue&type=template&id=b787d5ea\"\nimport script from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nexport * from \"./GradientDefs.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTShapeElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport GradientDefs from './GradientDefs.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n GradientDefs,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n\n const outline = computed(() => props.elementInfo.outline)\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n handleSelectElement,\n shadowStyle,\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=6a9228f2&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=6a9228f2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6a9228f2\"\n\nexport default script","\n\n\n\n\n","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\n\nconst pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z',\n}\nconst rotateMap = {\n 'arrow-start': 180,\n 'arrow-end': 0,\n}\n\nexport default defineComponent({\n name: 'line-point-marker',\n props: {\n id: {\n type: String,\n required: true,\n },\n position: {\n type: String as PropType<'start' | 'end'>,\n required: true,\n },\n type: {\n type: String as PropType<'dot' | 'arrow'>,\n required: true,\n },\n color: {\n type: String,\n },\n baseSize: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const path = computed(() => pathMap[props.type])\n const rotate = computed(() => rotateMap[`${props.type}-${props.position}`] || 0)\n const size = computed(() => props.baseSize < 2 ? 2 : props.baseSize)\n\n return {\n path,\n rotate,\n size,\n }\n },\n})\n","import { render } from \"./LinePointMarker.vue?vue&type=template&id=62085f5a\"\nimport script from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePointMarker.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTLineElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport LinePointMarker from './LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n LinePointMarker,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const svgWidth = computed(() => {\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\n return width < 24 ? 24 : width\n })\n const svgHeight = computed(() => {\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\n return height < 24 ? 24 : height\n })\n\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\n const path = computed(() => {\n const start = props.elementInfo.start.join(',')\n const end = props.elementInfo.end.join(',')\n return `M${start} L${end}`\n })\n\n return {\n handleSelectElement,\n shadowStyle,\n svgWidth,\n svgHeight,\n lineDashArray,\n path,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=d93ab0c4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=d93ab0c4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d93ab0c4\"\n\nexport default script","\r\n\r\n\r\n\r\n\r\n","\n\n\n\n\n\n","\nimport { defineComponent, inject, onMounted, PropType, ref, Ref, watch } from 'vue'\nimport upperFirst from 'lodash/upperFirst'\nimport tinycolor from 'tinycolor2'\nimport Chartist, {\n IChartistLineChart,\n IChartistBarChart,\n IChartistPieChart,\n ILineChartOptions,\n IBarChartOptions,\n IPieChartOptions,\n} from 'chartist'\nimport { ChartData, ChartType } from '@/types/slides'\n\nimport 'chartist/dist/scss/chartist.scss'\n\nexport default defineComponent({\n name: 'chart',\n props: {\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n type: {\n type: String as PropType,\n required: true,\n },\n data: {\n type: Object as PropType,\n required: true,\n },\n options: {\n type: Object as PropType,\n },\n themeColor: {\n type: String,\n required: true,\n },\n gridColor: {\n type: String,\n },\n },\n setup(props) {\n const chartRef = ref()\n const slideScale: Ref = inject('slideScale') || ref(1)\n\n let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined\n\n const getDataAndOptions = () => {\n const propsOptopns = props.options || {}\n const options = {\n ...propsOptopns,\n width: props.width * slideScale.value,\n height: props.height * slideScale.value,\n }\n const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data\n return { data, options }\n }\n\n const renderChart = () => {\n if(!chartRef.value) return\n\n const type = upperFirst(props.type)\n const { data, options } = getDataAndOptions()\n chart = new Chartist[type](chartRef.value, data, options)\n }\n\n const updateChart = () => {\n if(!chart) {\n renderChart()\n return\n }\n const { data, options } = getDataAndOptions()\n chart.update(data, options)\n }\n\n watch([\n () => props.width,\n () => props.height,\n () => props.data,\n slideScale,\n ], updateChart)\n\n onMounted(renderChart)\n\n const updateTheme = () => {\n if(!chartRef.value) return\n\n const hsla = tinycolor(props.themeColor).toHsl()\n\n for(let i = 0; i < 10; i++) {\n let h = hsla.h + i * 36\n if(h > 360) h = h - 360\n\n const _hsla = {\n ...hsla,\n h,\n }\n chartRef.value.style.setProperty(`--theme-color-${i + 1}`, tinycolor(_hsla).toRgbString())\n }\n\n if(props.gridColor) chartRef.value.style.setProperty(`--grid-color`, props.gridColor)\n }\n\n watch([\n () => props.themeColor,\n () => props.gridColor,\n ], updateTheme)\n onMounted(updateTheme)\n\n return {\n slideScale,\n chartRef,\n }\n },\n})\n","import { render } from \"./Chart.vue?vue&type=template&id=5f401eca&scoped=true\"\nimport script from \"./Chart.vue?vue&type=script&lang=ts\"\nexport * from \"./Chart.vue?vue&type=script&lang=ts\"\n\nimport \"./Chart.vue?vue&type=style&index=0&id=5f401eca&lang=scss&scoped=true\"\nimport \"./Chart.vue?vue&type=style&index=1&id=5f401eca&lang=scss\"\nscript.render = render\nscript.__scopeId = \"data-v-5f401eca\"\n\nexport default script","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\nimport Chart from './Chart.vue'\r\n\r\nexport default defineComponent({\r\n name: 'editable-element-chart',\r\n components: {\r\n ElementOutline,\r\n Chart,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n selectElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTChartElement, canMove?: boolean) => void>,\r\n required: true,\r\n },\r\n contextmenus: {\r\n type: Function as PropType<() => ContextmenuItem[]>,\r\n },\r\n },\r\n setup(props) {\r\n const handleSelectElement = (e: MouseEvent) => {\r\n if(props.elementInfo.lock) return\r\n e.stopPropagation()\r\n\r\n props.selectElement(e, props.elementInfo)\r\n }\r\n\r\n return {\r\n handleSelectElement,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=7550799e&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=7550799e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7550799e\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\n\n","\nimport { defineComponent, onUnmounted, ref, watch } from 'vue'\n\nexport default defineComponent({\n name: 'custom-textarea',\n props: {\n modelValue: {\n type: String,\n default: '',\n },\n contenteditable: {\n type: [Boolean, String],\n default: false,\n },\n },\n setup(props, { emit }) {\n const textareaRef = ref()\n const text = ref('')\n const isFocus = ref(false)\n\n watch(() => props.modelValue, () => {\n if(isFocus.value) return\n text.value = props.modelValue\n if(textareaRef.value) textareaRef.value.innerHTML = props.modelValue\n }, { immediate: true })\n\n const handleInput = () => {\n if(!textareaRef.value) return\n const text = textareaRef.value.innerHTML\n emit('update:modelValue', text)\n }\n\n const handleFocus = () => {\n isFocus.value = true\n\n if(!textareaRef.value) return\n textareaRef.value.onpaste = (e: ClipboardEvent) => {\n e.preventDefault()\n if(!e.clipboardData) return\n\n const clipboardDataFirstItem = e.clipboardData.items[0]\n\n if(clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {\n clipboardDataFirstItem.getAsString(text => emit('update:modelValue', text))\n }\n }\n }\n\n const handleBlur = () => {\n isFocus.value = false\n if(textareaRef.value) textareaRef.value.onpaste = null\n }\n\n onUnmounted(() => {\n if(textareaRef.value) textareaRef.value.onpaste = null\n })\n\n return {\n textareaRef,\n handleFocus,\n handleInput,\n handleBlur,\n text,\n }\n },\n})\n","import { render } from \"./CustomTextarea.vue?vue&type=template&id=ca4394a2\"\nimport script from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nexport * from \"./CustomTextarea.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport debounce from 'lodash/debounce'\nimport tinycolor from 'tinycolor2'\nimport { useStore } from '@/store'\nimport { PPTElementOutline, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { KEYS } from '@/configs/hotkey'\nimport { createRandomCode } from '@/utils/common'\n\nimport CustomTextarea from './CustomTextarea.vue'\n\nexport default defineComponent({\n name: 'editable-table',\n components: {\n CustomTextarea,\n },\n props: {\n data: {\n type: Array as PropType,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n colWidths: {\n type: Array as PropType,\n required: true,\n },\n outline: {\n type: Object as PropType,\n required: true,\n },\n theme: {\n type: Object as PropType,\n },\n editable: {\n type: Boolean,\n default: true,\n },\n },\n setup(props, { emit }) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const subThemeColor = ref(['', ''])\n watch(() => props.theme, () => {\n if(props.theme) {\n const rgba = tinycolor(props.theme.color).toRgb()\n const subRgba1 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.3 }\n const subRgba2 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.1 }\n subThemeColor.value = [\n `rgba(${[subRgba1.r, subRgba1.g, subRgba1.b, subRgba1.a].join(',')})`,\n `rgba(${[subRgba2.r, subRgba2.g, subRgba2.b, subRgba2.a].join(',')})`,\n ]\n }\n }, { immediate: true })\n\n const tableCells = computed({\n get() {\n return props.data\n },\n set(newData) {\n emit('change', newData)\n },\n })\n\n const colSizeList = ref([])\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\n watch([\n () => props.colWidths,\n () => props.width,\n ], () => {\n colSizeList.value = props.colWidths.map(item => item * props.width)\n }, { immediate: true })\n \n const isStartSelect = ref(false)\n const startCell = ref([])\n const endCell = ref([])\n \n const removeSelectedCells = () => {\n startCell.value = []\n endCell.value = []\n }\n\n watch(() => props.editable, () => {\n if(!props.editable) removeSelectedCells()\n })\n\n const dragLinePosition = computed(() => {\n const dragLinePosition: number[] = []\n for(let i = 1; i < colSizeList.value.length + 1; i++) {\n const pos = colSizeList.value.slice(0, i).reduce((a, b) => (a + b))\n dragLinePosition.push(pos)\n }\n return dragLinePosition\n })\n\n const hideCells = computed(() => {\n const hideCells = []\n \n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n\n for(let j = 0; j < rowCells.length; j++) {\n const cell = rowCells[j]\n \n if(cell.colspan > 1 || cell.rowspan > 1) {\n for(let row = i; row < i + cell.rowspan; row++) {\n for(let col = row === i ? j + 1 : j; col < j + cell.colspan; col++) {\n hideCells.push(`${row}_${col}`)\n }\n }\n }\n }\n }\n return hideCells\n })\n\n const selectedCells = computed(() => {\n if(!startCell.value.length) return []\n const [startX, startY] = startCell.value\n\n if(!endCell.value.length) return [`${startX}_${startY}`]\n const [endX, endY] = endCell.value\n\n if(startX === endX && startY === endY) return [`${startX}_${startY}`]\n\n const selectedCells = []\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n for(let j = 0; j < rowCells.length; j++) {\n if(i >= minX && i <= maxX && j >= minY && j <= maxY) selectedCells.push(`${i}_${j}`)\n }\n }\n return selectedCells\n })\n\n watch(selectedCells, () => {\n emit('changeSelectedCells', selectedCells.value)\n })\n\n const activedCell = computed(() => {\n if(selectedCells.value.length > 1) return null\n return selectedCells.value[0]\n })\n\n const selectedRange = computed(() => {\n if(!startCell.value.length) return null\n const [startX, startY] = startCell.value\n\n if(!endCell.value.length) return { row: [startX, startX], col: [startY, startY] }\n const [endX, endY] = endCell.value\n\n if(startX === endX && startY === endY) return { row: [startX, startX], col: [startY, startY] }\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n return {\n row: [minX, maxX],\n col: [minY, maxY],\n }\n })\n\n const handleMouseup = () => isStartSelect.value = false\n\n const handleCellMousedown = (e: MouseEvent, rowIndex: number, colIndex: number) => {\n if(e.button === 0) {\n endCell.value = []\n isStartSelect.value = true\n startCell.value = [rowIndex, colIndex]\n }\n }\n\n const handleCellMouseenter = (rowIndex: number, colIndex: number) => {\n if(!isStartSelect.value) return\n endCell.value = [rowIndex, colIndex]\n }\n\n onMounted(() => {\n document.addEventListener('mouseup', handleMouseup)\n })\n onUnmounted(() => {\n document.removeEventListener('mouseup', handleMouseup)\n })\n\n const isHideCell = (rowIndex: number, colIndex: number) => hideCells.value.includes(`${rowIndex}_${colIndex}`)\n\n const selectCol = (index: number) => {\n const maxRow = tableCells.value.length - 1\n startCell.value = [0, index]\n endCell.value = [maxRow, index]\n }\n\n const selectRow = (index: number) => {\n const maxCol = tableCells.value[index].length - 1\n startCell.value = [index, 0]\n endCell.value = [index, maxCol]\n }\n\n const selectAll = () => {\n const maxRow = tableCells.value.length - 1\n const maxCol = tableCells.value[maxRow].length - 1\n startCell.value = [0, 0]\n endCell.value = [maxRow, maxCol]\n }\n\n const deleteRow = (rowIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const targetCells = tableCells.value[rowIndex]\n const hideCellsPos = []\n for(let i = 0; i < targetCells.length; i++) {\n if(isHideCell(rowIndex, i)) hideCellsPos.push(i)\n }\n \n for(const pos of hideCellsPos) {\n for(let i = rowIndex; i >= 0; i--) {\n if(!isHideCell(i, pos)) {\n _tableCells[i][pos].rowspan = _tableCells[i][pos].rowspan - 1\n break\n }\n }\n }\n\n _tableCells.splice(rowIndex, 1)\n tableCells.value = _tableCells\n }\n\n const deleteCol = (colIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const hideCellsPos = []\n for(let i = 0; i < tableCells.value.length; i++) {\n if(isHideCell(i, colIndex)) hideCellsPos.push(i)\n }\n\n for(const pos of hideCellsPos) {\n for(let i = colIndex; i >= 0; i--) {\n if(!isHideCell(pos, i)) {\n _tableCells[pos][i].colspan = _tableCells[pos][i].colspan - 1\n break\n }\n }\n }\n\n tableCells.value = _tableCells.map(item => {\n item.splice(colIndex, 1)\n return item\n })\n colSizeList.value.splice(colIndex, 1)\n emit('changeColWidths', colSizeList.value)\n }\n \n const insertRow = (rowIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n const rowCells: TableCell[] = []\n for(let i = 0; i < _tableCells[0].length; i++) {\n rowCells.push({\n colspan: 1,\n rowspan: 1,\n text: '',\n id: createRandomCode(),\n })\n }\n\n _tableCells.splice(rowIndex, 0, rowCells)\n tableCells.value = _tableCells\n }\n\n const insertCol = (colIndex: number) => {\n tableCells.value = tableCells.value.map(item => {\n const cell = {\n colspan: 1,\n rowspan: 1,\n text: '',\n id: createRandomCode(),\n }\n item.splice(colIndex, 0, cell)\n return item\n })\n colSizeList.value.splice(colIndex, 0, 100)\n emit('changeColWidths', colSizeList.value)\n }\n \n const mergeCells = () => {\n const [startX, startY] = startCell.value\n const [endX, endY] = endCell.value\n\n const minX = Math.min(startX, endX)\n const minY = Math.min(startY, endY)\n const maxX = Math.max(startX, endX)\n const maxY = Math.max(startY, endY)\n\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n \n _tableCells[minX][minY].rowspan = maxX - minX + 1\n _tableCells[minX][minY].colspan = maxY - minY + 1\n\n tableCells.value = _tableCells\n removeSelectedCells()\n }\n\n const splitCells = (rowIndex: number, colIndex: number) => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n _tableCells[rowIndex][colIndex].rowspan = 1\n _tableCells[rowIndex][colIndex].colspan = 1\n\n tableCells.value = _tableCells\n removeSelectedCells()\n }\n\n const handleMousedownColHandler = (e: MouseEvent, colIndex: number) => {\n removeSelectedCells()\n let isMouseDown = true\n\n const originWidth = colSizeList.value[colIndex]\n const startPageX = e.pageX\n\n const minWidth = 50\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n \n const moveX = (e.pageX - startPageX) / canvasScale.value\n const width = originWidth + moveX < minWidth ? minWidth : Math.round(originWidth + moveX)\n\n colSizeList.value[colIndex] = width\n }\n document.onmouseup = () => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n emit('changeColWidths', colSizeList.value)\n }\n }\n\n const clearSelectedCellText = () => {\n const _tableCells: TableCell[][] = JSON.parse(JSON.stringify(tableCells.value))\n\n for(let i = 0; i < _tableCells.length; i++) {\n for(let j = 0; j < _tableCells[i].length; j++) {\n if(selectedCells.value.includes(`${i}_${j}`)) {\n _tableCells[i][j].text = ''\n }\n }\n }\n tableCells.value = _tableCells\n }\n\n const tabActiveCell = () => {\n const getNextCell = (i: number, j: number): [number, number] | null => {\n if(!tableCells.value[i]) return null\n if(!tableCells.value[i][j]) return getNextCell(i + 1, 0)\n if(isHideCell(i, j)) return getNextCell(i, j + 1)\n return [i, j]\n }\n\n endCell.value = []\n\n const nextRow = startCell.value[0]\n const nextCol = startCell.value[1] + 1\n\n const nextCell = getNextCell(nextRow, nextCol)\n if(!nextCell) {\n insertRow(nextRow + 1)\n startCell.value = [nextRow + 1, 0]\n }\n else startCell.value = nextCell\n\n nextTick(() => {\n const textRef = document.querySelector('.cell-text.active') as HTMLInputElement\n if(textRef) textRef.focus()\n })\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(selectedCells.value.length < 2) {\n if(key === KEYS.TAB) {\n e.preventDefault()\n tabActiveCell()\n }\n }\n else if(key === KEYS.DELETE) {\n clearSelectedCellText()\n }\n }\n\n onMounted(() => {\n document.addEventListener('keydown', keydownListener)\n })\n onUnmounted(() => {\n document.removeEventListener('keydown', keydownListener)\n })\n\n const getTextStyle = (style?: TableCellStyle) => {\n if(!style) return {}\n const {\n bold,\n em,\n underline,\n strikethrough,\n color,\n backcolor,\n fontsize,\n fontname,\n align,\n } = style\n \n return {\n fontWeight: bold ? 'bold' : 'normal',\n fontStyle: em ? 'italic' : 'normal',\n textDecoration: `${underline ? 'underline' : ''} ${strikethrough ? 'line-through' : ''}`,\n color: color || '#000',\n backgroundColor: backcolor || '',\n fontSize: fontsize || '14px',\n fontFamily: fontname || '微软雅黑',\n textAlign: align || 'left',\n }\n }\n\n const handleInput = debounce(function() {\n emit('change', tableCells.value)\n }, 300, { trailing: true })\n\n const getEffectiveTableCells = () => {\n const effectiveTableCells = []\n\n for(let i = 0; i < tableCells.value.length; i++) {\n const rowCells = tableCells.value[i]\n const _rowCells = []\n for(let j = 0; j < rowCells.length; j++) {\n if(!isHideCell(i, j)) _rowCells.push(rowCells[j])\n }\n if(_rowCells.length) effectiveTableCells.push(_rowCells)\n }\n\n return effectiveTableCells\n }\n\n const checkCanDeleteRowOrCol = () => {\n const effectiveTableCells = getEffectiveTableCells()\n const canDeleteRow = effectiveTableCells.length > 1\n const canDeleteCol = effectiveTableCells[0].length > 1\n\n return { canDeleteRow, canDeleteCol }\n }\n\n const checkCanMergeOrSplit = (rowIndex: number, colIndex: number) => {\n const isMultiSelected = selectedCells.value.length > 1\n const targetCell = tableCells.value[rowIndex][colIndex]\n\n const canMerge = isMultiSelected\n const canSplit = !isMultiSelected && (targetCell.rowspan > 1 || targetCell.colspan > 1)\n\n return { canMerge, canSplit }\n }\n\n const contextmenus = (el: HTMLElement): ContextmenuItem[] => {\n const cellIndex = el.dataset.cellIndex as string\n const rowIndex = +cellIndex.split('_')[0]\n const colIndex = +cellIndex.split('_')[1]\n\n if(!selectedCells.value.includes(`${rowIndex}_${colIndex}`)) {\n startCell.value = [rowIndex, colIndex]\n endCell.value = []\n }\n\n const { canMerge, canSplit } = checkCanMergeOrSplit(rowIndex, colIndex)\n const { canDeleteRow, canDeleteCol } = checkCanDeleteRowOrCol()\n\n return [\n {\n text: '插入列',\n children: [\n { text: '到左侧', handler: () => insertCol(colIndex) },\n { text: '到右侧', handler: () => insertCol(colIndex + 1) },\n ],\n },\n {\n text: '插入行',\n children: [\n { text: '到上方', handler: () => insertRow(rowIndex) },\n { text: '到下方', handler: () => insertRow(rowIndex + 1) },\n ],\n },\n {\n text: '删除列',\n disable: !canDeleteCol,\n handler: () => deleteCol(colIndex),\n },\n {\n text: '删除行',\n disable: !canDeleteRow,\n handler: () => deleteRow(rowIndex),\n },\n { divider: true },\n {\n text: '合并单元格',\n disable: !canMerge,\n handler: mergeCells,\n },\n {\n text: '取消合并单元格',\n disable: !canSplit,\n handler: () => splitCells(rowIndex, colIndex),\n },\n { divider: true },\n {\n text: '选中当前列',\n handler: () => selectCol(colIndex),\n },\n {\n text: '选中当前行',\n handler: () => selectRow(rowIndex),\n },\n {\n text: '选中全部单元格',\n handler: selectAll,\n },\n ]\n }\n\n return {\n getTextStyle,\n dragLinePosition,\n tableCells,\n colSizeList,\n totalWidth,\n hideCells,\n selectedCells,\n activedCell,\n selectedRange,\n handleCellMousedown,\n handleCellMouseenter,\n selectCol,\n selectRow,\n handleMousedownColHandler,\n contextmenus,\n handleInput,\n subThemeColor,\n }\n },\n})\n","import { render } from \"./EditableTable.vue?vue&type=template&id=7859e10e&scoped=true\"\nimport script from \"./EditableTable.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableTable.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableTable.vue?vue&type=style&index=0&id=7859e10e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7859e10e\"\n\nexport default script","\nimport { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTableElement, TableCell } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport EditableTable from './EditableTable.vue'\n\nexport default defineComponent({\n name: 'editable-element-table',\n components: {\n EditableTable,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, canMove?: boolean) => void>,\n required: true,\n },\n contextmenus: {\n type: Function as PropType<() => ContextmenuItem[]>,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const handleSelectElement = (e: MouseEvent) => {\n if(props.elementInfo.lock) return\n e.stopPropagation()\n\n props.selectElement(e, props.elementInfo)\n }\n const editable = ref(false)\n const handleElementId = computed(() => store.state.handleElementId)\n\n watch(handleElementId, () => {\n if(handleElementId.value !== props.elementInfo.id) editable.value = false\n })\n\n watch(editable, () => {\n store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, editable.value)\n })\n \n const elementRef = ref()\n\n const isScaling = ref(false)\n const realHeightCache = ref(-1)\n\n const scaleElementStateListener = (state: boolean) => {\n isScaling.value = state\n\n if(state) editable.value = false\n\n if(!state && realHeightCache.value !== -1) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeightCache.value },\n })\n realHeightCache.value = -1\n }\n }\n\n emitter.on(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n onUnmounted(() => {\n emitter.off(EmitterEvents.SCALE_ELEMENT_STATE, state => scaleElementStateListener(state))\n })\n\n const updateTableElementHeight = (entries: ResizeObserverEntry[]) => {\n const contentRect = entries[0].contentRect\n if(!elementRef.value) return\n\n const realHeight = contentRect.height\n\n if(props.elementInfo.height !== realHeight) {\n if(!isScaling.value) {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id,\n props: { height: realHeight },\n })\n }\n else realHeightCache.value = realHeight\n }\n }\n\n const resizeObserver = new ResizeObserver(updateTableElementHeight)\n\n onMounted(() => {\n if(elementRef.value) resizeObserver.observe(elementRef.value)\n })\n onUnmounted(() => {\n if(elementRef.value) resizeObserver.unobserve(elementRef.value)\n })\n\n const updateTableCells = (data: TableCell[][]) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { data },\n })\n addHistorySnapshot()\n }\n const updateColWidths = (widths: number[]) => {\n const width = widths.reduce((a, b) => a + b)\n const colWidths = widths.map(item => item / width)\n\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: props.elementInfo.id, \n props: { width, colWidths },\n })\n addHistorySnapshot()\n }\n\n const updateSelectedCells = (cells: string[]) => {\n nextTick(() => emitter.emit(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells))\n }\n\n const startEdit = () => {\n if(!props.elementInfo.lock) editable.value = true\n }\n\n return {\n elementRef,\n canvasScale,\n handleSelectElement,\n updateTableCells,\n updateColWidths,\n editable,\n startEdit,\n updateSelectedCells,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=045f7664&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=045f7664&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-045f7664\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\n\nimport useLockElement from '@/hooks/useLockElement'\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCombineElement from '@/hooks/useCombineElement'\nimport useOrderElement from '@/hooks/useOrderElement'\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\n\nimport { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'\n\nimport ImageElement from '@/views/components/element/ImageElement/index.vue'\nimport TextElement from '@/views/components/element/TextElement/index.vue'\nimport ShapeElement from '@/views/components/element/ShapeElement/index.vue'\nimport LineElement from '@/views/components/element/LineElement/index.vue'\nimport ChartElement from '@/views/components/element/ChartElement/index.vue'\nimport TableElement from '@/views/components/element/TableElement/index.vue'\n\nexport default defineComponent({\n name: 'editable-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n selectElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTElement, canMove?: boolean) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const theme = computed(() => store.state.theme)\n\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: ImageElement,\n [ElementTypes.TEXT]: TextElement,\n [ElementTypes.SHAPE]: ShapeElement,\n [ElementTypes.LINE]: LineElement,\n [ElementTypes.CHART]: ChartElement,\n [ElementTypes.TABLE]: TableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n const { orderElement } = useOrderElement()\n const { alignElementToCanvas } = useAlignElementToCanvas()\n const { combineElements, uncombineElements } = useCombineElement()\n const { deleteElement } = useDeleteElement()\n const { lockElement, unlockElement } = useLockElement()\n const { copyElement, cutElement } = useCopyAndPasteElement()\n\n const contextmenus = (): ContextmenuItem[] => {\n if(props.elementInfo.lock) {\n return [{\n text: '解锁', \n handler: () => unlockElement(props.elementInfo),\n }]\n }\n\n return [\n {\n text: '剪切',\n subText: 'Ctrl + X',\n handler: cutElement,\n },\n {\n text: '复制',\n subText: 'Ctrl + C',\n handler: copyElement,\n },\n { divider: true },\n {\n text: '层级排序',\n disable: props.isMultiSelect && !props.elementInfo.groupId,\n children: [\n { text: '置顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },\n { text: '置底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },\n { divider: true },\n { text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },\n { text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },\n ],\n },\n {\n text: '水平对齐',\n children: [\n { text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },\n { text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },\n { text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },\n ],\n },\n {\n text: '垂直对齐',\n children: [\n { text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },\n { text: '上对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },\n { text: '下对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },\n ],\n },\n { divider: true },\n {\n text: props.elementInfo.groupId ? '取消组合' : '组合',\n subText: 'Ctrl + G',\n handler: props.elementInfo.groupId ? uncombineElements : combineElements,\n hide: !props.isMultiSelect,\n },\n {\n text: '锁定',\n subText: 'Ctrl + L',\n handler: lockElement,\n },\n {\n text: '删除',\n subText: 'Delete',\n handler: deleteElement,\n },\n ]\n }\n\n return {\n currentElementComponent,\n contextmenus,\n theme,\n }\n },\n})\n","import { render } from \"./EditableElement.vue?vue&type=template&id=0d0be614\"\nimport script from \"./EditableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n\n\n","\nexport default {\n name: 'mouse-selection',\n props: {\n top: {\n type: Number,\n required: true,\n },\n left: {\n type: Number,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n height: {\n type: Number,\n required: true,\n },\n quadrant: {\n type: Number,\n required: true,\n validator(value: number) {\n return [1, 2, 3, 4].includes(value)\n },\n },\n }\n}\n","import { render } from \"./MouseSelection.vue?vue&type=template&id=1619c258&scoped=true\"\nimport script from \"./MouseSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./MouseSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./MouseSelection.vue?vue&type=style&index=0&id=1619c258&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1619c258\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\nimport { defineComponent, computed } from 'vue'\nimport tinycolor from 'tinycolor2'\nimport { useStore } from '@/store'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport { SlideBackground } from '@/types/slides'\n\nexport default defineComponent({\n name: 'grid-lines',\n setup() {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const background = computed(() => store.getters.currentSlide.background)\n\n const gridColor = computed(() => {\n if(!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'\n const color = background.value.color\n const rgba = tinycolor(color).toRgb()\n const newRgba = {\n r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,\n g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,\n b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,\n a: 0.5\n }\n return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`\n })\n\n const gridSize = 50\n\n const getPath = () => {\n const maxX = VIEWPORT_SIZE\n const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO\n\n let path = ''\n for(let i = 0; i <= Math.floor(maxY / gridSize); i++) {\n path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`\n }\n for(let i = 0; i <= Math.floor(maxX / gridSize); i++) {\n path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`\n }\n return path\n }\n\n return {\n canvasScale,\n gridColor,\n width: VIEWPORT_SIZE,\n height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,\n path: getPath(),\n }\n },\n})\n","import { render } from \"./GridLines.vue?vue&type=template&id=6515bb1c&scoped=true\"\nimport script from \"./GridLines.vue?vue&type=script&lang=ts\"\nexport * from \"./GridLines.vue?vue&type=script&lang=ts\"\n\nimport \"./GridLines.vue?vue&type=style&index=0&id=6515bb1c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6515bb1c\"\n\nexport default script","import { Ref, computed } from 'vue'\nimport { SlideBackground } from '@/types/slides'\n\nexport default (background: Ref) => {\n const backgroundStyle = computed(() => {\n if(!background.value) return { backgroundColor: '#fff' }\n\n const {\n type,\n color,\n image,\n imageSize,\n gradientColor,\n gradientRotate,\n gradientType,\n } = background.value\n\n if(type === 'solid') return { backgroundColor: color }\n else if(type === 'image') {\n if(!image) return { backgroundColor: '#fff' }\n if(imageSize === 'repeat') {\n return {\n backgroundImage: `url(${image}`,\n backgroundRepeat: 'repeat',\n backgroundSize: 'initial',\n }\n }\n return {\n backgroundImage: `url(${image}`,\n backgroundRepeat: 'no-repeat',\n backgroundSize: imageSize || 'cover',\n }\n }\n else if(type === 'gradient') {\n const rotate = gradientRotate || 0\n const color1 = gradientColor ? gradientColor[0] : '#fff'\n const color2 = gradientColor ? gradientColor[1] : '#fff'\n \n if(gradientType === 'radial') return { backgroundImage: `radial-gradient(${color1}, ${color2}` }\n return { backgroundImage: `linear-gradient(${rotate}deg, ${color1}, ${color2}` }\n }\n\n return { backgroundColor: '#fff' }\n })\n\n return {\n backgroundStyle,\n }\n}","\nimport { computed, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { SlideBackground } from '@/types/slides'\nimport GridLines from './GridLines.vue'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nexport default defineComponent({\n name: 'slide-background',\n components: {\n GridLines,\n },\n setup() {\n const store = useStore()\n const showGridLines = computed(() => store.state.showGridLines)\n const background = computed(() => store.getters.currentSlide.background)\n\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n return {\n showGridLines,\n backgroundStyle,\n }\n },\n})\n","import { render } from \"./SlideBackground.vue?vue&type=template&id=774174ab&scoped=true\"\nimport script from \"./SlideBackground.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideBackground.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideBackground.vue?vue&type=style&index=0&id=774174ab&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-774174ab\"\n\nexport default script","\n\n\n\n","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { AlignmentLineAxis } from '@/types/edit'\n\nexport default defineComponent({\n name: 'alignment-line',\n props: {\n type: {\n type: String as PropType<'vertical' | 'horizontal'>,\n required: true,\n },\n axis: {\n type: Object as PropType,\n required: true,\n },\n length: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const left = computed(() => props.axis.x * canvasScale.value + 'px')\n const top = computed(() => props.axis.y * canvasScale.value + 'px')\n\n const sizeStyle = computed(() => {\n if(props.type === 'vertical') return { height: props.length * canvasScale.value + 'px' }\n return { width: props.length * canvasScale.value + 'px' }\n })\n\n return {\n left,\n top,\n sizeStyle,\n }\n },\n})\n","import { render } from \"./AlignmentLine.vue?vue&type=template&id=520a7023&scoped=true\"\nimport script from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\nexport * from \"./AlignmentLine.vue?vue&type=script&lang=ts\"\n\nimport \"./AlignmentLine.vue?vue&type=style&index=0&id=520a7023&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-520a7023\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onMounted, reactive, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\n\nexport default defineComponent({\n name: 'element-create-selection',\n setup(props, { emit }) {\n const store = useStore()\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n const creatingElement = computed(() => store.state.creatingElement)\n\n const start = ref<[number, number] | null>(null)\n const end = ref<[number, number] | null>(null)\n\n const selectionRef = ref()\n const offset = reactive({\n x: 0,\n y: 0,\n })\n onMounted(() => {\n if(!selectionRef.value) return\n const { x, y } = selectionRef.value.getBoundingClientRect()\n offset.x = x\n offset.y = y\n })\n\n const createSelection = (e: MouseEvent) => {\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n start.value = [startPageX, startPageY]\n\n document.onmousemove = e => {\n if(!creatingElement.value || !isMouseDown) return\n\n let currentPageX = e.pageX\n let currentPageY = e.pageY\n\n if(ctrlOrShiftKeyActive.value) {\n const moveX = currentPageX - startPageX\n const moveY = currentPageY - startPageY\n\n const absX = Math.abs(moveX)\n const absY = Math.abs(moveY)\n\n if(creatingElement.value.type === 'shape') {\n // moveX和moveY一正一负\n const isOpposite = (moveY > 0 && moveX < 0) || (moveY < 0 && moveX > 0)\n\n if(absX > absY) {\n currentPageY = isOpposite ? startPageY - moveX : startPageY + moveX\n }\n else {\n currentPageX = isOpposite ? startPageX - moveY : startPageX + moveY\n }\n }\n\n else if(creatingElement.value.type === 'line') {\n if(absX > absY) currentPageY = startPageY\n else currentPageX = startPageX\n }\n }\n\n end.value = [currentPageX, currentPageY]\n }\n\n document.onmouseup = e => {\n document.onmousemove = null\n document.onmouseup = null\n isMouseDown = false\n\n const endPageX = e.pageX\n const endPageY = e.pageY\n\n const minSize = 30\n\n if(Math.abs(endPageX - startPageX) >= minSize || Math.abs(endPageY - startPageY) >= minSize) {\n emit('created', {\n start: start.value,\n end: end.value,\n })\n }\n else store.commit(MutationTypes.SET_CREATING_ELEMENT, null)\n }\n }\n\n const lineData = computed(() => {\n if(!start.value || !end.value) return null\n if(!creatingElement.value || creatingElement.value.type !== 'line') return null\n\n const [_startX, _startY] = start.value\n const [_endX, _endY] = end.value\n const minX = Math.min(_startX, _endX)\n const maxX = Math.max(_startX, _endX)\n const minY = Math.min(_startY, _endY)\n const maxY = Math.max(_startY, _endY)\n\n const svgWidth = maxX - minX >= 24 ? maxX - minX : 24\n const svgHeight = maxY - minY >= 24 ? maxY - minY : 24\n\n const startX = _startX === minX ? 0 : maxX - minX\n const startY = _startY === minY ? 0 : maxY - minY\n const endX = _endX === minX ? 0 : maxX - minX\n const endY = _endY === minY ? 0 : maxY - minY\n\n const path = `M${startX}, ${startY} L${endX}, ${endY}`\n\n return {\n svgWidth,\n svgHeight,\n startX,\n startY,\n endX,\n endY,\n path,\n }\n })\n\n const position = computed(() => {\n if(!start.value || !end.value) return {}\n\n const [startX, startY] = start.value\n const [endX, endY] = end.value\n const minX = Math.min(startX, endX)\n const maxX = Math.max(startX, endX)\n const minY = Math.min(startY, endY)\n const maxY = Math.max(startY, endY)\n\n const width = maxX - minX\n const height = maxY - minY\n\n return {\n left: minX - offset.x + 'px',\n top: minY - offset.y + 'px',\n width: width + 'px',\n height: height + 'px',\n }\n })\n\n return {\n selectionRef,\n start,\n end,\n creatingElement,\n createSelection,\n lineData,\n position,\n }\n },\n})\n","import { render } from \"./ElementCreateSelection.vue?vue&type=template&id=eea668f4&scoped=true\"\nimport script from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementCreateSelection.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementCreateSelection.vue?vue&type=style&index=0&id=eea668f4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-eea668f4\"\n\nexport default script","\n\n\n\n","import { computed, Ref } from 'vue'\nimport { OperateResizeHandlers, OperateBorderLines } from '@/types/edit'\n\nexport default (width: Ref, height: Ref) => {\n const resizeHandlers = computed(() => {\n return [\n { direction: OperateResizeHandlers.LEFT_TOP, style: {} },\n { direction: OperateResizeHandlers.TOP, style: {left: width.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT_TOP, style: {left: width.value + 'px'} },\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.LEFT_BOTTOM, style: {top: height.value + 'px'} },\n { direction: OperateResizeHandlers.BOTTOM, style: {left: width.value / 2 + 'px', top: height.value + 'px'} },\n { direction: OperateResizeHandlers.RIGHT_BOTTOM, style: {left: width.value + 'px', top: height.value + 'px'} },\n ]\n }\n )\n const textElementResizeHandlers = computed(() => {\n return [\n { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },\n { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },\n ]\n })\n\n const borderLines = computed(() => {\n return [\n { type: OperateBorderLines.T, style: {width: width.value + 'px'} },\n { type: OperateBorderLines.B, style: {top: height.value + 'px', width: width.value + 'px'} },\n { type: OperateBorderLines.L, style: {height: height.value + 'px'} },\n { type: OperateBorderLines.R, style: {left: width.value + 'px', height: height.value + 'px'} },\n ]\n })\n\n return {\n resizeHandlers,\n textElementResizeHandlers,\n borderLines,\n }\n}","\n\n\n\n","\nimport { PropType } from 'vue'\nimport { OperateResizeHandler } from '@/types/edit'\n\nexport default {\n name: 'resize-handler',\n props: {\n type: {\n type: String as PropType,\n default: '',\n },\n },\n}\n","import { render } from \"./ResizeHandler.vue?vue&type=template&id=1c2a68d0&scoped=true\"\nimport script from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./ResizeHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./ResizeHandler.vue?vue&type=style&index=0&id=1c2a68d0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1c2a68d0\"\n\nexport default script","\n\n\n\n","\nimport { PropType } from 'vue'\nimport { OperateBorderLine } from '@/types/edit'\n\nexport default {\n name: 'border-line',\n props: {\n type: {\n type: String as PropType,\n required: true,\n },\n isWide: {\n type: Boolean,\n default: false,\n },\n },\n}\n","import { render } from \"./BorderLine.vue?vue&type=template&id=630e246b&scoped=true\"\nimport script from \"./BorderLine.vue?vue&type=script&lang=ts\"\nexport * from \"./BorderLine.vue?vue&type=script&lang=ts\"\n\nimport \"./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-630e246b\"\n\nexport default script","\nimport { computed, defineComponent, reactive, PropType, watchEffect, toRefs } from 'vue'\nimport { useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { getElementListRange } from '@/utils/element'\nimport { OperateResizeHandler, MultiSelectRange } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'multi-select-operate',\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementList: {\n type: Array as PropType,\n required: true,\n },\n scaleMultiElement: {\n type: Function as PropType<(e: MouseEvent, range: MultiSelectRange, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const canvasScale = computed(() => store.state.canvasScale)\n const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))\n\n const range = reactive({\n minX: 0,\n maxX: 0,\n minY: 0,\n maxY: 0,\n })\n\n const width = computed(() => (range.maxX - range.minX) * canvasScale.value)\n const height = computed(() => (range.maxY - range.minY) * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(width, height)\n\n const disableResize = computed(() => {\n return localActiveElementList.value.some(item => {\n if(\n (item.type === 'image' || item.type === 'shape') && \n !item.rotate\n ) return false\n return true\n })\n })\n\n const setRange = () => {\n const { minX, maxX, minY, maxY } = getElementListRange(localActiveElementList.value)\n range.minX = minX\n range.maxX = maxX\n range.minY = minY\n range.maxY = maxY\n }\n\n watchEffect(setRange)\n\n return {\n ...toRefs(range),\n canvasScale,\n borderLines,\n disableResize,\n resizeHandlers,\n }\n },\n})\n","import { render } from \"./MultiSelectOperate.vue?vue&type=template&id=66dfa39d&scoped=true\"\nimport script from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiSelectOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiSelectOperate.vue?vue&type=style&index=0&id=66dfa39d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-66dfa39d\"\n\nexport default script","\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n","\n\n\n\n","\nexport default {\n name: 'rotate-handler',\n}\n","import { render } from \"./RotateHandler.vue?vue&type=template&id=9a549510&scoped=true\"\nimport script from \"./RotateHandler.vue?vue&type=script&lang=ts\"\nexport * from \"./RotateHandler.vue?vue&type=script&lang=ts\"\n\nimport \"./RotateHandler.vue?vue&type=style&index=0&id=9a549510&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-9a549510\"\n\nexport default script","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { PPTImageElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'image-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTImageElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTImageElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const clipingImageElementId = computed(() => store.state.clipingImageElementId)\r\n const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n isCliping,\r\n scaleWidth,\r\n resizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./ImageElementOperate.vue?vue&type=template&id=5b0628aa&scoped=true\"\nimport script from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageElementOperate.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageElementOperate.vue?vue&type=style&index=0&id=5b0628aa&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b0628aa\"\n\nexport default script","\r\n\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { useStore } from '@/store'\r\n\r\nimport { PPTTextElement } from '@/types/slides'\r\nimport { OperateResizeHandler } from '@/types/edit'\r\nimport useCommonOperate from '../hooks/useCommonOperate'\r\n\r\nimport RotateHandler from './RotateHandler.vue'\r\nimport ResizeHandler from './ResizeHandler.vue'\r\nimport BorderLine from './BorderLine.vue'\r\n\r\nexport default defineComponent({\r\n name: 'text-element-operate',\r\n inheritAttrs: false,\r\n components: {\r\n RotateHandler,\r\n ResizeHandler,\r\n BorderLine,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTTextElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTTextElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n\r\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\r\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\r\n\r\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\r\n\r\n return {\r\n scaleWidth,\r\n textElementResizeHandlers,\r\n borderLines,\r\n }\r\n },\r\n})\r\n","import { render } from \"./TextElementOperate.vue?vue&type=template&id=1f730982\"\nimport script from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TextElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport RotateHandler from './RotateHandler.vue'\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'shape-element-operate',\n inheritAttrs: false,\n components: {\n RotateHandler,\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n rotateElement: {\n type: Function as PropType<(element: PPTShapeElement) => void>,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n resizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./ShapeElementOperate.vue?vue&type=template&id=bfcf602e\"\nimport script from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTLineElement } from '@/types/slides'\nimport { OperateLineHandler, OperateLineHandlers } from '@/types/edit'\n\nimport ResizeHandler from './ResizeHandler.vue'\n\nexport default defineComponent({\n name: 'text-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n dragLineElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const resizeHandlers = computed(() => {\n return [\n {\n handler: OperateLineHandlers.START,\n style: {\n left: props.elementInfo.start[0] * canvasScale.value + 'px',\n top: props.elementInfo.start[1] * canvasScale.value + 'px',\n }\n },\n {\n handler: OperateLineHandlers.END,\n style: {\n left: props.elementInfo.end[0] * canvasScale.value + 'px',\n top: props.elementInfo.end[1] * canvasScale.value + 'px',\n }\n },\n ]\n })\n\n return {\n resizeHandlers,\n }\n },\n})\n","import { render } from \"./LineElementOperate.vue?vue&type=template&id=670e07f8\"\nimport script from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./LineElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTShapeElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'chart-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n resizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./ChartElementOperate.vue?vue&type=template&id=4218643e\"\nimport script from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport { PPTTableElement } from '@/types/slides'\nimport { OperateResizeHandler } from '@/types/edit'\nimport useCommonOperate from '../hooks/useCommonOperate'\n\nimport ResizeHandler from './ResizeHandler.vue'\nimport BorderLine from './BorderLine.vue'\n\nexport default defineComponent({\n name: 'table-element-operate',\n inheritAttrs: false,\n components: {\n ResizeHandler,\n BorderLine,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n isActiveGroupElement: {\n type: Boolean,\n required: true,\n },\n isMultiSelect: {\n type: Boolean,\n required: true,\n },\n scaleElement: {\n type: Function as PropType<(e: MouseEvent, element: PPTTableElement, command: OperateResizeHandler) => void>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n\n const outlineWidth = computed(() => props.elementInfo.outline.width || 1)\n\n const scaleWidth = computed(() => (props.elementInfo.width + outlineWidth.value) * canvasScale.value)\n const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)\n\n const { textElementResizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)\n\n return {\n scaleWidth,\n textElementResizeHandlers,\n borderLines,\n }\n },\n})\n","import { render } from \"./TableElementOperate.vue?vue&type=template&id=459ab724\"\nimport script from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nexport * from \"./TableElementOperate.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\nimport { defineComponent, PropType, computed } from 'vue'\r\nimport { useStore } from '@/store'\r\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\r\nimport { OperateLineHandler, OperateResizeHandler } from '@/types/edit'\r\n\r\nimport ImageElementOperate from './ImageElementOperate.vue'\r\nimport TextElementOperate from './TextElementOperate.vue'\r\nimport ShapeElementOperate from './ShapeElementOperate.vue'\r\nimport LineElementOperate from './LineElementOperate.vue'\r\nimport ChartElementOperate from './ChartElementOperate.vue'\r\nimport TableElementOperate from './TableElementOperate.vue'\r\n\r\nexport default defineComponent({\r\n name: 'operate',\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n isSelected: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActive: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isActiveGroupElement: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n isMultiSelect: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n rotateElement: {\r\n type: Function as PropType<(element: PPTElement) => void>,\r\n required: true,\r\n },\r\n scaleElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateResizeHandler) => void>,\r\n required: true,\r\n },\r\n dragLineElement: {\r\n type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateLineHandler) => void>,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const store = useStore()\r\n const canvasScale = computed(() => store.state.canvasScale)\r\n const toolbarState = computed(() => store.state.toolbarState)\r\n const currentSlide = computed(() => store.getters.currentSlide)\r\n\r\n const currentOperateComponent = computed(() => {\r\n const elementTypeMap = {\r\n [ElementTypes.IMAGE]: ImageElementOperate,\r\n [ElementTypes.TEXT]: TextElementOperate,\r\n [ElementTypes.SHAPE]: ShapeElementOperate,\r\n [ElementTypes.LINE]: LineElementOperate,\r\n [ElementTypes.CHART]: ChartElementOperate,\r\n [ElementTypes.TABLE]: TableElementOperate,\r\n }\r\n return elementTypeMap[props.elementInfo.type] || null\r\n })\r\n\r\n const elementIndexInAnimation = computed(() => {\r\n const animations = currentSlide.value.animations || []\r\n return animations.findIndex(animation => animation.elId === props.elementInfo.id)\r\n })\r\n\r\n return {\r\n currentOperateComponent,\r\n canvasScale,\r\n toolbarState,\r\n elementIndexInAnimation,\r\n }\r\n },\r\n})\r\n","import { render } from \"./index.vue?vue&type=template&id=558a94fe&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=558a94fe&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-558a94fe\"\n\nexport default script","\nimport { computed, defineComponent, provide, ref, watch, watchEffect } from 'vue'\nimport throttle from 'lodash/throttle'\nimport { MutationTypes, useStore } from '@/store'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { AlignmentLineProps } from '@/types/edit'\nimport { removeAllRanges } from '@/utils/selection'\n\nimport useViewportSize from './hooks/useViewportSize'\nimport useMouseSelection from './hooks/useMouseSelection'\nimport useDropImageOrText from './hooks/useDropImageOrText'\nimport useRotateElement from './hooks/useRotateElement'\nimport useScaleElement from './hooks/useScaleElement'\nimport useSelectElement from './hooks/useSelectElement'\nimport useDragElement from './hooks/useDragElement'\nimport useDragLineElement from './hooks/useDragLineElement'\nimport useInsertFromCreateSelection from './hooks/useInsertFromCreateSelection'\n\nimport useDeleteElement from '@/hooks/useDeleteElement'\nimport useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'\nimport useSelectAllElement from '@/hooks/useSelectAllElement'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\n\nimport EditableElement from './EditableElement.vue'\nimport MouseSelection from './MouseSelection.vue'\nimport SlideBackground from './SlideBackground.vue'\nimport AlignmentLine from './AlignmentLine.vue'\nimport ElementCreateSelection from './ElementCreateSelection.vue'\nimport MultiSelectOperate from './Operate/MultiSelectOperate.vue'\nimport Operate from './Operate/index.vue'\n\nexport default defineComponent({\n name: 'editor-canvas',\n components: {\n EditableElement,\n MouseSelection,\n SlideBackground,\n AlignmentLine,\n ElementCreateSelection,\n MultiSelectOperate,\n Operate,\n },\n setup() {\n const store = useStore()\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const handleElementId = computed(() => store.state.handleElementId)\n const editorAreaFocus = computed(() => store.state.editorAreaFocus)\n const ctrlKeyState = computed(() => store.state.ctrlKeyState)\n const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive)\n\n const viewportRef = ref()\n const alignmentLines = ref([])\n\n const activeGroupElementId = ref('')\n watch(handleElementId, () => activeGroupElementId.value = '')\n\n const currentSlide = computed(() => store.getters.currentSlide)\n const elementList = ref([])\n const setLocalElementList = () => {\n elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []\n }\n watchEffect(setLocalElementList)\n\n const canvasRef = ref()\n const canvasScale = computed(() => store.state.canvasScale)\n const { viewportStyles } = useViewportSize(canvasRef)\n\n useDropImageOrText(canvasRef)\n\n const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef)\n\n const { dragElement } = useDragElement(elementList, activeGroupElementId, alignmentLines)\n const { dragLineElement } = useDragLineElement(elementList)\n const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)\n const { scaleElement, scaleMultiElement } = useScaleElement(elementList, activeGroupElementId, alignmentLines)\n const { rotateElement } = useRotateElement(elementList, viewportRef)\n\n const { selectAllElement } = useSelectAllElement()\n const { deleteAllElements } = useDeleteElement()\n const { pasteElement } = useCopyAndPasteElement()\n\n const handleClickBlankArea = (e: MouseEvent) => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n if(!ctrlOrShiftKeyActive.value) updateMouseSelection(e)\n if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)\n removeAllRanges()\n }\n\n const removeEditorAreaFocus = () => {\n if(editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)\n }\n\n const { scaleCanvas } = useScaleCanvas()\n const throttleScaleCanvas = throttle(scaleCanvas, 100, { leading: true, trailing: false })\n\n const mousewheelScaleCanvas = (e: WheelEvent) => {\n if(!ctrlKeyState.value) return\n\n e.preventDefault()\n if(e.deltaY > 0) throttleScaleCanvas('-')\n else if(e.deltaY < 0) throttleScaleCanvas('+')\n }\n\n const showGridLines = computed(() => store.state.showGridLines)\n const toggleGridLines = () => {\n store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)\n }\n\n const creatingElement = computed(() => store.state.creatingElement)\n const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '全选',\n subText: 'Ctrl + A',\n handler: selectAllElement,\n },\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteElement,\n },\n {\n text: showGridLines.value ? '关闭网格线' : '打开网格线',\n handler: toggleGridLines,\n },\n {\n text: '清空本页',\n handler: deleteAllElements,\n },\n ]\n }\n\n provide('slideScale', canvasScale)\n\n return {\n elementList,\n activeElementIdList,\n handleElementId,\n activeGroupElementId,\n canvasRef,\n viewportRef,\n viewportStyles,\n canvasScale,\n mouseSelectionState,\n handleClickBlankArea,\n removeEditorAreaFocus,\n currentSlide,\n creatingElement,\n insertElementFromCreateSelection,\n alignmentLines,\n selectElement,\n rotateElement,\n scaleElement,\n dragLineElement,\n scaleMultiElement,\n mousewheelScaleCanvas,\n contextmenus,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=75c486b2&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=75c486b2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-75c486b2\"\n\nexport default script","\n\n\n\n","\n\n\n\n","export interface ShapePoolItem {\n viewBox: number;\n path: string;\n}\n\nexport const SHAPE_LIST = [\n {\n type: '矩形',\n children: [\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200'\n },\n {\n viewBox: 200,\n path: 'M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z'\n },\n ]\n },\n\n {\n type: '常用形状',\n children: [\n {\n viewBox: 200,\n path: 'M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 A 100 100 102 1 0 200 100 L 200 0 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 Q 200 200 0 200 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 200 L 200 200 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 0 200 L 200 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 200 0 L 150 200 L 0 200 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 150 0 L 200 200 L 0 200 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 100 L 100 200 L 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 90 L 50 200 L 150 200 L 200 90 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 60 L 0 140 L 100 200 L 200 140 L 200 60 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 60 0 L 140 0 L 200 60 L 200 140 L 140 200 L 60 200 L 0 140 L 0 60 L 60 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 50 L 0 200 L 200 200 L 200 50 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 L 0 0 L 150 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 150 0 A 50 100 0 1 1 150 200 L 0 200 A 50 100 0 0 0 0 0 L 150 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 150 0 L 0 0 L 50 100 L 0 200 L 150 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 0 L 200 200 L 0 200 L 0 100 L 200 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 50 0 L 150 0 L 150 50 L 200 50 L 200 150 L 150 150 L 150 200 L 50 200 L 50 150 L 0 150 L 0 50 L 50 50 L 50 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 0 200 L 200 200 L 200 140 L 60 140 L 60 0 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M0 0 L200 0 L200 200 L0 200 L0 0 Z M50 50 L50 150 L150 150 L150 50 Z'\n },\n {\n viewBox: 200,\n path: 'M0 100 A100 100 0 1 1 0 101 Z M150 100 A50 50 0 1 0 150 101 Z'\n },\n {\n viewBox: 200,\n path: 'M 70 0 L 70 70 L 0 70 L 0 130 L 70 130 L 70 200 L 130 200 L 130 130 L 200 130 L 200 70 L 130 70 L 130 0 L 70 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 40 0 L 0 40 L 60 100 L 0 160 L 40 200 L 100 140 L 160 200 L 200 160 L 140 100 L 200 40 L 160 0 L 100 60 L 40 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 200 0 L 200 160 L 100 160 L 60 200 L 60 160 L 0 160 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 40 Q 0 0 40 0 L 160 0 Q 200 0 200 40 L 200 120 Q 200 160 160 160 L 100 160 L 60 200 L 60 160 L 40 160 Q 0 160 0 120 L 0 40 Z'\n },\n ],\n },\n \n {\n type: '箭头',\n children: [\n {\n viewBox: 200,\n path: 'M 100 0 L 0 100 L 50 100 L 50 200 L 150 200 L 150 100 L 200 100 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 200 L 200 100 L 150 100 L 150 0 L 50 0 L 50 100 L 0 100 L 100 200 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 200 150 L 100 150 L 100 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 0 150 L 100 150 L 100 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 0 60 L 60 60 L 60 140 L 0 140 L 100 200 L 200 140 L 140 140 L 140 60 L 200 60 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 60 0 L 60 60 L 140 60 L 140 0 L 200 100 L 140 200 L 140 140 L 60 140 L 60 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 100 0 L 60 40 L 80 40 L 80 80 L 40 80 L 40 60 L 0 100 L 40 140 L 40 120 L 80 120 L 80 160 L 60 160 L 100 200 L 140 160 L 120 160 L 120 120 L 160 120 L 160 140 L 200 100 L 160 60 L 160 80 L 120 80 L 120 40 L 140 40 L 100 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 100 0 L 100 50 L 200 50 L 150 100 L 200 150 L 100 150 L 100 200 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 100 0 L 100 50 L 0 50 L 50 100 L 0 150 L 100 150 L 100 200 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 100 L 80 20 L 80 80 L 120 80 L 120 0 L 200 0 L 200 200 L 120 200 L 120 120 L 80 120 L 80 180 L 0 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 200 100 L 120 20 L 120 80 L 80 80 L 80 0 L 0 0 L 0 200 L 80 200 L 80 120 L 120 120 L 120 180 L 200 100 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 120 0 L 200 100 L 120 200 L 0 200 L 80 100 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 80 0 L 200 0 L 120 100 L 200 200 L 80 200 L 0 100 L 80 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 0 0 L 140 0 L 200 100 L 140 200 L 0 200 L 0 100 L 0 0 Z'\n },\n {\n viewBox: 200,\n path: 'M 60 0 L 200 0 L 200 100 L 200 200 L 60 200 L 0 100 L 60 0 Z'\n },\n ],\n },\n\n {\n type: '其他形状',\n children: [\n {\n viewBox: 1024,\n path: 'M995.336 243.4016c-15.7584-36.5736-38.3376-69.26639999-66.91440001-97.37280001-28.5768-27.98879999-61.73999999-49.8624-98.78399999-65.26799998-38.22-15.876-78.6744-23.8728-120.4224-23.87280001-57.97680001 0-114.5424 15.876-163.69919999 45.864-11.76 7.17360001-22.932 15.05279999-33.51600001 23.63760001-10.584-8.5848-21.75600001-16.46400001-33.51600001-23.63760001-49.1568-29.98799999-105.7224-45.86399999-163.69919999-45.864-41.74799999 0-82.2024 7.9968-120.4224 23.87280001-36.9264 15.28799999-70.2072 37.27919999-98.78399999 65.26799998-28.6944 28.10640001-51.156 60.79919999-66.91440001 97.37280001-16.34639999 37.9848-24.696 78.3216-24.696 119.83439999 0 39.1608 7.9968 79.96800001 23.8728 121.48080001 13.28880001 34.692 32.34000001 70.67760001 56.6832 107.016 38.57279999 57.5064 91.61040001 117.4824 157.4664 178.28160001 109.1328 100.78319999 217.2072 170.4024 221.79359999 173.22479998l27.87120001 17.8752c12.348 7.8792 28.224 7.8792 40.572 0l27.87119999-17.8752c4.58639999-2.94 112.54319999-72.44159999 221.79360001-173.22479998 65.85599999-60.79919999 118.89359999-120.7752 157.4664-178.28160001 24.3432-36.33839999 43.512-72.324 56.68319999-107.016 15.876-41.5128 23.8728-82.32 23.87280001-121.48080001 0.1176-41.5128-8.232-81.8496-24.5784-119.83439999z',\n },\n {\n viewBox: 1024,\n path: 'M985.20746667 343.50079998l-303.32586667-44.08319999L546.28693333 24.5248c-3.70346666-7.5264-9.79626667-13.6192-17.32266665-17.32266668-18.87573334-9.3184-41.81333333-1.55306667-51.25120001 17.32266668L342.1184 299.41759999l-303.32586667 44.08319999c-8.36266667 1.19466667-16.00853333 5.13706667-21.8624 11.11040001-14.69440001 15.17226667-14.45546667 39.30453334 0.71679999 54.1184l219.46026668 213.9648-51.84853333 302.1312c-1.43359999 8.24320001-0.11946667 16.8448 3.82293333 24.25173333 9.79626667 18.6368 32.9728 25.92426667 51.6096 16.00853334L512 822.44266665l271.3088 142.64320001c7.40693333 3.9424 16.00853333 5.25653333 24.25173333 3.82293333 20.78719999-3.584 34.7648-23.296 31.1808-44.0832l-51.84853333-302.1312 219.46026668-213.9648c5.97333334-5.85386666 9.91573333-13.49973334 11.11039999-21.8624 3.2256-20.90666667-11.34933333-40.26026667-32.256-43.36640001z',\n },\n {\n viewBox: 1024,\n path: 'M852.65066667 405.84533333C800.54044445 268.40177778 667.76177778 170.66666667 512.22755555 170.66666667S223.91466667 268.288 171.80444445 405.73155555C74.29688889 431.33155555 2.27555555 520.07822222 2.27555555 625.77777778c0 125.72444445 101.83111111 227.55555555 227.44177778 227.55555555h564.56533334C919.89333333 853.33333333 1021.72444445 751.50222222 1021.72444445 625.77777778c0-105.472-71.79377778-194.21866667-169.07377778-219.93244445z',\n },\n {\n viewBox: 1024,\n path: 'M926.25224691 323.7371485H654.6457886L898.88200917 15.14388241c5.05486373-6.53433603 0.49315743-16.02761669-7.76722963-16.02761668H418.30008701c-3.45210206 0-6.78091476 1.84934039-8.50696579 4.93157436L90.35039154 555.76772251c-3.82197013 6.53433603 0.86302552 14.7947231 8.50696578 14.79472311h215.01664245l-110.22068713 440.88274851c-2.34249783 9.61657002 9.24670194 16.39748478 16.39748477 9.49328065L933.03316167 340.62779071c6.41104668-6.0411786 2.09591911-16.8906422-6.78091476-16.89064221z',\n },\n {\n viewBox: 1024,\n path: 'M878.47822222 463.30311111c-22.18666667-49.83466667-53.93066667-93.98044445-94.32177777-131.072l-33.10933334-30.37866666c-4.89244445-4.32355555-12.62933333-2.38933333-14.79111111 3.75466666l-14.79111111 42.43911111c-9.216 26.624-26.16888889 53.81688889-50.176 80.55466667-1.59288889 1.70666667-3.41333333 2.16177778-4.66488889 2.27555556-1.25155555 0.11377778-3.18577778-0.11377778-4.89244445-1.70666667-1.59288889-1.36533333-2.38933333-3.41333333-2.27555555-5.46133333 4.20977778-68.49422222-16.27022222-145.74933333-61.09866667-229.83111112C561.26577778 124.01777778 509.72444445 69.51822222 445.32622222 31.51644445l-46.99022222-27.648c-6.144-3.64088889-13.99466667 1.13777778-13.65333333 8.30577777l2.50311111 54.61333333c1.70666667 37.31911111-2.61688889 70.31466667-12.85688889 97.73511112-12.51555555 33.56444445-30.49244445 64.73955555-53.47555556 92.72888888-16.15644445 19.56977778-34.24711111 37.20533333-54.04444444 52.45155556-47.90044445 36.75022222-87.38133333 84.65066667-114.11911111 138.24C125.72444445 502.10133333 111.50222222 562.74488889 111.50222222 623.50222222c0 53.70311111 10.58133333 105.69955555 31.51644445 154.73777778 20.25244445 47.21777778 49.152 89.77066667 85.90222222 126.17955555 36.864 36.40888889 79.64444445 65.08088889 127.31733333 84.992C405.61777778 1010.11911111 457.95555555 1020.58666667 512 1020.58666667s106.38222222-10.46755555 155.76177778-31.06133334c47.67288889-19.91111111 90.56711111-48.46933333 127.31733333-84.992 36.864-36.40888889 65.76355555-78.96177778 85.90222222-126.17955555 20.93511111-49.03822222 31.51644445-101.03466667 31.51644445-154.73777778 0-55.52355555-11.37777778-109.45422222-34.01955556-160.31288889z',\n },\n {\n viewBox: 1024,\n path: 'M968.20337778 20.11591112H705.44042667c-22.17301333 0-41.92483556 15.16430222-47.14951111 37.33731555C642.36202666 124.73685332 582.08711111 173.03324444 512 173.03324444s-130.36202666-48.29639112-146.29091556-115.58001777c-5.22467555-22.17301333-24.84906667-37.33731556-47.14951111-37.33731555H55.79662222c-30.96576 0-56.06968889 25.10392889-56.06968888 56.06968888v321.12639999c0 30.96576 25.10392889 56.06968889 56.06968888 56.06968889h95.57333334v494.43271112c0 30.96576 25.10392889 56.06968889 56.06968889 56.06968888h609.1207111c30.96576 0 56.06968889-25.10392889 56.06968889-56.06968888V453.38168888h95.57333334c30.96576 0 56.06968889-25.10392889 56.06968888-56.06968889V76.1856c0-30.96576-25.10392889-56.06968889-56.06968888-56.06968888z',\n },\n {\n viewBox: 1024,\n path: 'M980.94648889 239.80714666H523.46880001L373.99210666 96.82944c-1.91146667-1.78403556-4.46008889-2.80348444-7.00871111-2.80348445H43.05351111c-22.55530667 0-40.77795555 18.22264888-40.77795555 40.77795557v754.39217776c0 22.55530667 18.22264888 40.77795555 40.77795555 40.77795557h937.89297778c22.55530667 0 40.77795555-18.22264888 40.77795555-40.77795557V280.58510222c0-22.55530667-18.22264888-40.77795555-40.77795555-40.77795556z',\n },\n {\n viewBox: 1024,\n path: 'M972.60904597 164.57058577L841.30587843 33.39070759c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480282-29.3428675-26.75379095 0-51.90482023 10.47959553-70.76809219 29.3428675L558.60337778 174.68031322c-18.86327195 18.86327195-29.34286748 44.1375906-29.34286749 70.64480283 0 26.75379095 10.47959553 51.90482023 29.34286749 70.76809218l103.31648301 103.31648302c-24.28800376 53.50758189-57.69942011 101.59043198-99.24793416 143.13894603-41.42522469 41.67180341-89.63136414 75.08321976-143.13894603 99.61780223L316.21649759 558.84995649c-18.86327195-18.86327195-44.1375906-29.34286748-70.64480283-29.34286747-26.75379095 0-51.90482023 10.47959553-70.76809217 29.34286747L33.39070759 700.01627278c-18.86327195 18.86327195-29.34286748 44.1375906-29.3428675 70.76809217 0 26.75379095 10.47959553 51.90482023 29.3428675 70.76809219l131.05658883 131.05658883c30.08260365 30.205893 71.63111769 47.34311394 114.28923598 47.34311394 9.00012323 0 17.63037836-0.73973616 26.13734414-2.21920846 166.19405621-27.37023774 331.03192945-115.76870829 464.06114804-248.67463751C901.84095379 636.27567408 990.11613498 471.56109018 1017.85624079 304.87387654c8.38367642-50.91850535-8.50696579-103.31648302-45.24719482-140.30329077z',\n },\n {\n viewBox: 1024,\n path: 'M910.60451556 640.96028445c-20.38897778-65.49959112-43.83630221-120.54983112-79.89930667-210.64362666C836.31217778 193.67708444 737.93535999 2.27555556 511.36284444 2.27555556 282.24170667 2.27555556 186.03121778 197.50001778 192.14791111 430.31665779c-36.19043555 90.22122667-59.51032888 144.88917333-79.89930667 210.64362666-43.32657778 139.53706668-29.30915556 197.26336001-18.60494222 198.53767111 22.9376 2.80348444 89.32920888-105.00323556 89.32920889-105.00323556 0 62.44124445 32.11264001 143.86972444 101.69002667 202.61546667-33.64181333 10.32192-109.20846222 38.10190221-91.24067556 68.55793777 14.52714667 24.59420444 250.01984 15.67402668 317.94062222 8.02816 67.92078222 7.64586667 303.41347556 16.56604444 317.94062223-8.02816 17.96778667-30.32860444-57.72629333-58.23601779-91.24067555-68.55793777 69.57738667-58.87317334 101.69002667-140.30165333 101.69002667-202.61546667 0 0 66.39160889 107.80672 89.32920888 105.00323556 10.83164445-1.40174222 24.84906667-59.12803556-18.47751111-198.53767111z',\n },\n {\n viewBox: 1024,\n path: 'M1016.86992592 199.24764445c-37.13706667 16.01991111-77.55093333 27.54939259-119.17842962 32.03982222 42.96248889-25.60758518 75.60912592-66.02145185 91.02222222-114.08118519-39.68568889 23.66577778-84.58998518 41.02068148-131.31472593 50.00154074C819.53374815 126.79395555 765.76995555 101.79318518 706.18074075 101.79318518c-114.688 0-206.92385185 92.96402963-206.92385186 207.04521482 0 16.01991111 1.94180741 32.03982222 5.09724444 47.45291852-171.72859259-8.98085925-324.88865185-91.02222222-426.71217778-216.63288889-17.96171852 30.82619259-28.15620741 66.02145185-28.1562074 104.49351112 0 71.84687408 36.53025185 135.19834075 92.23585185 172.45677036-33.98162963-1.33499259-66.02145185-10.92266667-93.57084445-26.33576296v2.54862222c0 100.6098963 71.1186963 183.98625185 165.90317037 203.1616-17.3549037 4.49042963-35.92343703 7.03905185-54.49197037 7.03905185-13.47128889 0-26.2144-1.33499259-39.07887407-3.15543704C146.69748148 681.90814815 223.03478518 741.49736297 313.93564445 743.43917037c-71.1186963 55.7056-160.19911111 88.4736-256.9253926 88.4736-17.3549037 0-33.37481482-0.60681482-50.00154074-2.54862222C98.75911111 888.22518518 207.62168889 922.20681482 324.85831111 922.20681482 705.45256297 922.20681482 913.71140741 606.90583703 913.71140741 333.23235555c0-8.98085925 0-17.96171852-0.60681482-26.94257777 40.2925037-29.4912 75.60912592-66.02145185 103.76533333-107.04213333z',\n },\n ],\n },\n]","\nimport { defineComponent } from 'vue'\nimport { SHAPE_LIST, ShapePoolItem } from '@/configs/shapes'\n\nexport default defineComponent({\n name: 'shape-pool',\n setup(props, { emit }) {\n const shapeList = SHAPE_LIST\n\n const selectShape = (shape: ShapePoolItem) => {\n emit('select', shape)\n }\n\n return {\n shapeList,\n selectShape,\n }\n },\n})\n","import { render } from \"./ShapePool.vue?vue&type=template&id=e95c032e&scoped=true\"\nimport script from \"./ShapePool.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapePool.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapePool.vue?vue&type=style&index=0&id=e95c032e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-e95c032e\"\n\nexport default script","\n\n\n\n","export interface LinePoolItem {\n path: string;\n style: string;\n points: [string, string];\n}\n\nexport const LINE_LIST = [\n { path: 'M0,0 L20,20', style: 'solid', points: ['', ''] },\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', ''] },\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'arrow'] },\n { path: 'M0,0 L20,20', style: 'dashed', points: ['', 'arrow'] },\n { path: 'M0,0 L20,20', style: 'solid', points: ['', 'dot'] },\n]","\nimport { defineComponent } from 'vue'\nimport { LINE_LIST, LinePoolItem } from '@/configs/lines'\n\nimport LinePointMarker from '@/views/components/element/LineElement/LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'line-pool',\n components: {\n LinePointMarker,\n },\n setup(props, { emit }) {\n const lineList = LINE_LIST\n\n const selectLine = (line: LinePoolItem) => {\n emit('select', line)\n }\n\n return {\n lineList,\n selectLine,\n }\n },\n})\n","import { render } from \"./LinePool.vue?vue&type=template&id=a0f5af54&scoped=true\"\nimport script from \"./LinePool.vue?vue&type=script&lang=ts\"\nexport * from \"./LinePool.vue?vue&type=script&lang=ts\"\n\nimport \"./LinePool.vue?vue&type=style&index=0&id=a0f5af54&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a0f5af54\"\n\nexport default script","\n\n\n\n","\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n name: 'chart-pool',\n setup(props, { emit }) {\n const chartList = ['bar', 'line', 'pie']\n\n const selectChart = (chart: string) => {\n emit('select', chart)\n }\n\n return {\n chartList,\n selectChart,\n }\n },\n})\n","import { render } from \"./ChartPool.vue?vue&type=template&id=28a1a821&scoped=true\"\nimport script from \"./ChartPool.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartPool.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartPool.vue?vue&type=style&index=0&id=28a1a821&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-28a1a821\"\n\nexport default script","\n\n\n\n","\nimport { defineComponent, ref } from 'vue'\n\nimport { message } from 'ant-design-vue'\n\nexport default defineComponent({\n name: 'table-generator',\n setup(props, { emit }) {\n const endCell = ref([])\n const customRow = ref(3)\n const customCol = ref(3)\n const isCustom = ref(false)\n\n const handleClickTable = () => {\n if(!endCell.value.length) return\n const [row, col] = endCell.value\n emit('insert', { row, col })\n }\n\n const insertCustomTable = () => {\n if(customRow.value < 1 || customRow.value > 20) return message.warning('行数/列数必须在0~20之间!')\n if(customCol.value < 1 || customCol.value > 20) return message.warning('行数/列数必须在0~20之间!')\n emit('insert', { row: customRow.value, col: customCol.value })\n isCustom.value = false\n }\n\n const close = () => {\n emit('close')\n isCustom.value = false\n }\n\n return {\n endCell,\n customRow,\n customCol,\n handleClickTable,\n insertCustomTable,\n isCustom,\n close,\n }\n },\n})\n","import { render } from \"./TableGenerator.vue?vue&type=template&id=0239b43b&scoped=true\"\nimport script from \"./TableGenerator.vue?vue&type=script&lang=ts\"\nexport * from \"./TableGenerator.vue?vue&type=script&lang=ts\"\n\nimport \"./TableGenerator.vue?vue&type=style&index=0&id=0239b43b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0239b43b\"\n\nexport default script","\nimport { defineComponent, computed, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { getImageDataURL } from '@/utils/image'\nimport { ShapePoolItem } from '@/configs/shapes'\nimport { LinePoolItem } from '@/configs/lines'\nimport useScaleCanvas from '@/hooks/useScaleCanvas'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCreateElement from '@/hooks/useCreateElement'\n\nimport ShapePool from './ShapePool.vue'\nimport LinePool from './LinePool.vue'\nimport ChartPool from './ChartPool.vue'\nimport TableGenerator from './TableGenerator.vue'\n\nexport default defineComponent({\n name: 'canvas-tool',\n components: {\n ShapePool,\n LinePool,\n ChartPool,\n TableGenerator,\n },\n setup() {\n const store = useStore()\n const canvasScale = computed(() => store.state.canvasScale)\n const canUndo = computed(() => store.getters.canUndo)\n const canRedo = computed(() => store.getters.canRedo)\n\n const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')\n\n const { scaleCanvas, setCanvasPercentage } = useScaleCanvas()\n const { redo, undo } = useHistorySnapshot()\n\n const { createImageElement, createChartElement, createTableElement } = useCreateElement()\n\n const insertImageElement = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))\n }\n\n const shapePoolVisible = ref(false)\n const linePoolVisible = ref(false)\n const chartPoolVisible = ref(false)\n const tableGeneratorVisible = ref(false)\n\n const drawText = () => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'text',\n data: null,\n })\n }\n const drawShape = (shape: ShapePoolItem) => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'shape',\n data: shape,\n })\n shapePoolVisible.value = false\n }\n const drawLine = (line: LinePoolItem) => {\n store.commit(MutationTypes.SET_CREATING_ELEMENT, {\n type: 'line',\n data: line,\n })\n linePoolVisible.value = false\n }\n\n return {\n scaleCanvas,\n setCanvasPercentage,\n canvasScalePercentage,\n canUndo,\n canRedo,\n redo,\n undo,\n insertImageElement,\n shapePoolVisible,\n linePoolVisible,\n chartPoolVisible,\n tableGeneratorVisible,\n drawText,\n drawShape,\n drawLine,\n createChartElement,\n createTableElement,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=1a2df855&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=1a2df855&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1a2df855\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\n\nimport { PPTImageElement } from '@/types/slides'\nimport { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'\n\nimport ImageRectOutline from './ImageRectOutline.vue'\nimport ImageEllipseOutline from './ImageEllipseOutline.vue'\nimport ImagePolygonOutline from './ImagePolygonOutline.vue'\n\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nexport default defineComponent({\n name: 'base-element-image',\n components: {\n ImageRectOutline,\n ImageEllipseOutline,\n ImagePolygonOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const imgPosition = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) {\n return {\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n }\n }\n\n const [start, end] = props.elementInfo.clip.range\n\n const widthScale = (end[0] - start[0]) / 100\n const heightScale = (end[1] - start[1]) / 100\n const left = start[0] / widthScale\n const top = start[1] / heightScale\n\n return {\n left: -left + '%',\n top: -top + '%',\n width: 100 / widthScale + '%',\n height: 100 / heightScale + '%',\n }\n })\n\n const clipShape = computed(() => {\n if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect\n const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT\n\n return CLIPPATHS[shape]\n })\n\n const filter = computed(() => {\n if(!props.elementInfo.filters) return ''\n let filter = ''\n for(const key of Object.keys(props.elementInfo.filters)) {\n filter += `${key}(${props.elementInfo.filters[key]}) `\n }\n return filter\n })\n\n const flip = computed(() => {\n if(!props.elementInfo.flip) return ''\n const { x, y } = props.elementInfo.flip\n if(x && y) return `rotateX(${x}deg) rotateY(${y}deg)`\n else if(x) return `rotateX(${x}deg)`\n else if(y) return `rotateY(${y}deg)`\n return ''\n })\n\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n imgPosition,\n clipShape,\n filter,\n flip,\n shadowStyle,\n }\n },\n})\n","import { render } from \"./BaseImageElement.vue?vue&type=template&id=008489be&scoped=true\"\nimport script from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseImageElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseImageElement.vue?vue&type=style&index=0&id=008489be&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-008489be\"\n\nexport default script","\n\n\n\n\n","\nimport { defineComponent, PropType, computed } from 'vue'\nimport { PPTTextElement } from '@/types/slides'\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\n\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nexport default defineComponent({\n name: 'base-element-text',\n components: {\n ElementOutline,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n shadowStyle,\n }\n },\n})\n","import { render } from \"./BaseTextElement.vue?vue&type=template&id=fc2d45e0&scoped=true\"\nimport script from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTextElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTextElement.vue?vue&type=style&index=0&id=fc2d45e0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-fc2d45e0\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTShapeElement } from '@/types/slides'\nimport useElementOutline from '@/views/components/element/hooks/useElementOutline'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport GradientDefs from './GradientDefs.vue'\n\nexport default defineComponent({\n name: 'base-element-shape',\n components: {\n GradientDefs,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const outline = computed(() => props.elementInfo.outline)\n const { outlineWidth, outlineStyle, outlineColor } = useElementOutline(outline)\n \n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n return {\n shadowStyle,\n outlineWidth,\n outlineStyle,\n outlineColor,\n }\n },\n})\n","import { render } from \"./BaseShapeElement.vue?vue&type=template&id=a34ea4ec&scoped=true\"\nimport script from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseShapeElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseShapeElement.vue?vue&type=style&index=0&id=a34ea4ec&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a34ea4ec\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { PPTLineElement } from '@/types/slides'\nimport useElementShadow from '@/views/components/element/hooks/useElementShadow'\n\nimport LinePointMarker from './LinePointMarker.vue'\n\nexport default defineComponent({\n name: 'editable-element-shape',\n components: {\n LinePointMarker,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props) {\n const shadow = computed(() => props.elementInfo.shadow)\n const { shadowStyle } = useElementShadow(shadow)\n\n const svgWidth = computed(() => {\n const width = Math.abs(props.elementInfo.start[0] - props.elementInfo.end[0])\n return width < 24 ? 24 : width\n })\n const svgHeight = computed(() => {\n const height = Math.abs(props.elementInfo.start[1] - props.elementInfo.end[1])\n return height < 24 ? 24 : height\n })\n\n const lineDashArray = computed(() => props.elementInfo.style === 'dashed' ? '10, 5' : '0, 0')\n const path = computed(() => {\n const start = props.elementInfo.start.join(',')\n const end = props.elementInfo.end.join(',')\n return `M${start} L${end}`\n })\n\n return {\n shadowStyle,\n svgWidth,\n svgHeight,\n lineDashArray,\n path,\n }\n },\n})\n","import { render } from \"./BaseLineElement.vue?vue&type=template&id=103a3e59&scoped=true\"\nimport script from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseLineElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseLineElement.vue?vue&type=style&index=0&id=103a3e59&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-103a3e59\"\n\nexport default script","\r\n\r\n\r\n\r\n\r\n","\r\nimport { computed, defineComponent, PropType } from 'vue'\r\nimport { PPTChartElement } from '@/types/slides'\r\n\r\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\r\n\r\nexport default defineComponent({\r\n name: 'base-element-chart',\r\n components: {\r\n ElementOutline,\r\n },\r\n props: {\r\n elementInfo: {\r\n type: Object as PropType,\r\n required: true,\r\n },\r\n },\r\n setup(props) {\r\n const size = computed(() => Math.min(props.elementInfo.width, props.elementInfo.height))\r\n\r\n return {\r\n size,\r\n }\r\n },\r\n})\r\n","import { render } from \"./BaseChartElement.vue?vue&type=template&id=b4562eca&scoped=true\"\nimport script from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseChartElement.vue?vue&type=style&index=0&id=b4562eca&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b4562eca\"\n\nexport default script","\n\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent, PropType, ref, watch } from 'vue'\nimport tinycolor from 'tinycolor2'\nimport { PPTElementOutline, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\n\nexport default defineComponent({\n name: 'static-table',\n props: {\n data: {\n type: Array as PropType,\n required: true,\n },\n width: {\n type: Number,\n required: true,\n },\n colWidths: {\n type: Array as PropType,\n required: true,\n },\n outline: {\n type: Object as PropType,\n required: true,\n },\n theme: {\n type: Object as PropType,\n },\n editable: {\n type: Boolean,\n default: true,\n },\n },\n setup(props) {\n const colSizeList = ref([])\n const totalWidth = computed(() => colSizeList.value.reduce((a, b) => a + b))\n\n watch([\n () => props.colWidths,\n () => props.width,\n ], () => {\n colSizeList.value = props.colWidths.map(item => item * props.width)\n }, { immediate: true })\n\n const hideCells = computed(() => {\n const hideCells = []\n \n for(let i = 0; i < props.data.length; i++) {\n const rowCells = props.data[i]\n\n for(let j = 0; j < rowCells.length; j++) {\n const cell = rowCells[j]\n \n if(cell.colspan > 1 || cell.rowspan > 1) {\n for(let row = i; row < i + cell.rowspan; row++) {\n for(let col = row === i ? j + 1 : j; col < j + cell.colspan; col++) {\n hideCells.push(`${row}_${col}`)\n }\n }\n }\n }\n }\n return hideCells\n })\n\n const subThemeColor = ref(['', ''])\n watch(() => props.theme, () => {\n if(props.theme) {\n const rgba = tinycolor(props.theme.color).toRgb()\n const subRgba1 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.3 }\n const subRgba2 = { r: rgba.r, g: rgba.g, b: rgba.b, a: rgba.a * 0.1 }\n subThemeColor.value = [\n `rgba(${[subRgba1.r, subRgba1.g, subRgba1.b, subRgba1.a].join(',')})`,\n `rgba(${[subRgba2.r, subRgba2.g, subRgba2.b, subRgba2.a].join(',')})`,\n ]\n }\n }, { immediate: true })\n\n const getTextStyle = (style?: TableCellStyle) => {\n if(!style) return {}\n const {\n bold,\n em,\n underline,\n strikethrough,\n color,\n backcolor,\n fontsize,\n fontname,\n align,\n } = style\n \n return {\n fontWeight: bold ? 'bold' : 'normal',\n fontStyle: em ? 'italic' : 'normal',\n textDecoration: `${underline ? 'underline' : ''} ${strikethrough ? 'line-through' : ''}`,\n color: color || '#000',\n backgroundColor: backcolor || '',\n fontSize: fontsize || '14px',\n fontFamily: fontname || '微软雅黑',\n textAlign: align || 'left',\n }\n }\n\n return {\n colSizeList,\n totalWidth,\n hideCells,\n getTextStyle,\n subThemeColor,\n }\n },\n})\n","import { render } from \"./StaticTable.vue?vue&type=template&id=12bfa92e&scoped=true\"\nimport script from \"./StaticTable.vue?vue&type=script&lang=ts\"\nexport * from \"./StaticTable.vue?vue&type=script&lang=ts\"\n\nimport \"./StaticTable.vue?vue&type=style&index=0&id=12bfa92e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-12bfa92e\"\n\nexport default script","\nimport { defineComponent, PropType } from 'vue'\nimport { PPTTableElement } from '@/types/slides'\n\nimport StaticTable from './StaticTable.vue'\n\nexport default defineComponent({\n name: 'base-element-table',\n components: {\n StaticTable,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n})\n","import { render } from \"./BaseTableElement.vue?vue&type=template&id=dea016ac&scoped=true\"\nimport script from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\nexport * from \"./BaseTableElement.vue?vue&type=script&lang=ts\"\n\nimport \"./BaseTableElement.vue?vue&type=style&index=0&id=dea016ac&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dea016ac\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\n\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\nimport BaseChartElement from '@/views/components/element/ChartElement/BaseChartElement.vue'\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\n\nexport default defineComponent({\n name: 'base-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n const theme = computed(() => store.state.theme)\n\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: BaseImageElement,\n [ElementTypes.TEXT]: BaseTextElement,\n [ElementTypes.SHAPE]: BaseShapeElement,\n [ElementTypes.LINE]: BaseLineElement,\n [ElementTypes.CHART]: BaseChartElement,\n [ElementTypes.TABLE]: BaseTableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n return {\n currentElementComponent,\n theme,\n }\n },\n})\n","import { render } from \"./ThumbnailElement.vue?vue&type=template&id=43292aca\"\nimport script from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ThumbnailElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nimport ThumbnailElement from './ThumbnailElement.vue'\n\nexport default defineComponent({\n name: 'thumbnail-slide',\n components: {\n ThumbnailElement,\n },\n props: {\n slide: {\n type: Object as PropType,\n required: true,\n },\n size: {\n type: Number,\n required: true,\n },\n },\n setup(props) {\n const background = computed(() => props.slide.background)\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n const scale = computed(() => props.size / VIEWPORT_SIZE)\n\n return {\n scale,\n backgroundStyle,\n VIEWPORT_SIZE,\n VIEWPORT_ASPECT_RATIO,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=1debfb1c&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=1debfb1c&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1debfb1c\"\n\nexport default script","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { fillDigit } from '@/utils/common'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport useSlideHandler from '@/hooks/useSlideHandler'\nimport useScreening from '@/hooks/useScreening'\n\nimport Draggable from 'vuedraggable'\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\n\nexport default defineComponent({\n name: 'thumbnails',\n components: {\n Draggable,\n ThumbnailSlide,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n\n const {\n copySlide,\n pasteSlide,\n createSlide,\n copyAndPasteSlide,\n deleteSlide,\n cutSlide,\n } = useSlideHandler()\n\n const changSlideIndex = (index: number) => {\n store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])\n\n if(slideIndex.value === index) return\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n }\n\n const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)\n\n const setThumbnailsFocus = (focus: boolean) => {\n if(thumbnailsFocus.value === focus) return\n store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, focus)\n }\n\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\n const { newIndex, oldIndex } = eventData\n if(oldIndex === newIndex) return\n\n const _slides = JSON.parse(JSON.stringify(slides.value))\n const _slide = _slides[oldIndex]\n _slides.splice(oldIndex, 1)\n _slides.splice(newIndex, 0, _slide)\n store.commit(MutationTypes.SET_SLIDES, _slides)\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)\n }\n\n const { enterScreening } = useScreening()\n\n const contextmenusThumbnails = (): ContextmenuItem[] => {\n return [\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteSlide,\n },\n {\n text: '新建页面',\n subText: 'Enter',\n handler: createSlide,\n },\n ]\n }\n\n const contextmenusThumbnailItem = (): ContextmenuItem[] => {\n return [\n {\n text: '剪切',\n subText: 'Ctrl + X',\n handler: cutSlide,\n },\n {\n text: '复制',\n subText: 'Ctrl + C',\n handler: copySlide,\n },\n {\n text: '粘贴',\n subText: 'Ctrl + V',\n handler: pasteSlide,\n },\n { divider: true },\n {\n text: '新建页面',\n subText: 'Enter',\n handler: createSlide,\n },\n {\n text: '复制页面',\n handler: copyAndPasteSlide,\n },\n {\n text: '删除页面',\n subText: 'Delete',\n handler: deleteSlide,\n },\n { divider: true },\n {\n text: '从本页演示',\n subText: 'Ctrl+F',\n handler: enterScreening,\n },\n ]\n }\n\n return {\n setThumbnailsFocus,\n slides,\n slideIndex,\n createSlide,\n changSlideIndex,\n contextmenusThumbnails,\n contextmenusThumbnailItem,\n fillDigit,\n handleDragEnd,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=6821a1b4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=6821a1b4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6821a1b4\"\n\nexport default script","\n\n\n\n","export type ToolbarState = 'elAnimation' | 'elStyle' | 'elPosition' | 'slideStyle' | 'slideAnimation' | 'multiPosition'\n\nexport const ToolbarStates = {\n EL_ANIMATION: 'elAnimation',\n EL_STYLE: 'elStyle',\n EL_POSITION: 'elPosition',\n SLIDE_STYLE: 'slideStyle',\n SLIDE_ANIMATION: 'slideAnimation',\n MULTI_POSITION: 'multiPosition',\n}","\n\n","\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'element-opacity',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const opacity = ref()\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n opacity.value = 'opacity' in handleElement.value && handleElement.value.opacity !== undefined ? handleElement.value.opacity : 1\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateOpacity = (value: number) => {\n const props = { opacity: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n opacity,\n updateOpacity,\n }\n },\n})\n","import { render } from \"./ElementOpacity.vue?vue&type=template&id=4b901be6&scoped=true\"\nimport script from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOpacity.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOpacity.vue?vue&type=style&index=0&id=4b901be6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-4b901be6\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\nexport default {\n name: 'color-button',\n props: {\n color: {\n type: String,\n required: true,\n },\n },\n}\n","import { render } from \"./ColorButton.vue?vue&type=template&id=39016b60&scoped=true\"\nimport script from \"./ColorButton.vue?vue&type=script&lang=ts\"\nexport * from \"./ColorButton.vue?vue&type=script&lang=ts\"\n\nimport \"./ColorButton.vue?vue&type=style&index=0&id=39016b60&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-39016b60\"\n\nexport default script","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTElementOutline } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './ColorButton.vue'\n\nexport default defineComponent({\n name: 'element-outline',\n components: {\n ColorButton,\n },\n props: {\n fixed: {\n type: Boolean,\n default: false,\n },\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const outline = ref()\n const hasOutline = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n outline.value = 'outline' in handleElement.value ? handleElement.value.outline : undefined\n hasOutline.value = !!outline.value\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateOutline = (outlineProps: Partial) => {\n const props = { outline: { ...outline.value, ...outlineProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleOutline = (checked: boolean) => {\n if(checked) {\n const props = { outline: { width: 2, color: '#000', style: 'solid' } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'outline' })\n }\n addHistorySnapshot()\n }\n\n return {\n outline,\n hasOutline,\n toggleOutline,\n updateOutline,\n }\n },\n})\n","import { render } from \"./ElementOutline.vue?vue&type=template&id=38e2f880&scoped=true\"\nimport script from \"./ElementOutline.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementOutline.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementOutline.vue?vue&type=style&index=0&id=38e2f880&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-38e2f880\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, PPTElementShadow } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './ColorButton.vue'\n\nexport default defineComponent({\n name: 'element-shadow',\n components: {\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const shadow = ref()\n const hasShadow = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n shadow.value = 'shadow' in handleElement.value ? handleElement.value.shadow : undefined\n hasShadow.value = !!shadow.value\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateShadow = (shadowProps: Partial) => {\n const props = { shadow: { ...shadow.value, ...shadowProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleShadow = (checked: boolean) => {\n if(checked) {\n const props = { shadow: { h: 1, v: 1, blur: 2, color: '#000' } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'shadow' })\n }\n addHistorySnapshot()\n }\n\n return {\n shadow,\n hasShadow,\n toggleShadow,\n updateShadow,\n }\n },\n})\n","import { render } from \"./ElementShadow.vue?vue&type=template&id=02448be4&scoped=true\"\nimport script from \"./ElementShadow.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementShadow.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementShadow.vue?vue&type=style&index=0&id=02448be4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-02448be4\"\n\nexport default script","\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTextElement } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { TextAttrs } from '@/prosemirror/utils'\nimport { WEB_FONTS } from '@/configs/font'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOpacity from '../common/ElementOpacity.vue'\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\n\nconst presetStyles = [\n {\n label: '大标题',\n style: {\n fontSize: '26px',\n fontWeight: 700,\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '48px' },\n { command: 'align', value: 'center' },\n { command: 'bold' },\n ],\n },\n {\n label: '小标题',\n style: {\n fontSize: '22px',\n fontWeight: 700,\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '36px' },\n { command: 'align', value: 'center' },\n { command: 'bold' },\n ],\n },\n {\n label: '正文',\n style: {\n fontSize: '20px',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '20px' },\n ],\n },\n {\n label: '正文[小]',\n style: {\n fontSize: '18px',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '18px' },\n ],\n },\n {\n label: '注释 1',\n style: {\n fontSize: '16px',\n fontStyle: 'italic',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '16px' },\n { command: 'em' },\n ],\n },\n {\n label: '注释 2',\n style: {\n fontSize: '16px',\n textDecoration: 'underline',\n },\n cmd: [\n { command: 'clear' },\n { command: 'fontsize', value: '16px' },\n { command: 'underline' },\n ],\n },\n]\n\nconst webFonts = WEB_FONTS\n\ninterface CommandPayload {\n command: string;\n value?: string;\n}\n\nexport default defineComponent({\n name: 'text-style-panel',\n components: {\n ElementOpacity,\n ElementOutline,\n ElementShadow,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const fill = ref()\n const lineHeight = ref()\n const wordSpace = ref()\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'text') return\n\n fill.value = handleElement.value.fill || '#000'\n lineHeight.value = handleElement.value.lineHeight || 1.5\n wordSpace.value = handleElement.value.wordSpace || 0\n }, { deep: true, immediate: true })\n\n const richTextAttrs = ref({\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n superscript: false,\n subscript: false,\n code: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n bulletList: false,\n orderedList: false,\n blockquote: false,\n })\n\n const availableFonts = computed(() => store.state.availableFonts)\n const fontSizeOptions = [\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\n '36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '80px',\n ]\n const lineHeightOptions = [0.5, 1.0, 1.2, 1.5, 1.8, 2.0, 3.0]\n const wordSpaceOptions = [0, 1, 2, 3, 4, 5, 8]\n\n const updateRichTextAttrs = (attr: TextAttrs) => richTextAttrs.value = attr\n\n emitter.on(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\n onUnmounted(() => {\n emitter.off(EmitterEvents.UPDATE_TEXT_STATE, attr => updateRichTextAttrs(attr))\n })\n\n const emitRichTextCommand = (command: string, value?: string) => {\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value })\n }\n\n const emitBatchRichTextCommand = (payload: CommandPayload[]) => {\n emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, payload)\n }\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLineHeight = (value: number) => {\n const props = { lineHeight: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateWordSpace = (value: number) => {\n const props = { wordSpace: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n fill,\n lineHeight,\n wordSpace,\n richTextAttrs,\n availableFonts,\n webFonts,\n fontSizeOptions,\n lineHeightOptions,\n wordSpaceOptions,\n updateLineHeight,\n updateWordSpace,\n updateFill,\n emitRichTextCommand,\n emitBatchRichTextCommand,\n presetStyles,\n }\n },\n})\n","import { render } from \"./TextStylePanel.vue?vue&type=template&id=382a7e56&scoped=true\"\nimport script from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TextStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TextStylePanel.vue?vue&type=style&index=0&id=382a7e56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-382a7e56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTImageElement, Slide } from '@/types/slides'\nimport { CLIPPATHS } from '@/configs/imageClip'\nimport { getImageDataURL } from '@/utils/image'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\n\ninterface FilterOption {\n label: string;\n key: string;\n default: number;\n value: number;\n unit: string;\n max: number;\n step: number;\n}\n\nconst defaultFilters: FilterOption[] = [\n { label: '模糊', key: 'blur', default: 0, value: 0, unit: 'px', max: 10, step: 1 },\n { label: '亮度', key: 'brightness', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '对比度', key: 'contrast', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '灰度', key: 'grayscale', default: 0, value: 0, unit: '%', max: 100, step: 5 },\n { label: '饱和度', key: 'saturate', default: 100, value: 100, unit: '%', max: 200, step: 5 },\n { label: '色相', key: 'hue-rotate', default: 0, value: 0, unit: 'deg', max: 360, step: 10 },\n { label: '不透明度', key: 'opacity', default: 100, value: 100, unit: '%', max: 100, step: 5 },\n]\n\nconst shapeClipPathOptions = CLIPPATHS\nconst ratioClipOptions = [\n {\n label: '纵横比(方形)',\n children: [\n { key: '1:1', ratio: 1 / 1 },\n ],\n },\n {\n label: '纵横比(纵向)',\n children: [\n { key: '2:3', ratio: 3 / 2 },\n { key: '3:4', ratio: 4 / 3 },\n { key: '3:5', ratio: 5 / 3 },\n { key: '4:5', ratio: 5 / 4 },\n ],\n },\n {\n label: '纵横比(横向)',\n children: [\n { key: '3:2', ratio: 2 / 3 },\n { key: '4:3', ratio: 3 / 4 },\n { key: '5:3', ratio: 3 / 5 },\n { key: '5:4', ratio: 4 / 5 },\n ],\n },\n {\n children: [\n { key: '16:9', ratio: 9 / 16 },\n { key: '16:10', ratio: 10 / 16 },\n ],\n },\n]\n\nexport default defineComponent({\n name: 'image-style-panel',\n components: {\n ElementOutline,\n ElementShadow,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const clipPanelVisible = ref(false)\n\n const flip = ref({\n x: 0,\n y: 0,\n })\n\n const filterOptions = ref(JSON.parse(JSON.stringify(defaultFilters)))\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'image') return\n\n if(handleElement.value.flip) {\n flip.value = {\n x: handleElement.value.flip.x || 0,\n y: handleElement.value.flip.y || 0,\n }\n }\n else flip.value = { x: 0, y: 0 }\n\n const filters = handleElement.value.filters\n if(filters) {\n filterOptions.value = defaultFilters.map(item => {\n if(filters[item.key] !== undefined) return { ...item, value: parseInt(filters[item.key]) }\n return item\n })\n }\n else filterOptions.value = JSON.parse(JSON.stringify(defaultFilters))\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateImage = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFilter = (filter: FilterOption, value: number) => {\n const originFilters = handleElement.value.filters || {}\n const filters = { ...originFilters, [filter.key]: `${value}${filter.unit}` }\n const props = { filters }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const clipImage = () => {\n store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, handleElement.value.id)\n clipPanelVisible.value = false\n }\n\n const getImageElementDataBeforeClip = () => {\n // 图片当前宽高位置、裁剪范围\n const imgWidth = handleElement.value.width\n const imgHeight = handleElement.value.height\n const imgLeft = handleElement.value.left\n const imgTop = handleElement.value.top\n const originClipRange = handleElement.value.clip ? handleElement.value.clip.range : [[0, 0], [100, 100]]\n\n // 图片原本未裁剪过时的宽高位置\n const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)\n const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)\n const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100)\n const originTop = imgTop - originHeight * (originClipRange[0][1] / 100)\n\n return {\n originClipRange,\n originWidth,\n originHeight,\n originLeft,\n originTop,\n }\n }\n\n const presetImageClip = (shape: string, ratio = 0) => {\n const {\n originClipRange,\n originWidth,\n originHeight,\n originLeft,\n originTop,\n } = getImageElementDataBeforeClip()\n \n // 设置形状和纵横比\n if(ratio) {\n const imageRatio = originHeight / originWidth\n\n const min = 0\n const max = 100\n let range\n\n if(imageRatio > ratio) {\n const distance = ((1 - ratio / imageRatio) / 2) * 100\n range = [[min, distance], [max, max - distance]]\n }\n else {\n const distance = ((1 - imageRatio / ratio) / 2) * 100\n range = [[distance, min], [max - distance, max]]\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n clip: { ...handleElement.value.clip, shape, range },\n left: originLeft + originWidth * (range[0][0] / 100),\n top: originTop + originHeight * (range[0][1] / 100),\n width: originWidth * (range[1][0] - range[0][0]) / 100,\n height: originHeight * (range[1][1] - range[0][1]) / 100,\n },\n })\n }\n // 仅设置形状(维持目前的裁剪范围)\n else {\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n clip: { ...handleElement.value.clip, shape, range: originClipRange }\n },\n })\n }\n clipImage()\n addHistorySnapshot()\n }\n\n const replaceImage = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => {\n const props = { src: dataURL }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n })\n addHistorySnapshot()\n }\n\n const resetImage = () => {\n if(handleElement.value.clip) {\n const {\n originWidth,\n originHeight,\n originLeft,\n originTop,\n } = getImageElementDataBeforeClip()\n\n store.commit(MutationTypes.UPDATE_ELEMENT, {\n id: handleElement.value.id,\n props: {\n left: originLeft,\n top: originTop,\n width: originWidth,\n height: originHeight,\n },\n })\n }\n\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\n id: handleElement.value.id,\n propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],\n })\n addHistorySnapshot()\n }\n\n const setBackgroundImage = () => {\n const background = {\n ...currentSlide.value.background,\n type: 'image',\n image: handleElement.value.src,\n imageSize: 'cover',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background })\n addHistorySnapshot()\n }\n\n return {\n clipPanelVisible,\n shapeClipPathOptions,\n ratioClipOptions,\n filterOptions,\n flip,\n handleElement,\n updateImage,\n updateFilter,\n clipImage,\n presetImageClip,\n replaceImage,\n resetImage,\n setBackgroundImage,\n }\n },\n})\n","import { render } from \"./ImageStylePanel.vue?vue&type=template&id=af9fc43e&scoped=true\"\nimport script from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ImageStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ImageStylePanel.vue?vue&type=style&index=0&id=af9fc43e&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-af9fc43e\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTShapeElement, ShapeGradient } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOpacity from '../common/ElementOpacity.vue'\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ElementShadow from '../common/ElementShadow.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'shape-style-panel',\n components: {\n ElementOpacity,\n ElementOutline,\n ElementShadow,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const fill = ref()\n const gradient = ref()\n const fillType = ref('fill')\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'shape') return\n fill.value = handleElement.value.fill || '#000'\n\n gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }\n\n fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'\n }, { deep: true, immediate: true })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateFillType = (type: 'gradient' | 'fill') => {\n if(type === 'fill') {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {\n id: handleElement.value.id,\n propName: 'gradient',\n })\n }\n else {\n const props = { gradient: gradient.value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n addHistorySnapshot()\n }\n\n const updateGradient = (gradientProps: Partial) => {\n const props = { gradient: { ...gradient.value, ...gradientProps } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n fill,\n gradient,\n fillType,\n updateFillType,\n updateFill,\n updateGradient,\n }\n },\n})\n","import { render } from \"./ShapeStylePanel.vue?vue&type=template&id=d415c6bc&scoped=true\"\nimport script from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ShapeStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ShapeStylePanel.vue?vue&type=style&index=0&id=d415c6bc&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d415c6bc\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTLineElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementShadow from '../common/ElementShadow.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'line-style-panel',\n components: {\n ElementShadow,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLine = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n updateLine,\n }\n }\n})\n","import { render } from \"./LineStylePanel.vue?vue&type=template&id=65b24fb3&scoped=true\"\nimport script from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./LineStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./LineStylePanel.vue?vue&type=style&index=0&id=65b24fb3&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-65b24fb3\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\nimport { ChartData } from '@/types/slides'\nimport { computed, defineComponent, onMounted, PropType, ref } from 'vue'\n\nconst CELL_WIDTH = 100\nconst CELL_HEIGHT = 32\n\nexport default defineComponent({\n name: 'chart-data-editor',\n props: {\n data: {\n type: Object as PropType,\n required: true,\n }\n },\n setup(props, { emit }) {\n const selectedRange = ref([0, 0])\n const tempRangeSize = ref({ width: 0, height: 0 })\n\n const rangeLines = computed(() => {\n const width = selectedRange.value[0] * CELL_WIDTH\n const height = selectedRange.value[1] * CELL_HEIGHT\n return [\n { type: 't', style: {width: width + 'px'} },\n { type: 'b', style: {top: height + 'px', width: width + 'px'} },\n { type: 'l', style: {height: height + 'px'} },\n { type: 'r', style: {left: width + 'px', height: height + 'px'} },\n ]\n })\n\n const resizablePointStyle = computed(() => {\n const width = selectedRange.value[0] * CELL_WIDTH\n const height = selectedRange.value[1] * CELL_HEIGHT\n return { left: width + 'px', top: height + 'px' }\n })\n\n const initData = () => {\n const _data: string[][] = []\n\n const { labels, series } = props.data\n const rowCount = labels.length\n const colCount = series.length\n\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row = [labels[rowIndex]]\n for(let colIndex = 0; colIndex < colCount; colIndex++) {\n row.push(series[colIndex][rowIndex] + '')\n }\n _data.push(row)\n }\n\n for(let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n for(let colIndex = 0; colIndex < colCount + 1; colIndex++) {\n const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\n if(!inputRef) continue\n inputRef.value = _data[rowIndex][colIndex] + ''\n }\n }\n\n selectedRange.value = [colCount + 1, rowCount]\n }\n\n onMounted(initData)\n\n const getTableData = () => {\n const [col, row] = selectedRange.value\n\n const labels: string[] = []\n const series: number[][] = []\n\n for(let rowIndex = 0; rowIndex < row; rowIndex++) {\n let labelsItem = `类别${rowIndex + 1}`\n const labelInputRef = document.querySelector(`#cell-${rowIndex}-0`) as HTMLInputElement\n if(labelInputRef && labelInputRef.value) labelsItem = labelInputRef.value\n labels.push(labelsItem)\n }\n\n for(let colIndex = 1; colIndex < col; colIndex++) {\n const seriesItem = []\n for(let rowIndex = 0; rowIndex < row; rowIndex++) {\n const valueInputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement\n let value = 0\n if(valueInputRef && valueInputRef.value && !!(+valueInputRef.value)) {\n value = +valueInputRef.value\n }\n seriesItem.push(value)\n }\n series.push(seriesItem)\n }\n const data = { labels, series }\n emit('save', data)\n }\n\n const closeEditor = () => emit('close')\n\n const changeSelectRange = (e: MouseEvent) => {\n let isMouseDown = true\n\n const startPageX = e.pageX\n const startPageY = e.pageY\n\n const originWidth = selectedRange.value[0] * CELL_WIDTH\n const originHeight = selectedRange.value[1] * CELL_HEIGHT\n\n document.onmousemove = e => {\n if(!isMouseDown) return\n\n const currentPageX = e.pageX\n const currentPageY = e.pageY\n\n const x = currentPageX - startPageX\n const y = currentPageY - startPageY\n\n const width = originWidth + x\n const height = originHeight + y\n\n tempRangeSize.value = { width, height }\n }\n\n document.onmouseup = e => {\n isMouseDown = false\n document.onmousemove = null\n document.onmouseup = null\n\n const endPageX = e.pageX\n const endPageY = e.pageY\n\n if(startPageX === endPageX && startPageY === endPageY) return\n\n let width = tempRangeSize.value.width\n let height = tempRangeSize.value.height\n if(width % CELL_WIDTH > CELL_WIDTH * 0.5) width = width + (CELL_WIDTH - width % CELL_WIDTH)\n if(height % CELL_HEIGHT > CELL_HEIGHT * 0.5) height = height + (CELL_HEIGHT - height % CELL_HEIGHT)\n\n let row = Math.round(height / CELL_HEIGHT)\n let col = Math.round(width / CELL_WIDTH)\n\n if(row < 3) row = 3\n if(col < 2) col = 2\n\n selectedRange.value = [col, row]\n tempRangeSize.value = { width: 0, height: 0 }\n }\n }\n\n return {\n tempRangeSize,\n rangeLines,\n resizablePointStyle,\n changeSelectRange,\n selectedRange,\n getTableData,\n closeEditor,\n }\n },\n})\n","import { render } from \"./ChartDataEditor.vue?vue&type=template&id=73892bc6&scoped=true\"\nimport script from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\nexport * from \"./ChartDataEditor.vue?vue&type=script&lang=ts\"\n\nimport \"./ChartDataEditor.vue?vue&type=style&index=0&id=73892bc6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-73892bc6\"\n\nexport default script","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'\nimport { MutationTypes, useStore } from '@/store'\nimport { ChartData, PPTChartElement } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ElementOutline from '../../common/ElementOutline.vue'\nimport ColorButton from '../../common/ColorButton.vue'\nimport ChartDataEditor from './ChartDataEditor.vue'\n\nexport default defineComponent({\n name: 'chart-style-panel',\n components: {\n ElementOutline,\n ChartDataEditor,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const chartDataEditorVisible = ref(false)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const fill = ref()\n\n const themeColor = ref('')\n const gridColor = ref('')\n\n const lineSmooth = ref(true)\n const showLine = ref(true)\n const showArea = ref(false)\n const horizontalBars = ref(false)\n const donut = ref(false)\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'chart') return\n fill.value = handleElement.value.fill || '#000'\n\n if(handleElement.value.options) {\n const {\n lineSmooth: _lineSmooth,\n showLine: _showLine,\n showArea: _showArea,\n horizontalBars: _horizontalBars,\n donut: _donut,\n } = handleElement.value.options\n\n if(_lineSmooth !== undefined) lineSmooth.value = _lineSmooth\n if(_showLine !== undefined) showLine.value = _showLine\n if(_showArea !== undefined) showArea.value = _showArea\n if(_horizontalBars !== undefined) horizontalBars.value = _horizontalBars\n if(_donut !== undefined) donut.value = _donut\n }\n\n themeColor.value = handleElement.value.themeColor\n gridColor.value = handleElement.value.gridColor || 'rgba(0, 0, 0, 0.4)'\n }, { deep: true, immediate: true })\n\n const updateData = (data: ChartData) => {\n chartDataEditorVisible.value = false\n const props = { data }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateFill = (value: string) => {\n const props = { fill: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => {\n const options = handleElement.value.options || {}\n const newOptions = { ...options, ...optionProps }\n const props = { options: newOptions }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateTheme = (themeColor: string) => {\n const props = { themeColor }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const updateGridColor = (gridColor: string) => {\n const props = { gridColor }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n chartDataEditorVisible,\n handleElement,\n updateData,\n fill,\n updateFill,\n lineSmooth,\n showLine,\n showArea,\n horizontalBars,\n donut,\n updateOptions,\n themeColor,\n gridColor,\n updateTheme,\n updateGridColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=0bd1ca02&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0bd1ca02&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0bd1ca02\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, ref, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTTableElement, TableCell, TableCellStyle, TableTheme } from '@/types/slides'\nimport emitter, { EmitterEvents } from '@/utils/emitter'\nimport { createRandomCode } from '@/utils/common'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport { message } from 'ant-design-vue'\n\nimport ElementOutline from '../common/ElementOutline.vue'\nimport ColorButton from '../common/ColorButton.vue'\n\nexport default defineComponent({\n name: 'table-style-panel',\n components: {\n ElementOutline,\n ColorButton,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const textAttrs = ref({\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n })\n\n const theme = ref()\n const hasTheme = ref(false)\n const rowCount = ref(0)\n const colCount = ref(0)\n const minRowCount = ref(0)\n const minColCount = ref(0)\n\n watch(handleElement, () => {\n if(!handleElement.value || handleElement.value.type !== 'table') return\n \n theme.value = handleElement.value.theme\n hasTheme.value = !!theme.value\n\n rowCount.value = handleElement.value.data.length\n colCount.value = handleElement.value.data[0].length\n\n minRowCount.value = handleElement.value.data.length\n minColCount.value = handleElement.value.data[0].length\n }, { deep: true, immediate: true })\n\n const selectedCells = ref([])\n\n const updateTextAttrState = () => {\n if(!handleElement.value) return\n\n let rowIndex = 0\n let colIndex = 0\n if(selectedCells.value.length) {\n const selectedCell = selectedCells.value[0]\n rowIndex = +selectedCell.split('_')[0]\n colIndex = +selectedCell.split('_')[1]\n }\n const style = handleElement.value.data[rowIndex][colIndex].style\n\n if(!style) {\n textAttrs.value = {\n bold: false,\n em: false,\n underline: false,\n strikethrough: false,\n color: '#000',\n backcolor: '#000',\n fontsize: '12px',\n fontname: '微软雅黑',\n align: 'left',\n }\n }\n else {\n textAttrs.value = {\n bold: !!style.bold,\n em: !!style.em,\n underline: !!style.underline,\n strikethrough: !!style.strikethrough,\n color: style.color || '#000',\n backcolor: style.backcolor || '#000',\n fontsize: style.fontsize || '12px',\n fontname: style.fontname || '微软雅黑',\n align: style.align || 'left',\n }\n }\n }\n\n const updateSelectedCells = (cells: string[]) => {\n selectedCells.value = cells\n updateTextAttrState()\n }\n\n emitter.on(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\n onUnmounted(() => {\n emitter.off(EmitterEvents.UPDATE_TABLE_SELECTED_CELL, cells => updateSelectedCells(cells))\n })\n\n const availableFonts = computed(() => store.state.availableFonts)\n const fontSizeOptions = [\n '12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',\n ]\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateTextAttrs = (textAttrProp: Partial) => {\n const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\n\n for(let i = 0; i < data.length; i++) {\n for(let j = 0; j < data[i].length; j++) {\n if(!selectedCells.value.length || selectedCells.value.includes(`${i}_${j}`)) {\n const style = data[i][j].style || {}\n data[i][j].style = { ...style, ...textAttrProp }\n }\n }\n }\n const props = { data }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n\n addHistorySnapshot()\n updateTextAttrState()\n }\n\n const updateTheme = (themeProp: Partial) => {\n const currentTheme = theme.value || {}\n const props = { theme: { ...currentTheme, ...themeProp } }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const toggleTheme = (checked: boolean) => {\n if(checked) {\n const props = {\n theme: {\n color: '#d14424',\n rowHeader: true,\n rowFooter: false,\n colHeader: false,\n colFooter: false,\n }\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n }\n else {\n store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'theme' })\n }\n addHistorySnapshot()\n }\n\n const setTableRow = (e: KeyboardEvent) => {\n const value = +(e.target as HTMLInputElement).value\n const rowCount = handleElement.value.data.length\n\n if(value === rowCount) return\n if(value < rowCount) return message.warning('设置行数不能少于当前值')\n\n const rowCells: TableCell[] = new Array(colCount.value).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n const newTableCells: TableCell[][] = new Array(value - rowCount).fill(rowCells)\n\n const tableCells: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))\n tableCells.push(...newTableCells)\n\n const props = { data: tableCells }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n const setTableCol = (e: KeyboardEvent) => {\n const value = +(e.target as HTMLInputElement).value\n const colCount = handleElement.value.data[0].length\n\n if(value === colCount) return\n if(value < colCount) return message.warning('设置列数不能少于当前值')\n\n const tableCells = handleElement.value.data.map(item => {\n const cells: TableCell[] = new Array(value - colCount).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })\n item.push(...cells)\n return item\n })\n\n const colSizeList = handleElement.value.colWidths.map(item => item * handleElement.value.width)\n const newColSizeList = new Array(value - colCount).fill(100)\n colSizeList.push(...newColSizeList)\n\n const width = handleElement.value.width + 100 * (value - colCount)\n const colWidths = colSizeList.map(item => item / width)\n\n const props = {\n width,\n data: tableCells,\n colWidths,\n }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n availableFonts,\n fontSizeOptions,\n textAttrs,\n updateTextAttrs,\n theme,\n rowCount,\n colCount,\n minRowCount,\n minColCount,\n hasTheme,\n toggleTheme,\n updateTheme,\n setTableRow,\n setTableCol,\n }\n },\n})\n","import { render } from \"./TableStylePanel.vue?vue&type=template&id=63aedd01&scoped=true\"\nimport script from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./TableStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./TableStylePanel.vue?vue&type=style&index=0&id=63aedd01&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-63aedd01\"\n\nexport default script","\nimport { computed, defineComponent } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement } from '@/types/slides'\n\nimport TextStylePanel from './TextStylePanel.vue'\nimport ImageStylePanel from './ImageStylePanel.vue'\nimport ShapeStylePanel from './ShapeStylePanel.vue'\nimport LineStylePanel from './LineStylePanel.vue'\nimport ChartStylePanel from './ChartStylePanel/index.vue'\nimport TableStylePanel from './TableStylePanel.vue'\n\nexport default defineComponent({\n name: 'element-style-panel',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const currentPanelComponent = computed(() => {\n if(!handleElement.value) return null\n \n const panelMap = {\n [ElementTypes.TEXT]: TextStylePanel,\n [ElementTypes.IMAGE]: ImageStylePanel,\n [ElementTypes.SHAPE]: ShapeStylePanel,\n [ElementTypes.LINE]: LineStylePanel,\n [ElementTypes.CHART]: ChartStylePanel,\n [ElementTypes.TABLE]: TableStylePanel,\n }\n return panelMap[handleElement.value.type] || null\n })\n\n return {\n handleElement,\n currentPanelComponent,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=459125fc\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport round from 'lodash/round'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement } from '@/types/slides'\nimport { MIN_SIZE } from '@/configs/element'\nimport useOrderElement from '@/hooks/useOrderElement'\nimport useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'element-positopn-panel',\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n\n const left = ref(0)\n const top = ref(0)\n const width = ref(0)\n const height = ref(0)\n const rotate = ref(0)\n const fixedRatio = ref(false)\n\n const minSize = computed(() => {\n if(!handleElement.value) return 20\n return MIN_SIZE[handleElement.value.type] || 20\n })\n\n watch(handleElement, () => {\n if(!handleElement.value) return\n\n left.value = round(handleElement.value.left, 1)\n top.value = round(handleElement.value.top, 1)\n\n fixedRatio.value = 'fixedRatio' in handleElement.value && !!handleElement.value.fixedRatio\n\n if(handleElement.value.type !== 'line') {\n width.value = round(handleElement.value.width, 1)\n height.value = round(handleElement.value.height, 1)\n rotate.value = 'rotate' in handleElement.value && handleElement.value.rotate !== undefined ? round(handleElement.value.rotate, 1) : 0\n }\n }, { deep: true, immediate: true })\n\n const { orderElement } = useOrderElement()\n const { alignElementToCanvas } = useAlignElementToCanvas()\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateLeft = (value: number) => {\n const props = { left: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateTop = (value: number) => {\n const props = { top: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateWidth = (value: number) => {\n const props = { width: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateHeight = (value: number) => {\n const props = { height: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateRotate = (value: number) => {\n const props = { rotate: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateFixedRatio = (value: boolean) => {\n const props = { fixedRatio: value }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n const updateRotate45 = (command: '+' | '-') => {\n let _rotate = Math.floor(rotate.value / 45) * 45\n if(command === '+') _rotate = _rotate + 45\n else if(command === '-') _rotate = _rotate - 45\n\n if(_rotate < -180) _rotate = -180\n if(_rotate > 180) _rotate = 180\n\n const props = { rotate: _rotate }\n store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })\n addHistorySnapshot()\n }\n\n return {\n handleElement,\n orderElement,\n alignElementToCanvas,\n left,\n top,\n width,\n height,\n rotate,\n fixedRatio,\n minSize,\n updateLeft,\n updateTop,\n updateWidth,\n updateHeight,\n updateRotate,\n updateFixedRatio,\n updateRotate45,\n }\n },\n})\n","import { render } from \"./ElementPositionPanel.vue?vue&type=template&id=1a79147f&scoped=true\"\nimport script from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementPositionPanel.vue?vue&type=style&index=0&id=1a79147f&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1a79147f\"\n\nexport default script","\n\n\n\n","export const ANIMATIONS = [\r\n {\r\n type: 'bounce',\r\n name: '弹跳',\r\n children: [\r\n { name: '弹入', value: 'bounceIn' },\r\n { name: '向右弹入', value: 'bounceInLeft' },\r\n { name: '向左弹入', value: 'bounceInRight' },\r\n { name: '向上弹入', value: 'bounceInUp' },\r\n { name: '向下弹入', value: 'bounceInDown' },\r\n ],\r\n },\r\n {\r\n type: 'fade',\r\n name: '浮现',\r\n children: [\r\n { name: '浮入', value: 'fadeIn' },\r\n { name: '向下浮入', value: 'fadeInDown' },\r\n { name: '向下长距浮入', value: 'fadeInDownBig' },\r\n { name: '向右浮入', value: 'fadeInLeft' },\r\n { name: '向右长距浮入', value: 'fadeInLeftBig' },\r\n { name: '向左浮入', value: 'fadeInRight' },\r\n { name: '向左长距浮入', value: 'fadeInRightBig' },\r\n { name: '向上浮入', value: 'fadeInUp' },\r\n { name: '向上长距浮入', value: 'fadeInUpBig' },\r\n { name: '从左上浮入', value: 'fadeInTopLeft' },\r\n { name: '从右上浮入', value: 'fadeInTopRight' },\r\n { name: '从左下浮入', value: 'fadeInBottomLeft' },\r\n { name: '从右下浮入', value: 'fadeInBottomRight' },\r\n ],\r\n },\r\n {\r\n type: 'rotate',\r\n name: '旋转',\r\n children: [\r\n { name: '旋转进入', value: 'rotateIn' },\r\n { name: '绕左下旋转进入', value: 'rotateInDownLeft' },\r\n { name: '绕右下旋转进入', value: 'rotateInDownRight' },\r\n { name: '绕左上旋转进入', value: 'rotateInUpLeft' },\r\n { name: '绕右上旋转进入', value: 'rotateInUpRight' },\r\n ],\r\n },\r\n {\r\n type: 'zoom',\r\n name: '缩放',\r\n children: [\r\n { name: '放大进入', value: 'zoomIn' },\r\n { name: '向下放大进入', value: 'zoomInDown' },\r\n { name: '从左放大进入', value: 'zoomInLeft' },\r\n { name: '从右放大进入', value: 'zoomInRight' },\r\n { name: '向上放大进入', value: 'zoomInUp' },\r\n ],\r\n },\r\n {\r\n type: 'slide',\r\n name: '滑入',\r\n children: [\r\n { name: '向下滑入', value: 'slideInDown' },\r\n { name: '从右滑入', value: 'slideInLeft' },\r\n { name: '从左滑入', value: 'slideInRight' },\r\n { name: '向上滑入', value: 'slideInUp' },\r\n ],\r\n },\r\n {\r\n type: 'flip',\r\n name: '翻转',\r\n children: [\r\n { name: 'X轴翻转进入', value: 'flipInX' },\r\n { name: 'Y轴翻转进入', value: 'flipInY' },\r\n ],\r\n },\r\n {\r\n type: 'back',\r\n name: '放大滑入',\r\n children: [\r\n { name: '向下放大滑入', value: 'backInDown' },\r\n { name: '从左放大滑入', value: 'backInLeft' },\r\n { name: '从右放大滑入', value: 'backInRight' },\r\n { name: '向上放大滑入', value: 'backInUp' },\r\n ],\r\n },\r\n {\r\n type: 'lightSpeed',\r\n name: '飞入',\r\n children: [\r\n { name: '从右飞入', value: 'lightSpeedInRight' },\r\n { name: '从左飞入', value: 'lightSpeedInLeft' },\r\n ],\r\n },\r\n]","\nimport { computed, defineComponent, ref } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTAnimation, PPTElement, Slide } from '@/types/slides'\nimport { ANIMATIONS } from '@/configs/animation'\nimport { ELEMENT_TYPE_ZH } from '@/configs/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport Draggable from 'vuedraggable'\n\nconst animationTypes: { [key: string]: string } = {}\nfor(const type of ANIMATIONS) {\n for(const animation of type.children) {\n animationTypes[animation.value] = animation.name\n }\n}\n\nexport default defineComponent({\n name: 'element-animation-panel',\n components: {\n Draggable,\n },\n setup() {\n const store = useStore()\n const handleElement = computed(() => store.getters.handleElement)\n const currentSlideAnimations = computed(() => store.getters.currentSlideAnimations)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const hoverPreviewAnimation = ref('')\n const animationPoolVisible = ref(false)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const animations = ANIMATIONS\n\n const animationSequence = computed(() => {\n if(!currentSlideAnimations.value) return []\n const animationSequence = []\n for(const animation of currentSlideAnimations.value) {\n const el = currentSlide.value.elements.find(el => el.id === animation.elId)\n if(!el) continue\n const elType = ELEMENT_TYPE_ZH[el.type]\n const animationType = animationTypes[animation.type]\n\n animationSequence.push({\n ...animation,\n elType,\n animationType,\n })\n }\n return animationSequence\n })\n\n const handleElementAnimation = computed(() => {\n if(!handleElement.value) return null\n const animations = currentSlideAnimations.value || []\n const animation = animations.find(item => item.elId === handleElement.value.id)\n if(!animation) return null\n return animationTypes[animation.type]\n })\n\n const updateElementAnimation = (type: string) => {\n const animations = (currentSlideAnimations.value as PPTAnimation[]).map(item => {\n if(item.elId === handleElement.value.id) return { ...item, type }\n return item\n })\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n animationPoolVisible.value = false\n addHistorySnapshot()\n }\n\n const addAnimation = (type: string) => {\n if(handleElementAnimation.value) {\n updateElementAnimation(type)\n return\n }\n const animations: PPTAnimation[] = currentSlideAnimations.value ? JSON.parse(JSON.stringify(currentSlideAnimations.value)) : []\n animations.push({\n elId: handleElement.value.id,\n type,\n duration: 1000,\n })\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n animationPoolVisible.value = false\n addHistorySnapshot()\n }\n\n const deleteAnimation = (elId: string) => {\n const animations = (currentSlideAnimations.value as PPTAnimation[]).filter(item => item.elId !== elId)\n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n addHistorySnapshot()\n }\n\n const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => {\n const { newIndex, oldIndex } = eventData\n if(oldIndex === newIndex) return\n\n const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value))\n const animation = animations[oldIndex]\n animations.splice(oldIndex, 1)\n animations.splice(newIndex, 0, animation)\n \n store.commit(MutationTypes.UPDATE_SLIDE, { animations })\n addHistorySnapshot()\n }\n\n const runAnimation = (elId: string, animationType: string) => {\n const prefix = 'animate__'\n const elRef = document.querySelector(`#editable-element-${elId} [class^=editable-element-]`)\n if(elRef) {\n const animationName = `${prefix}${animationType}`\n elRef.classList.add(`${prefix}animated`, animationName)\n\n const handleAnimationEnd = () => {\n elRef.classList.remove(`${prefix}animated`, animationName)\n }\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\n }\n }\n\n return {\n handleElement,\n animationPoolVisible,\n animations,\n animationSequence,\n hoverPreviewAnimation,\n handleElementAnimation,\n addAnimation,\n deleteAnimation,\n handleDragEnd,\n runAnimation,\n }\n },\n})\n","import { render } from \"./ElementAnimationPanel.vue?vue&type=template&id=3483fbf2&scoped=true\"\nimport script from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./ElementAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./ElementAnimationPanel.vue?vue&type=style&index=0&id=3483fbf2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3483fbf2\"\n\nexport default script","\n\n\n\n","export const PRESET_THEMES = [\r\n { color: '#d14424', background: '#ffffff', text: '#333' },\r\n { color: '#42464b', background: '#ffffff', text: '#333' },\r\n { color: '#5d82ba', background: '#ffffff', text: '#333' },\r\n { color: '#005a6f', background: '#ffffff', text: '#333' },\r\n { color: '#d0614c', background: '#dfb044', text: '#333' },\r\n { color: '#86a1ad', background: '#dfdbd4', text: '#333' },\r\n { color: '#697586', background: '#d5c4a4', text: '#333' },\r\n { color: '#333333', background: '#7acfa6', text: '#333' },\r\n { color: '#42464b', background: '#415065', text: '#fff' },\r\n { color: '#0c5999', background: '#35a2cd', text: '#fff' },\r\n { color: '#c49a41', background: '#8c4357', text: '#fff' },\r\n { color: '#dfaa00', background: '#2e4e7d', text: '#fff' },\r\n { color: '#d1ad88', background: '#f99070', text: '#fff' },\r\n { color: '#464d52', background: '#657984', text: '#fff' },\r\n { color: '#ffcfb6', background: '#1e4c6f', text: '#fff' },\r\n { color: '#c3a043', background: '#43292a', text: '#fff' },\r\n { color: '#ffffff', background: '#171925', text: '#fff' },\r\n { color: '#df9636', background: '#5b89a0', text: '#fff' },\r\n { color: '#b898a4', background: '#93716b', text: '#fff' },\r\n { color: '#c47a11', background: '#187db1', text: '#fff' },\r\n { color: '#333333', background: '#759564', text: '#fff' },\r\n { color: '#355b5e', background: '#424b50', text: '#fff' },\r\n { color: '#d29090', background: '#942a32', text: '#fff' },\r\n { color: '#00cfdf', background: '#3b434d', text: '#fff' },\r\n { color: '#424246', background: '#c70042', text: '#fff' },\r\n { color: '#2e4155', background: '#b35d44', text: '#fff' },\r\n { color: '#11bfce', background: '#8f98aa', text: '#fff' },\r\n { color: '#333333', background: '#549688', text: '#fff' },\r\n]","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide, SlideBackground, SlideTheme } from '@/types/slides'\nimport { PRESET_THEMES } from '@/configs/theme'\nimport { WEB_FONTS } from '@/configs/font'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nimport ColorButton from './common/ColorButton.vue'\nimport { getImageDataURL } from '@/utils/image'\n\nconst themes = PRESET_THEMES\nconst webFonts = WEB_FONTS\n\nexport default defineComponent({\n name: 'slide-style-panel',\n components: {\n ColorButton,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const theme = computed(() => store.state.theme)\n const currentSlide = computed(() => store.getters.currentSlide)\n const availableFonts = computed(() => store.state.availableFonts)\n\n const background = computed(() => {\n if(!currentSlide.value.background) {\n return {\n type: 'solid',\n value: '#fff',\n } as SlideBackground\n }\n return currentSlide.value.background\n })\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateBackgroundType = (type: 'solid' | 'image' | 'gradient') => {\n if(type === 'solid') {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'solid',\n color: background.value.color || '#fff',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n else if(type === 'image') {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'image',\n image: background.value.image || '',\n imageSize: background.value.imageSize || 'cover',\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n else {\n const newBackground: SlideBackground = {\n ...background.value,\n type: 'gradient',\n gradientType: background.value.gradientType || 'linear',\n gradientColor: background.value.gradientColor || ['#fff', '#fff'],\n gradientRotate: background.value.gradientRotate || 0,\n }\n store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })\n }\n addHistorySnapshot()\n }\n\n const updateBackground = (props: Partial) => {\n store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })\n addHistorySnapshot()\n }\n\n const uploadBackgroundImage = (files: File[]) => {\n const imageFile = files[0]\n if(!imageFile) return\n getImageDataURL(imageFile).then(dataURL => updateBackground({ image: dataURL }))\n }\n\n const applyBackgroundAllSlide = () => {\n const newSlides = slides.value.map(slide => {\n return {\n ...slide,\n background: currentSlide.value.background,\n }\n })\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n const updateTheme = (themeProps: Partial) => {\n store.commit(MutationTypes.SET_THEME, themeProps)\n }\n\n const applyThemeAllSlide = () => {\n const newSlides: Slide[] = JSON.parse(JSON.stringify(slides.value))\n const { themeColor, backgroundColor, fontColor } = theme.value\n\n for(const slide of newSlides) {\n if(!slide.background || slide.background.type !== 'image') {\n slide.background = {\n ...slide.background,\n type: 'solid',\n color: backgroundColor\n }\n }\n\n const elements = slide.elements\n for(const el of elements) {\n if(el.type === 'shape') el.fill = themeColor\n else if(el.type === 'line') el.color = themeColor\n else if(el.type === 'text') {\n if(el.fill) el.fill = themeColor\n }\n else if(el.type === 'table') {\n if(el.theme) el.theme.color = themeColor\n }\n else if(el.type === 'chart') {\n el.themeColor = themeColor\n el.gridColor = fontColor\n }\n }\n }\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n return {\n availableFonts,\n background,\n updateBackgroundType,\n updateBackground,\n uploadBackgroundImage,\n applyBackgroundAllSlide,\n themes,\n theme,\n webFonts,\n updateTheme,\n applyThemeAllSlide,\n }\n },\n})\n","import { render } from \"./SlideStylePanel.vue?vue&type=template&id=52253a56&scoped=true\"\nimport script from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideStylePanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideStylePanel.vue?vue&type=style&index=0&id=52253a56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-52253a56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\n\nexport default defineComponent({\n name: 'slide-animation-panel',\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')\n\n const animations = [\n { label: '无', value: 'no' },\n { label: '淡入淡出', value: 'fade' },\n { label: '左右推移', value: 'slideX' },\n { label: '上下推移', value: 'slideY' },\n ]\n\n const { addHistorySnapshot } = useHistorySnapshot()\n\n const updateTurningMode = (mode: string) => {\n if(mode === currentTurningMode.value) return\n store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })\n addHistorySnapshot()\n }\n\n const applyAllSlide = () => {\n const newSlides = slides.value.map(slide => {\n return {\n ...slide,\n turningMode: currentSlide.value.turningMode,\n }\n })\n store.commit(MutationTypes.SET_SLIDES, newSlides)\n addHistorySnapshot()\n }\n\n return {\n currentTurningMode,\n animations,\n updateTurningMode,\n applyAllSlide,\n }\n },\n})\n","import { render } from \"./SlideAnimationPanel.vue?vue&type=template&id=a3bc22da&scoped=true\"\nimport script from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideAnimationPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideAnimationPanel.vue?vue&type=style&index=0&id=a3bc22da&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-a3bc22da\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { PPTElement, Slide } from '@/types/slides'\nimport { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'\nimport { getElementListRange } from '@/utils/element'\nimport useHistorySnapshot from '@/hooks/useHistorySnapshot'\nimport useCombineElement from '@/hooks/useCombineElement'\n\nexport default defineComponent({\n name: 'multi-position-panel',\n setup() {\n const store = useStore()\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const activeElementList = computed(() => store.getters.activeElementList)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const { addHistorySnapshot } = useHistorySnapshot()\n const { combineElements, uncombineElements } = useCombineElement()\n\n const canCombine = computed(() => {\n const firstGroupId = activeElementList.value[0].groupId\n if(!firstGroupId) return true\n\n const inSameGroup = activeElementList.value.every(el => (el.groupId && el.groupId) === firstGroupId)\n return !inSameGroup\n })\n\n const alignActiveElement = (command: ElementAlignCommand) => {\n const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)\n const elementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))\n\n // 获取每一个组合的宽高位置\n const groupElementRangeMap = {}\n for(const activeElement of activeElementList.value) {\n if(activeElement.groupId && !groupElementRangeMap[activeElement.groupId]) {\n const groupElements = activeElementList.value.filter(item => item.groupId === activeElement.groupId)\n groupElementRangeMap[activeElement.groupId] = getElementListRange(groupElements)\n }\n }\n\n if(command === ElementAlignCommands.LEFT) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) element.left = minX\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.minX - minX\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.RIGHT) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\n element.left = maxX - elWidth\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.maxX - maxX\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.TOP) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) element.top = minY\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.minY - minY\n element.top = element.top - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.BOTTOM) {\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\n element.top = maxY - elHeight\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const offset = range.maxY - maxY\n element.top = element.top - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.HORIZONTAL) {\n const horizontalCenter = (minX + maxX) / 2\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width\n element.left = horizontalCenter - elWidth / 2\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const center = (range.maxX + range.minX) / 2\n const offset = center - horizontalCenter\n element.left = element.left - offset\n }\n }\n })\n }\n else if(command === ElementAlignCommands.VERTICAL) {\n const verticalCenter = (minY + maxY) / 2\n elementList.forEach(element => {\n if(activeElementIdList.value.includes(element.id)) {\n if(!element.groupId) {\n const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height\n element.top = verticalCenter - elHeight / 2\n }\n else {\n const range = groupElementRangeMap[element.groupId]\n const center = (range.maxY + range.minY) / 2\n const offset = center - verticalCenter\n element.top = element.top - offset\n }\n }\n })\n }\n \n store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })\n addHistorySnapshot()\n }\n\n return {\n canCombine,\n combineElements,\n uncombineElements,\n alignActiveElement,\n }\n },\n})\n","import { render } from \"./MultiPositionPanel.vue?vue&type=template&id=1040b5b1&scoped=true\"\nimport script from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\nexport * from \"./MultiPositionPanel.vue?vue&type=script&lang=ts\"\n\nimport \"./MultiPositionPanel.vue?vue&type=style&index=0&id=1040b5b1&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1040b5b1\"\n\nexport default script","\nimport { computed, defineComponent, watch } from 'vue'\nimport { MutationTypes, useStore } from '@/store'\nimport { ToolbarState, ToolbarStates } from '@/types/toolbar'\n\nimport ElementStylePanel from './ElementStylePanel/index.vue'\nimport ElementPositionPanel from './ElementPositionPanel.vue'\nimport ElementAnimationPanel from './ElementAnimationPanel.vue'\nimport SlideStylePanel from './SlideStylePanel.vue'\nimport SlideAnimationPanel from './SlideAnimationPanel.vue'\nimport MultiPositionPanel from './MultiPositionPanel.vue'\n\nexport default defineComponent({\n name: 'toolbar',\n setup() {\n const store = useStore()\n const toolbarState = computed(() => store.state.toolbarState)\n\n const elementTabs = [\n { label: '样式', value: ToolbarStates.EL_STYLE },\n { label: '位置', value: ToolbarStates.EL_POSITION },\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\n ]\n const slideTabs = [\n { label: '页面样式', value: ToolbarStates.SLIDE_STYLE },\n { label: '切换', value: ToolbarStates.SLIDE_ANIMATION },\n { label: '动画', value: ToolbarStates.EL_ANIMATION },\n ]\n const multiSelectTabs = [\n { label: '位置', value: ToolbarStates.MULTI_POSITION },\n { label: '样式', value: ToolbarStates.EL_STYLE },\n ]\n\n const setToolbarState = (value: ToolbarState) => {\n store.commit(MutationTypes.SET_TOOLBAR_STATE, value)\n }\n\n const activeElementIdList = computed(() => store.state.activeElementIdList)\n const currentTabs = computed(() => {\n if(!activeElementIdList.value.length) return slideTabs\n else if(activeElementIdList.value.length > 1) return multiSelectTabs\n return elementTabs\n })\n\n watch(currentTabs, () => {\n const currentTabsValue = currentTabs.value.map(tab => tab.value)\n if(!currentTabsValue.includes(toolbarState.value)) {\n store.commit(MutationTypes.SET_TOOLBAR_STATE, currentTabsValue[0])\n }\n })\n\n const currentPanelComponent = computed(() => {\n const panelMap = {\n [ToolbarStates.EL_STYLE]: ElementStylePanel,\n [ToolbarStates.EL_POSITION]: ElementPositionPanel,\n [ToolbarStates.EL_ANIMATION]: ElementAnimationPanel,\n [ToolbarStates.SLIDE_STYLE]: SlideStylePanel,\n [ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,\n [ToolbarStates.MULTI_POSITION]: MultiPositionPanel,\n }\n return panelMap[toolbarState.value] || null\n })\n\n return {\n toolbarState,\n currentTabs,\n setToolbarState,\n currentPanelComponent,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=8468ba32&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=8468ba32&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-8468ba32\"\n\nexport default script","\nimport { defineComponent } from 'vue'\n\nimport useHotkey from './useHotkey'\nimport usePasteEvent from './usePasteEvent'\n\nimport EditorHeader from './EditorHeader/index.vue'\nimport Canvas from './Canvas/index.vue'\nimport CanvasTool from './CanvasTool/index.vue'\nimport Thumbnails from './Thumbnails/index.vue'\nimport Toolbar from './Toolbar/index.vue'\n\nexport default defineComponent({\n name: 'editor',\n components: {\n EditorHeader,\n Canvas,\n CanvasTool,\n Thumbnails,\n Toolbar,\n },\n setup() {\n useHotkey()\n usePasteEvent()\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=d5c6b448&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=d5c6b448&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-d5c6b448\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n","\n\n\n\n\n","\nimport { defineComponent, PropType } from 'vue'\nimport { PPTChartElement } from '@/types/slides'\n\nimport ElementOutline from '@/views/components/element/ElementOutline.vue'\nimport Chart from './Chart.vue'\n\nexport default defineComponent({\n name: 'screen-element-chart',\n components: {\n ElementOutline,\n Chart,\n },\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n },\n})\n","import { render } from \"./ScreenChartElement.vue?vue&type=template&id=1423f8c2&scoped=true\"\nimport script from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenChartElement.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenChartElement.vue?vue&type=style&index=0&id=1423f8c2&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-1423f8c2\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\nimport { ElementTypes, PPTElement, Slide } from '@/types/slides'\n\nimport BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'\nimport BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'\nimport BaseShapeElement from '@/views/components/element/ShapeElement/BaseShapeElement.vue'\nimport BaseLineElement from '@/views/components/element/LineElement/BaseLineElement.vue'\nimport ScreenChartElement from '@/views/components/element/ChartElement/ScreenChartElement.vue'\nimport BaseTableElement from '@/views/components/element/TableElement/BaseTableElement.vue'\n\nexport default defineComponent({\n name: 'screen-element',\n props: {\n elementInfo: {\n type: Object as PropType,\n required: true,\n },\n elementIndex: {\n type: Number,\n required: true,\n },\n animationIndex: {\n type: Number,\n default: -1,\n },\n },\n setup(props) {\n const currentElementComponent = computed(() => {\n const elementTypeMap = {\n [ElementTypes.IMAGE]: BaseImageElement,\n [ElementTypes.TEXT]: BaseTextElement,\n [ElementTypes.SHAPE]: BaseShapeElement,\n [ElementTypes.LINE]: BaseLineElement,\n [ElementTypes.CHART]: ScreenChartElement,\n [ElementTypes.TABLE]: BaseTableElement,\n }\n return elementTypeMap[props.elementInfo.type] || null\n })\n\n const store = useStore()\n const theme = computed(() => store.state.theme)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const needWaitAnimation = computed(() => {\n const animations = currentSlide.value.animations || []\n const elementIndexInAnimation = animations.findIndex(animation => animation.elId === props.elementInfo.id)\n if(elementIndexInAnimation !== -1 && elementIndexInAnimation >= props.animationIndex) return true\n return false \n })\n\n return {\n currentElementComponent,\n needWaitAnimation,\n theme,\n }\n },\n})\n","import { render } from \"./ScreenElement.vue?vue&type=template&id=68c19726\"\nimport script from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenElement.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\nimport { computed, PropType, defineComponent } from 'vue'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'\nimport useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'\n\nimport ScreenElement from './ScreenElement.vue'\n\nexport default defineComponent({\n name: 'screen-slide',\n components: {\n ScreenElement,\n },\n props: {\n slide: {\n type: Object as PropType,\n required: true,\n },\n scale: {\n type: Number,\n required: true,\n },\n animationIndex: {\n type: Number,\n default: -1,\n },\n },\n setup(props) {\n const background = computed(() => props.slide.background)\n const { backgroundStyle } = useSlideBackgroundStyle(background)\n\n return {\n backgroundStyle,\n VIEWPORT_SIZE,\n VIEWPORT_ASPECT_RATIO,\n }\n },\n})\n","import { render } from \"./ScreenSlide.vue?vue&type=template&id=5e193d56&scoped=true\"\nimport script from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\nexport * from \"./ScreenSlide.vue?vue&type=script&lang=ts\"\n\nimport \"./ScreenSlide.vue?vue&type=style&index=0&id=5e193d56&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5e193d56\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { useStore } from '@/store'\n\nimport ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'\n\nexport default defineComponent({\n name: 'slide-thumbnails',\n components: {\n ThumbnailSlide,\n },\n props: {\n turnSlideToIndex: {\n type: Function as PropType<(index: number) => void>,\n },\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n\n return {\n slides,\n slideIndex,\n }\n },\n})\n","import { render } from \"./SlideThumbnails.vue?vue&type=template&id=5b8ebe1d&scoped=true\"\nimport script from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\nexport * from \"./SlideThumbnails.vue?vue&type=script&lang=ts\"\n\nimport \"./SlideThumbnails.vue?vue&type=style&index=0&id=5b8ebe1d&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b8ebe1d\"\n\nexport default script","\n\n\n\n","\r\n\r\n\r\n\r\n","\r\nimport { defineComponent, onMounted, PropType, reactive, ref } from 'vue'\r\n\r\nconst penSize = 6\r\nconst rubberSize = 80\r\n\r\nexport default defineComponent({\r\n name: 'writing-board',\r\n props: {\r\n color: {\r\n type: String,\r\n default: '#ffcc00',\r\n },\r\n model: {\r\n type: String as PropType<'pen' | 'eraser'>,\r\n default: 'pen',\r\n },\r\n },\r\n setup(props) {\r\n let ctx: CanvasRenderingContext2D | null = null\r\n const writingBoardRef = ref()\r\n const canvasRef = ref()\r\n let lastPos = {\r\n x: 0,\r\n y: 0,\r\n }\r\n let isMouseDown = false\r\n let lastTime = 0\r\n let lastLineWidth = -1\r\n\r\n const mouse = reactive({\r\n x: 0,\r\n y: 0,\r\n })\r\n const mouseInCanvas = ref(false)\r\n\r\n const initCanvas = () => {\r\n if(!canvasRef.value || !writingBoardRef.value) return\r\n\r\n ctx = canvasRef.value.getContext('2d')\r\n if(!ctx) return\r\n\r\n canvasRef.value.width = writingBoardRef.value.clientWidth\r\n canvasRef.value.height = writingBoardRef.value.clientHeight\r\n\r\n canvasRef.value.style.width = writingBoardRef.value.clientWidth + 'px'\r\n canvasRef.value.style.height = writingBoardRef.value.clientHeight + 'px'\r\n\r\n ctx.lineCap = 'round'\r\n ctx.lineJoin = 'round'\r\n }\r\n\r\n const getDistance = (posX: number, posY: number) => {\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n return Math.sqrt((posX - lastPosX) * (posX - lastPosX) + (posY - lastPosY) * (posY - lastPosY))\r\n }\r\n\r\n const getLineWidth = (s: number, t: number) => {\r\n const maxV = 10\r\n const minV = 0.1\r\n const maxWidth = penSize\r\n const minWidth = 3\r\n const v = s / t\r\n let lineWidth\r\n\r\n if(v <= minV) lineWidth = maxWidth\r\n else if(v >= maxV) lineWidth = minWidth\r\n else lineWidth = maxWidth - v / maxV * maxWidth\r\n\r\n if(lastLineWidth === -1) return lineWidth\r\n return lineWidth * 1 / 3 + lastLineWidth * 2 / 3\r\n }\r\n\r\n // 画笔绘制方法\r\n const draw = (posX: number, posY: number, lineWidth: number) => {\r\n if(!ctx) return\r\n\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n ctx.lineWidth = lineWidth\r\n ctx.strokeStyle = props.color\r\n ctx.beginPath()\r\n ctx.moveTo(lastPosX, lastPosY)\r\n ctx.lineTo(posX, posY)\r\n ctx.stroke()\r\n ctx.closePath()\r\n }\r\n\r\n // 橡皮擦除方法\r\n const erase = (posX: number, posY: number) => {\r\n if(!ctx || !canvasRef.value) return\r\n const lastPosX = lastPos.x\r\n const lastPosY = lastPos.y\r\n\r\n const radius = rubberSize / 2\r\n\r\n const sinRadius = radius * Math.sin(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const cosRadius = radius * Math.cos(Math.atan((posY - lastPosY) / (posX - lastPosX)))\r\n const rectPoint1: [number, number] = [lastPosX + sinRadius, lastPosY - cosRadius]\r\n const rectPoint2: [number, number] = [lastPosX - sinRadius, lastPosY + cosRadius]\r\n const rectPoint3: [number, number] = [posX + sinRadius, posY - cosRadius]\r\n const rectPoint4: [number, number] = [posX - sinRadius, posY + cosRadius]\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.arc(posX, posY, radius, 0, Math.PI * 2)\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n\r\n ctx.save()\r\n ctx.beginPath()\r\n ctx.moveTo(...rectPoint1)\r\n ctx.lineTo(...rectPoint3)\r\n ctx.lineTo(...rectPoint4)\r\n ctx.lineTo(...rectPoint2)\r\n ctx.closePath()\r\n ctx.clip()\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n ctx.restore()\r\n }\r\n\r\n const startDraw = (posX: number, posY: number) => {\r\n lastPos = { x: posX, y: posY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n const startMove = (posX: number, posY: number) => {\r\n const time = new Date().getTime()\r\n\r\n // 画笔模式(这里通过绘制速度调节画笔的粗细)\r\n if(props.model === 'pen') {\r\n const s = getDistance(posX, posY)\r\n const t = time - lastTime\r\n const lineWidth = getLineWidth(s, t)\r\n \r\n draw(posX, posY, lineWidth)\r\n lastLineWidth = lineWidth\r\n }\r\n // 橡皮模式\r\n else erase(posX, posY)\r\n\r\n lastPos = { x: posX, y: posY }\r\n lastTime = new Date().getTime()\r\n }\r\n\r\n const handleMousedown = (e: MouseEvent) => {\r\n isMouseDown = true\r\n startDraw(e.offsetX, e.offsetY)\r\n }\r\n\r\n const updateMousePosition = (e: MouseEvent) => {\r\n mouse.x = e.pageX\r\n mouse.y = e.pageY\r\n }\r\n\r\n const handleMousemove = (e: MouseEvent) => {\r\n updateMousePosition(e)\r\n\r\n if(!isMouseDown) return\r\n startMove(e.offsetX, e.offsetY)\r\n }\r\n\r\n const handleMouseup = () => {\r\n if(!isMouseDown) return\r\n isMouseDown = false\r\n }\r\n\r\n // 清空画布\r\n const clearCanvas = () => {\r\n if(!ctx || !canvasRef.value) return\r\n ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)\r\n }\r\n\r\n onMounted(initCanvas)\r\n\r\n return {\r\n mouse,\r\n mouseInCanvas,\r\n penSize,\r\n rubberSize,\r\n writingBoardRef,\r\n canvasRef,\r\n handleMousedown,\r\n handleMousemove,\r\n handleMouseup,\r\n clearCanvas,\r\n }\r\n },\r\n})\r\n","import { render } from \"./WritingBoard.vue?vue&type=template&id=5b8a1ac6&scoped=true\"\nimport script from \"./WritingBoard.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoard.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoard.vue?vue&type=style&index=0&id=5b8a1ac6&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-5b8a1ac6\"\n\nexport default script","\nimport { defineComponent, ref } from 'vue'\nimport WritingBoard from '@/components/WritingBoard.vue'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\n\nconst writingBoardColors = ['#000000', '#ffffff', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\n\nexport default defineComponent({\n name: 'writing-board-tool',\n components: {\n WritingBoard,\n },\n setup(props, { emit }) {\n const writingBoardRef = ref()\n const writingBoardVisible = ref(false)\n const writingBoardColor = ref('#e2534d')\n const writingBoardModel = ref('pen')\n\n const changePen = () => {\n if(!writingBoardVisible.value) writingBoardVisible.value = true\n writingBoardModel.value = 'pen'\n emit('close')\n }\n\n const changeEraser = () => {\n writingBoardModel.value = 'eraser'\n emit('close')\n }\n\n const clearCanvas = () => {\n writingBoardRef.value.clearCanvas()\n emit('close')\n }\n\n const changeColor = (color: string) => {\n if(writingBoardModel.value !== 'pen') writingBoardModel.value = 'pen'\n writingBoardColor.value = color\n emit('close')\n }\n\n const closeWritingBoard = () => {\n writingBoardVisible.value = false\n emit('close')\n }\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '画笔',\n handler: changePen,\n disable: writingBoardModel.value === 'pen',\n },\n {\n text: '橡皮擦',\n handler: changeEraser,\n disable: writingBoardModel.value === 'eraser',\n },\n {\n text: '擦除所有墨迹',\n handler: clearCanvas,\n },\n {\n text: '退出画笔',\n handler: closeWritingBoard,\n },\n ]\n }\n\n return {\n writingBoardRef,\n writingBoardVisible,\n writingBoardColors,\n writingBoardColor,\n writingBoardModel,\n changePen,\n changeEraser,\n clearCanvas,\n changeColor,\n closeWritingBoard,\n contextmenus,\n }\n },\n})\n","import { render } from \"./WritingBoardTool.vue?vue&type=template&id=0ecab351&scoped=true\"\nimport script from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\nexport * from \"./WritingBoardTool.vue?vue&type=script&lang=ts\"\n\nimport \"./WritingBoardTool.vue?vue&type=style&index=0&id=0ecab351&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0ecab351\"\n\nexport default script","\nimport { computed, defineComponent, onMounted, onUnmounted, provide, ref } from 'vue'\nimport throttle from 'lodash/throttle'\nimport { MutationTypes, useStore } from '@/store'\nimport { Slide } from '@/types/slides'\nimport { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas'\nimport { KEYS } from '@/configs/hotkey'\nimport { ContextmenuItem } from '@/components/Contextmenu/types'\nimport { isFullscreen } from '@/utils/fullscreen'\nimport useScreening from '@/hooks/useScreening'\n\nimport ScreenSlide from './ScreenSlide.vue'\nimport SlideThumbnails from './SlideThumbnails.vue'\nimport WritingBoardTool from './WritingBoardTool.vue'\n\nexport default defineComponent({\n name: 'screen',\n components: {\n ScreenSlide,\n SlideThumbnails,\n WritingBoardTool,\n },\n setup() {\n const store = useStore()\n const slides = computed(() => store.state.slides)\n const slideIndex = computed(() => store.state.slideIndex)\n const currentSlide = computed(() => store.getters.currentSlide)\n\n const slideWidth = ref(0)\n const slideHeight = ref(0)\n\n const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)\n\n const slideThumbnailModelVisible = ref(false)\n\n const writingBoardToolVisible = ref(false)\n\n const setSlideContentSize = () => {\n const winWidth = document.body.clientWidth\n const winHeight = document.body.clientHeight\n let width, height\n\n if(winHeight / winWidth === VIEWPORT_ASPECT_RATIO) {\n width = winWidth\n height = winHeight\n }\n else if(winHeight / winWidth > VIEWPORT_ASPECT_RATIO) {\n width = winWidth\n height = winWidth * VIEWPORT_ASPECT_RATIO\n }\n else {\n width = winHeight / VIEWPORT_ASPECT_RATIO\n height = winHeight\n }\n slideWidth.value = width\n slideHeight.value = height\n }\n\n const { exitScreening } = useScreening()\n\n const windowResizeListener = () => {\n setSlideContentSize()\n if(!isFullscreen()) exitScreening()\n }\n\n const animationIndex = ref(0)\n const animations = computed(() => currentSlide.value.animations || [])\n\n const runAnimation = () => {\n const prefix = 'animate__'\n const animation = animations.value[animationIndex.value]\n animationIndex.value += 1\n\n const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`)\n if(elRef) {\n const animationName = `${prefix}${animation.type}`\n elRef.classList.add(`${prefix}animated`, animationName)\n\n const handleAnimationEnd = () => {\n elRef.classList.remove(`${prefix}animated`, animationName)\n }\n elRef.addEventListener('animationend', handleAnimationEnd, { once: true })\n }\n }\n\n const execPrev = () => {\n if(animations.value.length && animationIndex.value > 0) {\n animationIndex.value -= 1\n }\n else if(slideIndex.value > 0) {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\n const lastIndex = animations.value ? animations.value.length : 0\n animationIndex.value = lastIndex\n }\n }\n const execNext = () => {\n if(animations.value.length && animationIndex.value < animations.value.length) {\n runAnimation()\n }\n else if(slideIndex.value < slides.value.length - 1) {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\n animationIndex.value = 0\n }\n }\n\n const keydownListener = (e: KeyboardEvent) => {\n const key = e.key.toUpperCase()\n if(key === KEYS.UP || key === KEYS.LEFT) execPrev()\n else if(\n key === KEYS.DOWN || \n key === KEYS.RIGHT ||\n key === KEYS.SPACE || \n key === KEYS.ENTER\n ) execNext()\n }\n\n const mousewheelListener = throttle(function(e: WheelEvent) {\n if(e.deltaY < 0) execPrev()\n else if(e.deltaY > 0) execNext()\n }, 500, { leading: true, trailing: false })\n\n onMounted(() => {\n window.addEventListener('resize', windowResizeListener)\n document.addEventListener('keydown', keydownListener)\n })\n onUnmounted(() => {\n window.removeEventListener('resize', windowResizeListener)\n document.removeEventListener('keydown', keydownListener)\n })\n\n const turnPrevSlide = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)\n animationIndex.value = 0\n }\n const turnNextSlide = () => {\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)\n animationIndex.value = 0\n }\n\n const turnSlideToIndex = (index: number) => {\n slideThumbnailModelVisible.value = false\n store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)\n animationIndex.value = 0\n }\n\n const contextmenus = (): ContextmenuItem[] => {\n return [\n {\n text: '上一页',\n disable: slideIndex.value <= 0,\n handler: () => turnPrevSlide(),\n },\n {\n text: '下一页',\n disable: slideIndex.value >= slides.value.length - 1,\n handler: () => turnNextSlide(),\n },\n {\n text: '结束放映',\n subText: 'ESC',\n handler: exitScreening,\n },\n ]\n }\n \n provide('slideScale', scale)\n\n return {\n slides,\n slideIndex,\n currentSlide,\n slideWidth,\n slideHeight,\n scale,\n mousewheelListener,\n animationIndex,\n contextmenus,\n execPrev,\n execNext,\n slideThumbnailModelVisible,\n turnSlideToIndex,\n writingBoardToolVisible,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=048f6280&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=048f6280&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-048f6280\"\n\nexport default script","\nimport { computed, defineComponent, onMounted } from 'vue'\nimport { MutationTypes, ActionTypes, useStore } from '@/store'\n\nimport Editor from './views/Editor/index.vue'\nimport Screen from './views/Screen/index.vue'\n\nexport default defineComponent({\n name: 'app',\n components: {\n Editor,\n Screen,\n },\n setup() {\n const store = useStore()\n const screening = computed(() => store.state.screening)\n\n onMounted(() => {\n store.commit(MutationTypes.SET_AVAILABLE_FONTS)\n store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)\n })\n\n return {\n screening,\n }\n },\n})\n","import { render } from \"./App.vue?vue&type=template&id=7fa1c35b\"\nimport script from \"./App.vue?vue&type=script&lang=ts\"\nexport * from \"./App.vue?vue&type=script&lang=ts\"\n\nimport \"./App.vue?vue&type=style&index=0&id=7fa1c35b&lang=scss\"\nscript.render = render\n\nexport default script","\n\n\n\n","\n\n\n\n","\nimport { PropType, defineComponent } from 'vue'\nimport { ContextmenuItem } from './types'\n\nexport default defineComponent({\n name: 'menu-content',\n props: {\n menus: {\n type: Array as PropType,\n required: true,\n },\n subMenuPosition: {\n type: String,\n default: 'left',\n },\n handleClickMenuItem: {\n type: Function,\n required: true,\n },\n },\n})\n","import { render } from \"./MenuContent.vue?vue&type=template&id=3cad6828&scoped=true\"\nimport script from \"./MenuContent.vue?vue&type=script&lang=ts\"\nexport * from \"./MenuContent.vue?vue&type=script&lang=ts\"\n\nimport \"./MenuContent.vue?vue&type=style&index=0&id=3cad6828&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-3cad6828\"\n\nexport default script","\nimport { computed, defineComponent, PropType } from 'vue'\nimport { ContextmenuItem, Axis } from './types'\n\nimport MenuContent from './MenuContent.vue'\n\nconst MENU_WIDTH = 160\nconst MENU_HEIGHT = 30\nconst DIVIDER_HEIGHT = 11\nconst SUB_MENU_WIDTH = 120\n\nexport default defineComponent({\n name: 'contextmenu',\n components: {\n MenuContent,\n },\n props: {\n axis: {\n type: Object as PropType,\n required: true,\n },\n el: {\n type: Object as PropType,\n required: true,\n },\n menus: {\n type: Array as PropType,\n required: true,\n },\n removeContextMenu: {\n type: Function,\n required: true,\n },\n },\n setup(props) {\n const style = computed(() => {\n const { x, y } = props.axis\n const normalMenuCount = props.menus.filter(menu => !menu.divider && !menu.hide).length\n const dividerMenuCount = props.menus.filter(menu => menu.divider).length\n const padding = 10\n\n const menuWidth = MENU_WIDTH\n const menuHeight = normalMenuCount * MENU_HEIGHT + dividerMenuCount * DIVIDER_HEIGHT + padding\n\n const maxMenuWidth = MENU_WIDTH + SUB_MENU_WIDTH - 10\n\n const screenWidth = document.body.clientWidth\n const screenHeight = document.body.clientHeight\n\n const left = (screenWidth <= x + menuWidth ? x - menuWidth : x)\n const top = (screenHeight <= y + menuHeight ? y - menuHeight : y)\n\n const subMenuPosition = screenWidth <= left + maxMenuWidth ? 'right' : 'left'\n\n return {\n left: left + 'px',\n top: top + 'px',\n subMenuPosition,\n }\n })\n\n const handleClickMenuItem = (item: ContextmenuItem) => {\n if(item.disable || item.children) return\n if(item.handler) item.handler(props.el)\n props.removeContextMenu()\n }\n\n return {\n style,\n handleClickMenuItem,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=0fa561b9\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0fa561b9&lang=scss\"\nscript.render = render\n\nexport default script","import { Directive, createVNode, render, DirectiveBinding } from 'vue'\nimport ContextmenuComponent from '@/components/Contextmenu/index.vue'\n\nconst CTX_CONTEXTMENU_HANDLER = 'CTX_CONTEXTMENU_HANDLER'\n\nconst contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\n event.stopPropagation()\n event.preventDefault()\n\n const menus = binding.value(el)\n if(!menus) return\n\n let container: HTMLDivElement | null = null\n\n const removeContextMenu = () => {\n if(container) {\n document.body.removeChild(container)\n container = null\n }\n el.classList.remove('contextmenu-active')\n document.body.removeEventListener('scroll', removeContextMenu) \n window.removeEventListener('resize', removeContextMenu)\n }\n\n const options = {\n axis: { x: event.x, y: event.y },\n el,\n menus,\n removeContextMenu,\n }\n container = document.createElement('div')\n const vm = createVNode(ContextmenuComponent, options, null)\n render(vm, container)\n document.body.appendChild(container)\n\n el.classList.add('contextmenu-active')\n\n document.body.addEventListener('scroll', removeContextMenu)\n window.addEventListener('resize', removeContextMenu)\n}\n\nconst ContextmenuDirective: Directive = {\n mounted(el: HTMLElement, binding) {\n el[CTX_CONTEXTMENU_HANDLER] = (event: MouseEvent) => contextmenuListener(el, event, binding)\n el.addEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\n },\n\n unmounted(el: HTMLElement) {\n if(el && el[CTX_CONTEXTMENU_HANDLER]) {\n el.removeEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])\n delete el[CTX_CONTEXTMENU_HANDLER]\n }\n },\n}\n\nexport default ContextmenuDirective","import { Directive, DirectiveBinding } from 'vue'\n\nconst CTX_CLICK_OUTSIDE_HANDLER = 'CTX_CLICK_OUTSIDE_HANDLER'\n\nconst clickListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {\n const handler = binding.value\n\n const path = event.composedPath()\n const isClickOutside = path ? path.indexOf(el) < 0 : !el.contains(event.target as HTMLElement)\n\n if(!isClickOutside) return\n handler(event)\n}\n\nconst ClickOutsideDirective: Directive = {\n mounted(el: HTMLElement, binding) {\n el[CTX_CLICK_OUTSIDE_HANDLER] = (event: MouseEvent) => clickListener(el, event, binding)\n setTimeout(() => {\n document.addEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\n }, 0)\n },\n \n unmounted(el: HTMLElement) {\n if(el[CTX_CLICK_OUTSIDE_HANDLER]) {\n document.removeEventListener('click', el[CTX_CLICK_OUTSIDE_HANDLER])\n delete el[CTX_CLICK_OUTSIDE_HANDLER]\n }\n },\n}\n\nexport default ClickOutsideDirective","import { App } from 'vue'\nimport {\n Home,\n PlayOne,\n Lock,\n Unlock,\n Search,\n Delete,\n Ppt,\n SettingOne,\n Clear,\n Format,\n Picture,\n FullScreen,\n OffScreen,\n LinkOne,\n List,\n OrderedList,\n Drag,\n Helpcenter,\n SplitCells,\n MergeCells,\n FlipVertically,\n FlipHorizontally,\n FontSize,\n Code,\n TextBold,\n TextItalic,\n TextUnderline,\n Strikethrough,\n Edit,\n Quote,\n EnterTheKeyboard,\n Copy,\n Clipboard,\n Find,\n BackgroundColor,\n Group,\n Ungroup,\n FullSelection,\n ClearFormat,\n Back,\n Next,\n Fullwidth,\n GridFour,\n AlignTop,\n AlignLeft,\n AlignRight,\n AlignBottom,\n AlignVertically,\n AlignHorizontally,\n BringToFront,\n SendToBack,\n AlignTextLeft,\n AlignTextRight,\n AlignTextCenter,\n RowHeight,\n More,\n Write,\n InsertTable,\n CuttingOne,\n AddThree,\n AddText,\n Fill,\n Tailoring,\n Newlybuild,\n Effects,\n ColorFilter,\n Up,\n Down,\n Left,\n Right,\n Plus,\n Minus,\n Check,\n Close,\n Connection,\n BringToFrontOne,\n SentToBack,\n Github,\n ChartRing,\n ChartLine,\n ChartHistogramOne,\n ChartHistogram,\n ChartProportion,\n ChartScatter,\n PentagonOne,\n PageTemplate,\n Text,\n Rotate,\n LeftC,\n RightC,\n Platte,\n UpOne,\n DownOne,\n SeoFolder,\n CloseSmall,\n Undo,\n Transform,\n Click,\n Theme,\n Symbol,\n} from '@icon-park/vue-next'\n\nexport default {\n install(app: App) {\n // 插入元素\n app.component('IconFontSize', FontSize)\n app.component('IconPicture', Picture)\n app.component('IconPentagonOne', PentagonOne)\n app.component('IconConnection', Connection)\n app.component('IconInsertTable', InsertTable)\n app.component('IconSymbol', Symbol)\n\n // 剪贴板\n app.component('IconCopy', Copy)\n app.component('IconClipboard', Clipboard)\n app.component('IconCuttingOne', CuttingOne)\n\n // 锁定与解锁\n app.component('IconLock', Lock)\n app.component('IconUnlock', Unlock)\n\n // 全屏\n app.component('IconFullScreen', FullScreen)\n app.component('IconOffScreen', OffScreen)\n\n // 撤销重做\n app.component('IconBack', Back)\n app.component('IconNext', Next) \n \n // 对齐\n app.component('IconAlignTop', AlignTop)\n app.component('IconAlignLeft', AlignLeft)\n app.component('IconAlignRight', AlignRight)\n app.component('IconAlignBottom', AlignBottom)\n app.component('IconAlignVertically', AlignVertically)\n app.component('IconAlignHorizontally', AlignHorizontally)\n\n // 层级\n app.component('IconBringToFront', BringToFront)\n app.component('IconSentToBack', SentToBack)\n app.component('IconBringToFrontOne', BringToFrontOne)\n app.component('IconSendToBack', SendToBack)\n\n // 组合\n app.component('IconGroup', Group)\n app.component('IconUngroup', Ungroup)\n\n // 通用元素编辑\n app.component('IconFill', Fill)\n app.component('IconBackgroundColor', BackgroundColor)\n app.component('IconPlatte', Platte)\n\n // 表格编辑\n app.component('IconSplitCells', SplitCells)\n app.component('IconMergeCells', MergeCells)\n \n // 图片编辑\n app.component('IconTailoring', Tailoring)\n app.component('IconColorFilter', ColorFilter)\n app.component('IconFlipVertically', FlipVertically)\n app.component('IconFlipHorizontally', FlipHorizontally)\n\n // 文字编辑\n app.component('IconText', Text)\n app.component('IconAddText', AddText)\n app.component('IconAlignTextLeft', AlignTextLeft)\n app.component('IconAlignTextRight', AlignTextRight)\n app.component('IconAlignTextCenter', AlignTextCenter)\n app.component('IconRowHeight', RowHeight)\n app.component('IconFullwidth', Fullwidth)\n app.component('IconCode', Code)\n app.component('IconTextBold', TextBold)\n app.component('IconTextItalic', TextItalic)\n app.component('IconTextUnderline', TextUnderline)\n app.component('IconStrikethrough', Strikethrough)\n app.component('IconQuote', Quote)\n app.component('IconList', List)\n app.component('IconOrderedList', OrderedList)\n app.component('IconUpOne', UpOne)\n app.component('IconDownOne', DownOne)\n app.component('IconFormat', Format)\n\n // 箭头与符号\n app.component('IconUp', Up)\n app.component('IconDown', Down)\n app.component('IconLeft', Left)\n app.component('IconRight', Right)\n app.component('IconLeftC', LeftC)\n app.component('IconRightC', RightC)\n app.component('IconPlus', Plus)\n app.component('IconMinus', Minus)\n app.component('IconCheck', Check)\n app.component('IconClose', Close)\n app.component('IconCloseSmall', CloseSmall)\n \n // 图表\n app.component('IconChartRing', ChartRing)\n app.component('IconChartLine', ChartLine)\n app.component('IconChartHistogramOne', ChartHistogramOne)\n app.component('IconChartHistogram', ChartHistogram)\n app.component('IconChartProportion', ChartProportion)\n app.component('IconChartScatter', ChartScatter)\n\n // 其他\n app.component('IconHome', Home)\n app.component('IconPlayOne', PlayOne)\n app.component('IconSearch', Search)\n app.component('IconDelete', Delete)\n app.component('IconPpt', Ppt)\n app.component('IconSettingOne', SettingOne)\n app.component('IconClear', Clear)\n app.component('IconLinkOne', LinkOne)\n app.component('IconDrag', Drag)\n app.component('IconHelpcenter', Helpcenter)\n app.component('IconEnterTheKeyboard', EnterTheKeyboard)\n app.component('IconFind', Find)\n app.component('IconFullSelection', FullSelection)\n app.component('IconClearFormat', ClearFormat)\n app.component('IconGridFour', GridFour)\n app.component('IconPageTemplate', PageTemplate)\n app.component('IconGithub', Github)\n app.component('IconMore', More)\n app.component('IconWrite', Write)\n app.component('IconAddThree', AddThree)\n app.component('IconNewlybuild', Newlybuild)\n app.component('IconEffects', Effects)\n app.component('IconRotate', Rotate)\n app.component('IconEdit', Edit)\n app.component('IconSeoFolder', SeoFolder)\n app.component('IconUndo', Undo)\n app.component('IconTransform', Transform)\n app.component('IconClick', Click)\n app.component('IconTheme', Theme)\n }\n}","\n\n\n\n","\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n name: 'file-input',\n props: {\n accept: {\n type: String,\n default: 'image/*',\n },\n },\n setup(props, { emit }) {\n const inputRef = ref()\n\n const handleClick = () => {\n if(!inputRef.value) return\n inputRef.value.value = ''\n inputRef.value.click()\n }\n const handleChange = (e: InputEvent) => {\n const files = (e.target as HTMLInputElement).files\n if(files) emit('change', files)\n }\n\n return {\n handleClick,\n handleChange,\n inputRef,\n }\n },\n})\n","import { render } from \"./FileInput.vue?vue&type=template&id=59732924&scoped=true\"\nimport script from \"./FileInput.vue?vue&type=script&lang=ts\"\nexport * from \"./FileInput.vue?vue&type=script&lang=ts\"\n\nimport \"./FileInput.vue?vue&type=style&index=0&id=59732924&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-59732924\"\n\nexport default script","\n\n","\nexport default {\n name: 'svg-wrapper',\n}\n","import { render } from \"./SvgWrapper.vue?vue&type=template&id=07215504\"\nimport script from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nexport * from \"./SvgWrapper.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\r\n\r\n\r\n\r\n","\r\nexport default {\r\n name: 'checkbox-button',\r\n props: {\r\n checked: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n}\r\n","import { render } from \"./CheckboxButton.vue?vue&type=template&id=7cae2b90&scoped=true\"\nimport script from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButton.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButton.vue?vue&type=style&index=0&id=7cae2b90&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7cae2b90\"\n\nexport default script","\r\n\r\n\r\n\r\n","\r\nexport default {\r\n name: 'checkbox-button-group',\r\n}\r\n","import { render } from \"./CheckboxButtonGroup.vue?vue&type=template&id=7dafd0a9&scoped=true\"\nimport script from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\nexport * from \"./CheckboxButtonGroup.vue?vue&type=script&lang=ts\"\n\nimport \"./CheckboxButtonGroup.vue?vue&type=style&index=0&id=7dafd0a9&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7dafd0a9\"\n\nexport default script","\n\n\n\n","\n\n\n\n","\n\n\n\n","\nimport { computed, defineComponent } from 'vue'\n\nconst checkboardCache = {}\nconst renderCheckboard = (white: string, grey: string, size: number) => {\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = size * 2\n const ctx = canvas.getContext('2d')\n \n if(!ctx) return null\n\n ctx.fillStyle = white\n ctx.fillRect(0, 0, canvas.width, canvas.height)\n ctx.fillStyle = grey\n ctx.fillRect(0, 0, size, size)\n ctx.translate(size, size)\n ctx.fillRect(0, 0, size, size)\n return canvas.toDataURL()\n}\n\nconst getCheckboard = (white: string, grey: string, size: number) => {\n const key = white + ',' + grey + ',' + size\n if(checkboardCache[key]) return checkboardCache[key]\n \n const checkboard = renderCheckboard(white, grey, size)\n checkboardCache[key] = checkboard\n return checkboard\n}\n\nexport default defineComponent({\n name: 'checkboard',\n props: {\n size: {\n type: Number,\n default: 8,\n },\n white: {\n type: String,\n default: '#fff',\n },\n grey: {\n type: String,\n default: '#e6e6e6',\n },\n },\n setup(props) {\n const bgStyle = computed(() => {\n const checkboard = getCheckboard(props.white, props.grey, props.size)\n return { backgroundImage: `url(${checkboard})` }\n })\n\n return {\n bgStyle,\n }\n },\n})\n","import { render } from \"./Checkboard.vue?vue&type=template&id=2352ea60&scoped=true\"\nimport script from \"./Checkboard.vue?vue&type=script&lang=ts\"\nexport * from \"./Checkboard.vue?vue&type=script&lang=ts\"\n\nimport \"./Checkboard.vue?vue&type=style&index=0&id=2352ea60&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-2352ea60\"\n\nexport default script","\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\n\nimport Checkboard from './Checkboard.vue'\nimport { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'alpha',\n components: {\n Checkboard,\n },\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props, { emit }) {\n const color = computed(() => props.value)\n const gradientColor = computed(() => {\n const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')\n return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`\n })\n\n const alphaRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!alphaRef.value) return\n const containerWidth = alphaRef.value.clientWidth\n const xOffset = alphaRef.value.getBoundingClientRect().left + window.pageXOffset\n const left = e.pageX - xOffset\n let a\n\n if(left < 0) a = 0\n else if(left > containerWidth) a = 1\n else a = Math.round(left * 100 / containerWidth) / 100\n\n if(color.value.a !== a) {\n emit('colorChange', {\n r: color.value.r,\n g: color.value.g,\n b: color.value.b,\n a: a,\n })\n }\n }\n\n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n alphaRef,\n gradientColor,\n handleMouseDown,\n color,\n }\n },\n})\n","import { render } from \"./Alpha.vue?vue&type=template&id=40ed15f5&scoped=true\"\nimport script from \"./Alpha.vue?vue&type=script&lang=ts\"\nexport * from \"./Alpha.vue?vue&type=script&lang=ts\"\n\nimport \"./Alpha.vue?vue&type=style&index=0&id=40ed15f5&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-40ed15f5\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, PropType, ref, watch } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'hue',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n hue: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const oldHue = ref(0)\n const pullDirection = ref('')\n \n const color = computed(() => {\n const hsla = tinycolor(props.value).toHsl()\n if(hsla.s === 0) hsla.h = props.hue\n return hsla\n })\n\n const pointerLeft = computed(() => {\n if(color.value.h === 0 && pullDirection.value === 'right') return '100%'\n return color.value.h * 100 / 360 + '%'\n })\n\n watch(() => props.value, () => {\n const hsla = tinycolor(props.value).toHsl()\n const h = hsla.s === 0 ? props.hue : hsla.h\n if(h !== 0 && h - oldHue.value > 0) pullDirection.value = 'right'\n if(h !== 0 && h - oldHue.value < 0) pullDirection.value = 'left'\n oldHue.value = h\n })\n\n const hueRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!hueRef.value) return\n\n const containerWidth = hueRef.value.clientWidth\n const xOffset = hueRef.value.getBoundingClientRect().left + window.pageXOffset\n const left = e.pageX - xOffset\n let h, percent\n \n if(left < 0) h = 0\n else if(left > containerWidth) h = 360\n else {\n percent = left * 100 / containerWidth\n h = (360 * percent / 100)\n }\n if(color.value.h !== h) {\n emit('colorChange', {\n h,\n l: color.value.l,\n s: color.value.s,\n a: color.value.a,\n })\n }\n }\n\n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n hueRef,\n handleMouseDown,\n pointerLeft,\n }\n },\n})\n","import { render } from \"./Hue.vue?vue&type=template&id=0cb6d507&scoped=true\"\nimport script from \"./Hue.vue?vue&type=script&lang=ts\"\nexport * from \"./Hue.vue?vue&type=script&lang=ts\"\n\nimport \"./Hue.vue?vue&type=style&index=0&id=0cb6d507&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-0cb6d507\"\n\nexport default script","\n\n\n\n","\nimport { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\nimport throttle from 'lodash/throttle'\nimport clamp from 'lodash/clamp'\n\nexport default defineComponent({\n name: 'saturation',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n hue: {\n type: Number,\n required: true,\n },\n },\n setup(props, { emit }) {\n const color = computed(() => {\n const hsva = tinycolor(props.value).toHsv()\n if(hsva.s === 0) hsva.h = props.hue\n return hsva\n })\n\n const bgColor = computed(() => `hsl(${color.value.h}, 100%, 50%)`)\n const pointerTop = computed(() => (-(color.value.v * 100) + 1) + 100 + '%')\n const pointerLeft = computed(() => color.value.s * 100 + '%')\n\n const emitChangeEvent = throttle(function(param) {\n emit('colorChange', param)\n }, 20, { leading: true, trailing: false })\n\n const saturationRef = ref()\n const handleChange = (e: MouseEvent) => {\n e.preventDefault()\n if(!saturationRef.value) return\n \n const containerWidth = saturationRef.value.clientWidth\n const containerHeight = saturationRef.value.clientHeight\n const xOffset = saturationRef.value.getBoundingClientRect().left + window.pageXOffset\n const yOffset = saturationRef.value.getBoundingClientRect().top + window.pageYOffset\n const left = clamp(e.pageX - xOffset, 0, containerWidth)\n const top = clamp(e.pageY - yOffset, 0, containerHeight)\n const saturation = left / containerWidth\n const bright = clamp(-(top / containerHeight) + 1, 0, 1)\n\n emitChangeEvent({\n h: color.value.h,\n s: saturation,\n v: bright,\n a: color.value.a,\n })\n }\n\n \n const unbindEventListeners = () => {\n window.removeEventListener('mousemove', handleChange)\n window.removeEventListener('mouseup', unbindEventListeners)\n }\n const handleMouseDown = (e: MouseEvent) => {\n handleChange(e)\n window.addEventListener('mousemove', handleChange)\n window.addEventListener('mouseup', unbindEventListeners)\n }\n\n onUnmounted(unbindEventListeners)\n\n return {\n saturationRef,\n bgColor,\n handleMouseDown,\n pointerTop,\n pointerLeft,\n }\n },\n})\n","import { render } from \"./Saturation.vue?vue&type=template&id=792755a0&scoped=true\"\nimport script from \"./Saturation.vue?vue&type=script&lang=ts\"\nexport * from \"./Saturation.vue?vue&type=script&lang=ts\"\n\nimport \"./Saturation.vue?vue&type=style&index=0&id=792755a0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-792755a0\"\n\nexport default script","\n\n\n\n\n","\nimport { computed, defineComponent, PropType } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nexport default defineComponent({\n name: 'editable-input',\n props: {\n value: {\n type: Object as PropType,\n required: true,\n },\n },\n setup(props, { emit }) {\n const val = computed(() => {\n let _hex = ''\n if(props.value.a < 1) _hex = tinycolor(props.value).toHex8String().toUpperCase()\n else _hex = tinycolor(props.value).toHexString().toUpperCase()\n return _hex.replace('#', '')\n })\n\n const handleInput = (e: InputEvent) => {\n const value = (e.target as HTMLInputElement).value\n if(value.length >= 6) emit('colorChange', tinycolor(value).toRgb())\n }\n\n return {\n val,\n handleInput,\n }\n },\n})\n","import { render } from \"./EditableInput.vue?vue&type=template&id=67f94aae&scoped=true\"\nimport script from \"./EditableInput.vue?vue&type=script&lang=ts\"\nexport * from \"./EditableInput.vue?vue&type=script&lang=ts\"\n\nimport \"./EditableInput.vue?vue&type=style&index=0&id=67f94aae&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-67f94aae\"\n\nexport default script","\nimport { computed, defineComponent, ref } from 'vue'\nimport tinycolor, { ColorFormats } from 'tinycolor2'\n\nimport Alpha from './Alpha.vue'\nimport Checkboard from './Checkboard.vue'\nimport Hue from './Hue.vue'\nimport Saturation from './Saturation.vue'\nimport EditableInput from './EditableInput.vue'\n\nconst presetColorConfig = [\n ['#7f7f7f', '#f2f2f2'],\n ['#0d0d0d', '#808080'],\n ['#1c1a10', '#ddd8c3'],\n ['#0e243d', '#c6d9f0'],\n ['#233f5e', '#dae5f0'],\n ['#632623', '#f2dbdb'],\n ['#4d602c', '#eaf1de'],\n ['#3f3150', '#e6e0ec'],\n ['#1e5867', '#d9eef3'],\n ['#99490f', '#fee9da'],\n]\n\nconst gradient = (startColor: string, endColor: string, step: number) => {\n const _startColor = tinycolor(startColor).toRgb()\n const _endColor = tinycolor(endColor).toRgb()\n\n const rStep = (_endColor.r - _startColor.r) / step\n const gStep = (_endColor.g - _startColor.g) / step\n const bStep = (_endColor.b - _startColor.b) / step\n const gradientColorArr = []\n\n for(let i = 0; i < step; i++) {\n const gradientColor = tinycolor({\n r: _startColor.r + rStep * i,\n g: _startColor.g + gStep * i,\n b: _startColor.b + bStep * i,\n }).toRgbString()\n gradientColorArr.push(gradientColor)\n }\n return gradientColorArr\n}\n\nconst getPresetColors = () => {\n const presetColors = []\n for(const color of presetColorConfig) {\n presetColors.push(gradient(color[1], color[0], 5))\n }\n return presetColors\n}\n\nexport default defineComponent({\n name: 'color-picker',\n components: {\n Alpha,\n Checkboard,\n Hue,\n Saturation,\n EditableInput,\n },\n props: {\n modelValue: {\n type: String,\n default: '#e86b99',\n },\n },\n setup(props, { emit }) {\n const hue = ref(0)\n\n const color = computed({\n get() {\n return tinycolor(props.modelValue).toRgb()\n },\n set(rgba: ColorFormats.RGBA) {\n const rgbaString = `rgba(${[rgba.r, rgba.g, rgba.b, rgba.a].join(',')})`\n emit('update:modelValue', rgbaString)\n },\n })\n\n const themeColors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']\n const standardColors = ['#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57', '#00afee', '#0071be', '#00215f', '#72349d']\n const presetColors = getPresetColors()\n\n const currentColor = computed(() => {\n return `rgba(${[color.value.r, color.value.g, color.value.b, color.value.a].join(',')})`\n })\n\n const selectPresetColor = (colorString: string) => {\n emit('update:modelValue', colorString)\n }\n\n const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {\n if('h' in value) {\n hue.value = value.h\n color.value = tinycolor(value).toRgb()\n }\n else color.value = value\n }\n\n return {\n themeColors,\n standardColors,\n presetColors,\n color,\n hue,\n currentColor,\n changeColor,\n selectPresetColor,\n }\n },\n})\n","import { render } from \"./index.vue?vue&type=template&id=dc0cf132&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=dc0cf132&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dc0cf132\"\n\nexport default script","import { createApp } from 'vue'\nimport App from './App.vue'\nimport { store, key } from './store'\n\nimport '@icon-park/vue-next/styles/index.css'\nimport 'prosemirror-view/style/prosemirror.css'\nimport '@/assets/styles/prosemirror.scss'\nimport '@/assets/styles/global.scss'\nimport '@/assets/styles/antd.scss'\nimport '@/assets/styles/font.scss'\nimport 'animate.css'\n\nimport Contextmenu from './plugins/contextmenu'\nimport ClickOutside from './plugins/clickOutside'\nimport IconPark from './plugins/iconPark'\n\nimport FileInput from '@/components/FileInput.vue'\nimport SvgWrapper from '@/components/SvgWrapper.vue'\nimport CheckboxButton from '@/components/CheckboxButton.vue'\nimport CheckboxButtonGroup from '@/components/CheckboxButtonGroup.vue'\nimport ColorPicker from '@/components/ColorPicker/index.vue'\n\nimport {\n InputNumber,\n Divider,\n Button,\n Tooltip,\n Popover,\n Slider,\n Select,\n Switch,\n Radio,\n Input,\n Modal,\n Dropdown,\n Menu,\n Checkbox,\n Drawer,\n} from 'ant-design-vue'\n\nconst app = createApp(App)\n\napp.component('InputNumber', InputNumber)\napp.component('Divider', Divider)\napp.component('Button', Button)\napp.component('ButtonGroup', Button.Group)\napp.component('Tooltip', Tooltip)\napp.component('Popover', Popover)\napp.component('Slider', Slider)\napp.component('Select', Select)\napp.component('SelectOption', Select.Option)\napp.component('SelectOptGroup', Select.OptGroup)\napp.component('Switch', Switch)\napp.component('Radio', Radio)\napp.component('RadioGroup', Radio.Group)\napp.component('RadioButton', Radio.Button)\napp.component('Input', Input)\napp.component('InputGroup', Input.Group)\napp.component('Modal', Modal)\napp.component('Dropdown', Dropdown)\napp.component('Menu', Menu)\napp.component('MenuItem', Menu.Item)\napp.component('Checkbox', Checkbox)\napp.component('Drawer', Drawer)\n\napp.directive('contextmenu', Contextmenu)\napp.directive('click-outside', ClickOutside)\napp.use(IconPark)\n\napp.component('FileInput', FileInput)\napp.component('SvgWrapper', SvgWrapper)\napp.component('CheckboxButton', CheckboxButton)\napp.component('CheckboxButtonGroup', CheckboxButtonGroup)\napp.component('ColorPicker', ColorPicker)\n\napp.use(store, key)\napp.mount('#app')\n","export * from \"-!../../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=0bd1ca02&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Chart.vue?vue&type=style&index=1&id=5f401eca&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./TableGenerator.vue?vue&type=style&index=0&id=0239b43b&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Hue.vue?vue&type=style&index=0&id=0cb6d507&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementOutline.vue?vue&type=style&index=0&id=38e2f880&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./MenuContent.vue?vue&type=style&index=0&id=3cad6828&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ElementPositionPanel.vue?vue&type=style&index=0&id=1a79147f&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BorderLine.vue?vue&type=style&index=0&id=630e246b&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=7550799e&lang=scss&scoped=true\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./ShapeStylePanel.vue?vue&type=style&index=0&id=d415c6bc&lang=scss&scoped=true\""],"sourceRoot":""} \ No newline at end of file diff --git a/vue.config.js b/vue.config.js index b046530..3aec66c 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,7 +1,7 @@ const StyleLintPlugin = require('stylelint-webpack-plugin') module.exports = { - assetsDir: './', + publicPath: './', css: { loaderOptions: { sass: {