r?"right":"left");var f,l=[],h=[e,n],d=[r,o],p=h[0]+(d[0]-h[0])/2,v=h[1]+(d[1]-h[1])/2,y=function(){var t=[p,f[1]],e=[p,C[1]];l.push(t),l.push(e)},g=function(){var t=[f[0],v],e=[C[0],v];l.push(t),l.push(e)},b=function(){l.push([f[0],h[1]-50]),l.push([C[0],h[1]-50])},m=function(){l.push([f[0],h[1]+50]),l.push([C[0],h[1]+50])},x=function(){l.push([h[0]+80,f[1]]),l.push([h[0]+80,C[1]])},w=function(){l.push([h[0]-80,f[1]]),l.push([h[0]-80,C[1]])},_=function(){l.push([f[0],C[1]])},S=function(){l.push([C[0],f[1]])};switch(i){case"left":f=[h[0]-20,h[1]];break;case"top":f=[h[0],h[1]-20];break;case"bottom":f=[h[0],h[1]+20];break;default:f=[h[0]+20,h[1]];break}var C=null;switch(c){case"right":C=[d[0]+20,d[1]];break;case"top":C=[d[0],d[1]-20];break;case"bottom":C=[d[0],d[1]+20];break;default:C=[d[0]-20,d[1]];break}l.push(h),l.push(f),i=i||"right",c=c||"left";var k=I(e,n,r,o);switch(k.indexOf("r")>-1&&("right"!==i&&"left"!==c||(f[0]>p&&(f[0]=p),C[0]-1&&("bottom"!==i&&"top"!==c||(f[1]>v&&(f[1]=v),C[1]-1&&("left"!==i&&"right"!==c||(f[0]p&&(C[0]=p))),k.indexOf("u")>-1&&("top"!==i&&"bottom"!==c||(f[1]v&&(C[1]=v))),k){case"lu":if("right"===i)switch(c){case"top":case"right":_();break;default:g();break}else if("bottom"===i)switch(c){case"top":y();break;default:S();break}else if("top"===i)switch(c){case"top":case"right":_();break;default:g();break}else switch(c){case"top":case"right":y();break;default:S();break}break;case"u":if("right"===i)switch(c){case"right":break;case"top":_();break;default:g();break}else if("bottom"===i)switch(c){case"left":case"right":S();break;default:x();break}else if("top"===i)switch(c){case"left":S();break;case"right":g();break;case"top":x();break;default:break}else switch(c){case"left":case"right":break;default:l.push([f[0],C[1]]);break}break;case"ru":if("right"===i)switch(c){case"left":y();break;case"top":_();break;default:S();break}else if("bottom"===i)switch(c){case"top":y();break;default:S();break}else if("top"===i)switch(c){case"right":y();break;default:_();break}else switch(c){case"left":case"top":_();break;default:g();break}break;case"l":if("right"===i)switch(c){case"left":case"right":case"top":b();break;default:m();break}else if("bottom"===i)switch(c){case"left":m();break;case"right":_();break;case"top":y();break;default:break}else if("top"===i)switch(c){case"left":b();break;case"right":_();break;case"top":break;default:y();break}else switch(c){case"left":b();break;case"right":break;default:_();break}break;case"r":if("right"===i)switch(c){case"left":break;case"right":b();break;default:_();break}else if("bottom"===i)switch(c){case"left":_();break;case"right":m();break;case"top":y();break;default:break}else if("top"===i)switch(c){case"left":S();break;case"right":b();break;case"top":break;default:y();break}else switch(c){case"left":case"right":case"top":b();break;default:m();break}break;case"ld":if("right"===i)switch(c){case"left":g();break;default:_();break}else if("bottom"===i)switch(c){case"left":S();break;case"top":g();break;default:_();break}else if("top"===i)switch(c){case"left":case"right":case"top":S();break;default:y();break}else switch(c){case"left":case"top":S();break;case"right":y();break;default:_();break}break;case"d":if("right"===i)switch(c){case"left":g();break;case"right":S();break;case"top":_();break;default:x();break}else if("bottom"===i)switch(c){case"left":case"right":S();break;case"top":break;default:x();break}else if("top"===i)switch(c){case"left":w();break;default:x();break}else switch(c){case"left":break;case"right":g();break;case"top":_();break;default:w();break}break;case"rd":"right"===i&&"left"===c?y():"right"===i&&"bottom"===c?_():"right"===i&&"top"===c||"right"===i&&"right"===c?S():"bottom"===i&&"left"===c?_():"bottom"===i&&"right"===c?S():"bottom"===i&&"top"===c?g():"bottom"===i&&"bottom"===c?_():"top"===i&&"left"===c||"top"===i&&"right"===c||"top"===i&&"top"===c?S():"top"===i&&"bottom"===c?y():"left"===i&&"left"===c?_():"left"===i&&"right"===c||"left"===i&&"top"===c?g():"left"===i&&"bottom"===c&&_();break}l.push(C),l.push(d);for(var O=[],N=[],E=0;Et&&E(r,e)?"r":E(n,t)&&re?"d":nt&&re?"ld":"rd"}var R={},F=null;if("undefined"!==typeof document){var D=document.documentElement;"onmouseenter"in D||(R={mouseenter:"mouseover",mouseleave:"mouseout"})}function Y(t,e,n){return t=B(t,e,n),function(e){var n=e.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||t.call(this,e)}}function B(t,e,n){return function(r){var o=F;F=r;try{t.call(this,this.__data__,e,n)}finally{F=o}}}function G(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function X(t){return function(){var e=this.__on;if(e){for(var n,r=0,o=-1,i=e.length;r=w&&(w=x+1);while(!(m=y[w])&&++w=0;)(r=o[i])&&(c&&4^r.compareDocumentPosition(c)&&c.parentNode.insertBefore(r,c),c=r);return this},ht=function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=dt);for(var n=this._groups,r=n.length,o=new Array(r),i=0;ie?1:t>=e?0:NaN}var pt=function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},vt=function(){var t=new Array(this.size()),e=-1;return this.each((function(){t[++e]=this})),t},yt=function(){for(var t=this._groups,e=0,n=t.length;e=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),wt.hasOwnProperty(e)?{space:wt[e],local:t}:t};function St(t){return function(){this.removeAttribute(t)}}function Ct(t){return function(){this.removeAttributeNS(t.space,t.local)}}function kt(t,e){return function(){this.setAttribute(t,e)}}function Ot(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function Nt(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function Et(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}var Tt=function(t,e){var n=_t(t);if(arguments.length<2){var r=this.node();return n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}return this.each((null==e?n.local?Ct:St:"function"===typeof e?n.local?Et:Nt:n.local?Ot:kt)(n,e))},Pt=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};function jt(t){return function(){this.style.removeProperty(t)}}function At(t,e,n){return function(){this.style.setProperty(t,e,n)}}function Mt(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}var Lt=function(t,e,n){return arguments.length>1?this.each((null==e?jt:"function"===typeof e?Mt:At)(t,e,null==n?"":n)):It(this.node(),t)};function It(t,e){return t.style.getPropertyValue(e)||Pt(t).getComputedStyle(t,null).getPropertyValue(e)}function Rt(t){return function(){delete this[t]}}function Ft(t,e){return function(){this[t]=e}}function Dt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}var Yt=function(t,e){return arguments.length>1?this.each((null==e?Rt:"function"===typeof e?Dt:Ft)(t,e)):this.node()[t]};function Bt(t){return t.trim().split(/^|\s+/)}function Gt(t){return t.classList||new Xt(t)}function Xt(t){this._node=t,this._names=Bt(t.getAttribute("class")||"")}function $t(t,e){var n=Gt(t),r=-1,o=e.length;while(++r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Wt=function(t,e){var n=Bt(t+"");if(arguments.length<2){var r=Gt(this.node()),o=-1,i=n.length;while(++o=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function je(t,e){for(var n,r=0,o=t.length;r0)for(var n,r,o=new Array(n),i=0;il}u.mouse("drag")}function v(){Oe(F.view).on("mousemove.drag mouseup.drag",null),Ge(F.view,n),Ye(),u.mouse("end")}function y(){if(o.apply(this,arguments)){var t,e,n=F.changedTouches,r=i.apply(this,arguments),c=n.length;for(t=0;te.width-8&&r.length>0)r=r.slice(0,-1),t.text(r+"..."),n=t.node().getComputedTextLength()})));var l=t.append("rect").attr("class","body");l.style("width",e.width+"px").style("fill",a).style("stroke-width","1px"),"start"!==e.type&&"end"!==e.type?(l.attr("x",e.x).attr("y",e.y+20),l.style("height",j(e.height-20)+"px")):(l.attr("x",e.x).attr("y",e.y).classed(e.type,!0).attr("rx",30),l.style("height",j(e.height)+"px")),l.attr("stroke",f);var h,d="start"===e.type?"Start":"end"===e.type?"End":e.approvers&&0!==e.approvers.length?e.approvers.length>1?"".concat(e.approvers[0].name+"..."):e.approvers[0].name:"No approver";h="start"!==e.type&&"end"!==e.type?e.y+25+j(e.height-20)/2:e.y+5+j(e.height)/2;var p=t.append("text").attr("fill",u).attr("x",e.x+e.width/2).attr("y",h).attr("class","unselectable").attr("text-anchor","middle").text((function(){return d})).each((function(){var t=Oe(this),n=t.node().getComputedTextLength(),r=t.text();while(n>e.width-8&&r.length>0)r=r.slice(0,-1),t.text(r+"..."),n=t.node().getComputedTextLength()}));return{header:r,title:o,body:l,content:p}}var Ke=He;n("5df3"),n("1c4c");function Je(t,e){var n=document.querySelector(t),r=Array.from(n.childNodes);return r.some((function(t){return t.contains(e)}))}var Qe={name:"flowchart",props:{nodes:{type:Array,default:function(){return[{id:1,x:140,y:270,name:"Start",type:"start"},{id:2,x:540,y:270,name:"End",type:"end"}]}},connections:{type:Array,default:function(){return[{source:{id:1,position:"right"},destination:{id:2,position:"left"},id:1,type:"pass"}]}},width:{type:[String,Number],default:800},height:{type:[String,Number],default:600},readonly:{type:Boolean,default:!1},readOnlyPermissions:{type:Object,default:function(){return{allowDragNodes:!1,allowSave:!1,allowAddNodes:!1,allowEditNodes:!1,allowEditConnections:!1,allowDblClick:!1}}},removeRequiresConfirmation:{type:Boolean,default:!1}},data:function(){return{internalNodes:[],internalConnections:[],connectingInfo:{source:null,sourcePosition:null},selectionInfo:null,moveInfo:null,currentNodes:[],currentConnections:[],cursorToChartOffset:{x:0,y:0},clickedOnce:!1,pathClickedOnce:!1,lines:[],invalidConnections:[],moveCoordinates:{startX:0,startY:0,diffX:0,diffY:0}}},methods:{add:function(t){this.readonly&&!this.readOnlyPermissions.allowAddNodes||(this.internalNodes.push(t),this.$emit("add",t,this.internalNodes,this.internalConnections))},editCurrent:function(){1===this.currentNodes.length?this.editNode(this.currentNodes[0]):1===this.currentConnections.length&&this.editConnection(this.currentConnections[0])},editNode:function(t){this.readonly&&!this.readOnlyPermissions.allowEditNodes||this.$emit("editnode",t)},editConnection:function(t){this.readonly&&!this.readOnlyPermissions.allowEditConnections||this.$emit("editconnection",t)},handleChartMouseWheel:function(t){if(t.stopPropagation(),t.preventDefault(),t.ctrlKey){var e=document.getElementById("svg"),n=parseFloat(e.style.zoom||1);if(t.deltaY>0&&.1===n)return;n-=t.deltaY/100/10,e.style.zoom=n}},handleChartMouseUp:function(){var t=k(regeneratorRuntime.mark((function t(e){var n,r;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:this.connectingInfo.source&&(this.hoveredConnector&&this.isNodesConnectionValid()&&(n=+new Date,r={source:{id:this.connectingInfo.source.id,position:this.connectingInfo.sourcePosition},destination:{id:this.hoveredConnector.node.id,position:this.hoveredConnector.position},id:n,type:"pass",name:"Pass"},this.internalConnections.push(r),this.$emit("connect",r,this.internalNodes,this.internalConnections)),this.connectingInfo.source=null,this.connectingInfo.sourcePosition=null),this.selectionInfo&&(this.selectionInfo=null),this.moveInfo&&(this.moveCoordinates.diffX-=e.pageX-this.moveCoordinates.startX,this.moveCoordinates.diffY+=e.pageY-this.moveCoordinates.startY,this.$emit("movediff",{x:this.moveCoordinates.diffX,y:this.moveCoordinates.diffY}),this.moveInfo=null);case 3:case"end":return t.stop()}}),t,this)})));function e(e){return t.apply(this,arguments)}return e}(),isNodesConnectionValid:function(){var t=this,e=this.connectingInfo.source.id===this.hoveredConnector.node.id,n=this.internalConnections.some((function(e){return e.source.id===t.connectingInfo.source.id&&e.source.position===t.connectingInfo.sourcePosition&&e.destination.id===t.hoveredConnector.node.id&&e.destination.position===t.hoveredConnector.position}));return!e&&!n},handleChartMouseMove:function(){var t=k(regeneratorRuntime.mark((function t(e){var n,r,o,i,c,a,u,s,f,l,h;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(n=e.currentTarget.getBoundingClientRect(),r=e.pageX-n.left-window.scrollX,this.cursorToChartOffset.x=Math.trunc(r),o=e.pageY-n.top-window.scrollY,this.cursorToChartOffset.y=Math.trunc(o),!this.connectingInfo.source){t.next=30;break}return t.next=8,this.renderConnections();case 8:for(i=!0,c=!1,a=void 0,t.prev=11,u=document.querySelectorAll("#svg .connector")[Symbol.iterator]();!(i=(s=u.next()).done);i=!0)f=s.value,f.classList.add("active");t.next=19;break;case 15:t.prev=15,t.t0=t["catch"](11),c=!0,a=t.t0;case 19:t.prev=19,t.prev=20,i||null==u.return||u.return();case 22:if(t.prev=22,!c){t.next=25;break}throw a;case 25:return t.finish(22);case 26:return t.finish(19);case 27:l=this.getNodeConnectorOffset(this.connectingInfo.source.id,this.connectingInfo.sourcePosition),h=this.hoveredConnector?this.hoveredConnector.position:null,this.arrowTo(l.x,l.y,this.cursorToChartOffset.x,this.cursorToChartOffset.y,this.connectingInfo.sourcePosition,h);case 30:case"end":return t.stop()}}),t,this,[[11,15,19,27],[20,,22,26]])})));function e(e){return t.apply(this,arguments)}return e}(),handleChartDblClick:function(t){this.isMouseClickOnSlot(t.target)||this.readonly&&!this.readOnlyPermissions.allowDblClick||this.$emit("dblclick",{x:t.offsetX,y:t.offsetY})},handleChartMouseDown:function(t){this.isMouseClickOnSlot(t.target)||(t.ctrlKey?(this.moveCoordinates.startX=t.pageX,this.moveCoordinates.startY=t.pageY,this.initializeMovingAllElements(t)):this.selectionInfo={x:t.offsetX,y:t.offsetY})},isMouseClickOnSlot:function(t){return Je("#chart-slot",t)},initializeMovingAllElements:function(t){this.isMouseOverAnyNode()||(this.moveInfo={x:t.offsetX,y:t.offsetY})},isMouseOverAnyNode:function(){for(var t={x:this.cursorToChartOffset.x,y:this.cursorToChartOffset.y},e=!1,n=0;n=o.start.x&&t.x<=o.end.x&&t.y>=o.start.y&&t.y<=o.end.y;if(i){e=!0;break}}return e},getConnectorPosition:function(t){var e=t.width/2,n=t.height/2,r={};return this.hasNodeConnector(t,"top")&&(r.top={x:t.x+e,y:t.y}),this.hasNodeConnector(t,"right")&&(r.right={x:t.x+t.width,y:t.y+n}),this.hasNodeConnector(t,"bottom")&&(r.bottom={x:t.x+e,y:t.y+t.height}),this.hasNodeConnector(t,"left")&&(r.left={x:t.x,y:t.y+n}),r},hasNodeConnector:function(t,e){return!t.connectors||t.connectors.includes(e)},moveAllElements:function(){var t=this;if(t.moveInfo){var e=t.moveInfo.x-t.cursorToChartOffset.x,n=t.moveInfo.y-t.cursorToChartOffset.y;this.internalNodes.forEach((function(t){t.x-=e,t.y-=n})),t.moveInfo.x=t.cursorToChartOffset.x,t.moveInfo.y=t.cursorToChartOffset.y}},renderSelection:function(){var t=this;if(t.selectionInfo){t.currentNodes.splice(0,t.currentNodes.length),t.currentConnections.splice(0,t.currentConnections.length);var e=T([{x:t.selectionInfo.x,y:t.selectionInfo.y},{x:t.cursorToChartOffset.x,y:t.cursorToChartOffset.y}]),n=!0,r=!1,o=void 0;try{for(var i,c=document.querySelectorAll("#svg .selection")[Symbol.iterator]();!(n=(i=c.next()).done);n=!0){var a=i.value;a.classList.add("active"),a.setAttribute("x",e.start.x),a.setAttribute("y",e.start.y),a.setAttribute("width",e.end.x-e.start.x),a.setAttribute("height",e.end.y-e.start.y)}}catch(p){r=!0,o=p}finally{try{n||null==c.return||c.return()}finally{if(r)throw o}}t.internalNodes.forEach((function(n){var r=[{x:n.x,y:n.y},{x:n.x,y:n.y+n.height},{x:n.x+n.width,y:n.y},{x:n.x+n.width,y:n.y+n.height}];r.some((function(t){return P(t,e)}))&&t.currentNodes.push(n)})),t.lines.forEach((function(n){var r=[{x:n.sourceX,y:n.sourceY},{x:n.destinationX,y:n.destinationY}];if(r.every((function(t){return P(t,e)}))&&t.currentConnections.every((function(t){return t.id!==n.id}))){var o=t.internalConnections.filter((function(t){return t.id===n.id}))[0];t.currentConnections.push(o)}}))}else{var u=!0,s=!1,f=void 0;try{for(var l,h=document.querySelectorAll("#svg > .selection")[Symbol.iterator]();!(u=(l=h.next()).done);u=!0){var d=l.value;d.classList.remove("active")}}catch(p){s=!0,f=p}finally{try{u||null==h.return||h.return()}finally{if(s)throw f}}}},renderConnections:function(){var t=this;return new Promise((function(e){t.$nextTick((function(){var n=!0,r=!1,o=void 0;try{for(var i,c=document.querySelectorAll("#svg > g.connection")[Symbol.iterator]();!(n=(i=c.next()).done);n=!0){var a=i.value;a.remove()}}catch(u){r=!0,o=u}finally{try{n||null==c.return||c.return()}finally{if(r)throw o}}t.lines=[],t.invalidConnections=[],t.internalConnections.forEach((function(e){if(t.haveNodesSelectedConnectors(e)){var n=t.getNodeConnectorOffset(e.source.id,e.source.position),r=t.getNodeConnectorOffset(e.destination.id,e.destination.position),o={pass:"#52c41a",reject:"red"};t.currentConnections.filter((function(t){return t===e})).length>0&&(o={pass:"#12640a",reject:"darkred"});var i=t.arrowTo(n.x,n.y,r.x,r.y,e.source.position,e.destination.position,o[e.type]),c=!0,a=!1,s=void 0;try{for(var f,l=i.paths[Symbol.iterator]();!(c=(f=l.next()).done);c=!0){var h=f.value;h.on("mousedown",(function(){if(F.stopPropagation(),t.pathClickedOnce)t.editConnection(e);else{var n=setTimeout((function(){t.pathClickedOnce=!1,clearTimeout(n)}),300);t.pathClickedOnce=!0}t.currentNodes.splice(0,t.currentNodes.length),t.currentConnections.splice(0,t.currentConnections.length),t.currentConnections.push(e)}))}}catch(u){a=!0,s=u}finally{try{c||null==l.return||l.return()}finally{if(a)throw s}}var d=!0,p=!1,v=void 0;try{for(var y,g=i.lines[Symbol.iterator]();!(d=(y=g.next()).done);d=!0){var b=y.value;t.lines.push({sourceX:b.sourceX,sourceY:b.sourceY,destinationX:b.destinationX,destinationY:b.destinationY,id:e.id})}}catch(u){p=!0,v=u}finally{try{d||null==g.return||g.return()}finally{if(p)throw v}}}else t.invalidConnections.push(e)})),e()}))}))},haveNodesSelectedConnectors:function(t){var e=this.nodes.find((function(e){return e.id===t.source.id})),n=this.nodes.find((function(e){return e.id===t.destination.id}));return this.hasNodeConnector(e,t.source.position)&&this.hasNodeConnector(n,t.destination.position)},renderNodes:function(){var t=this;return new Promise((function(e){var n=!0,r=!1,o=void 0;try{for(var i,c=document.querySelectorAll("#svg > g.node")[Symbol.iterator]();!(n=(i=c.next()).done);n=!0){var a=i.value;a.remove()}}catch(u){r=!0,o=u}finally{try{n||null==c.return||c.return()}finally{if(r)throw o}}t.internalNodes.forEach((function(e){t.renderNode(e,t.currentNodes.filter((function(t){return t===e})).length>0)})),e()}))},getNodeConnectorOffset:function(t,e){var n=this.internalNodes.filter((function(e){return e.id===t}))[0];return this.getConnectorPosition(n)[e]},append:function(t){var e=Oe("#svg");return e.insert(t,".selection")},guideLineTo:function(t,e,n,r){var o=this.append("g");o.classed("guideline",!0),A(o,t,e,n,r,1,"#a3a3a3",[5,3])},arrowTo:function(t,e,n,r,o,i,c){var a=this.append("g");return a.classed("connection",!0),M(a,t,e,n,r,o,i,1,c||"#a3a3a3",!0),M(a,t,e,n,r,o,i,5,"transparent",!1)},renderNode:function(t,e){var n=this,r=n.append("g").attr("cursor","move").classed("node",!0),o=Ke(r,t,e);n.$emit("render",t,o);var i=We().on("start",(function(){var e=0===n.currentNodes.filter((function(e){return e===t})).length;if(e&&(n.currentConnections.splice(0,n.currentConnections.length),n.currentNodes.splice(0,n.currentNodes.length),n.currentNodes.push(t)),n.clickedOnce)n.currentNodes.splice(0,n.currentNodes.length),n.editNode(t);else{var r=setTimeout((function(){n.clickedOnce=!1,clearTimeout(r)}),300);n.clickedOnce=!0}})).on("drag",k(regeneratorRuntime.mark((function t(){var e,r,o,i,c,a,u,s,f,l,h,d,p,v,y,g,b,m;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(!n.readonly||n.readOnlyPermissions.allowDragNodes){t.next=2;break}return t.abrupt("return");case 2:for(e=parseFloat(document.getElementById("svg").style.zoom||1),r=!0,o=!1,i=void 0,t.prev=6,c=n.currentNodes[Symbol.iterator]();!(r=(a=c.next()).done);r=!0)u=a.value,s=F.dx/e,u.x+s<0&&(s=-u.x),u.x+=s,f=F.dy/e,u.y+f<0&&(f=-u.y),u.y+=f;t.next=14;break;case 10:t.prev=10,t.t0=t["catch"](6),o=!0,i=t.t0;case 14:t.prev=14,t.prev=15,r||null==c.return||c.return();case 17:if(t.prev=17,!o){t.next=20;break}throw i;case 20:return t.finish(17);case 21:return t.finish(14);case 22:for(l=!0,h=!1,d=void 0,t.prev=25,p=document.querySelectorAll("#svg > g.guideline")[Symbol.iterator]();!(l=(v=p.next()).done);l=!0)y=v.value,y.remove();t.next=33;break;case 29:t.prev=29,t.t1=t["catch"](25),h=!0,d=t.t1;case 33:t.prev=33,t.prev=34,l||null==p.return||p.return();case 36:if(t.prev=36,!h){t.next=39;break}throw d;case 39:return t.finish(36);case 40:return t.finish(33);case 41:g=n.getCurrentNodesEdge(),b=10*Math.round(Math.round(g.start.x)/10),m=10*Math.round(Math.round(g.start.y)/10),n.internalNodes.forEach((function(t){0===n.currentNodes.filter((function(e){return e===t})).length&&(t.x===b&&(t.y g.guideline")[Symbol.iterator]();!(t=(o=i.next()).done);t=!0){var c=o.value;c.remove()}}catch(d){e=!0,r=d}finally{try{t||null==i.return||i.return()}finally{if(e)throw r}}var a=!0,u=!1,s=void 0;try{for(var f,l=n.currentNodes[Symbol.iterator]();!(a=(f=l.next()).done);a=!0){var h=f.value;h.x=10*Math.round(Math.round(h.x)/10),h.y=10*Math.round(Math.round(h.y)/10)}}catch(d){u=!0,s=d}finally{try{a||null==l.return||l.return()}finally{if(u)throw s}}n.$emit("nodesdragged",n.currentNodes)}));r.call(i),r.on("mousedown",(function(){if(F.ctrlKey){var e=0===n.currentNodes.filter((function(e){return e===t})).length;e?n.currentNodes.push(t):n.currentNodes.splice(n.currentNodes.indexOf(t),1)}}));var c=[],a=this.getConnectorPosition(t),u=function(e){var o=a[e],i=r.append("circle").attr("cx",o.x).attr("cy",o.y).attr("r",4).attr("class","connector");i.on("mousedown",(function(){F.stopPropagation(),"end"===t.type||n.readonly||(n.connectingInfo.source=t,n.connectingInfo.sourcePosition=e)})).on("mouseup",(function(){if(F.stopPropagation(),n.connectingInfo.source){if(n.connectingInfo.source.id!==t.id){var r=+new Date,o={source:{id:n.connectingInfo.source.id,position:n.connectingInfo.sourcePosition},destination:{id:t.id,position:e},id:r,type:"pass",name:"Pass"};n.internalConnections.push(o),n.$emit("connect",o,n.internalNodes,n.internalConnections)}n.connectingInfo.source=null,n.connectingInfo.sourcePosition=null}})).on("mouseover",(function(){i.classed("active",!0)})).on("mouseout",(function(){i.classed("active",!1)})),c.push(i)};for(var s in a)u(s);r.on("mouseover",(function(){c.forEach((function(t){return t.classed("active",!0)}))})).on("mouseout",(function(){c.forEach((function(t){return t.classed("active",!1)}))}))},getCurrentNodesEdge:function(){var t=this.currentNodes.map((function(t){return{x:t.x,y:t.y}}));return t.push.apply(t,w(this.currentNodes.map((function(t){return{x:t.x+t.width,y:t.y+t.height}})))),T(t)},save:function(){this.readonly&&!this.readOnlyPermissions.allowSave||this.$emit("save",this.internalNodes,this.internalConnections)},remove:function(){var t=k(regeneratorRuntime.mark((function t(){var e;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(!this.readonly||this.readOnlyPermissions.allowRemove){t.next=2;break}return t.abrupt("return");case 2:if(e=this.currentConnections.length>0||this.currentNodes.length>0,e){t.next=5;break}return t.abrupt("return");case 5:this.removeRequiresConfirmation?this.$emit("removeconfirmationrequired",this.currentNodes,this.currentConnections):this.removeSelectedNodesAndConnections();case 6:case"end":return t.stop()}}),t,this)})));function e(){return t.apply(this,arguments)}return e}(),confirmRemove:function(){this.removeSelectedNodesAndConnections()},removeSelectedNodesAndConnections:function(){if(!this.readonly){if(this.currentConnections.length>0){var t=!0,e=!1,n=void 0;try{for(var r,o=this.currentConnections[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var i=r.value;this.removeConnection(i)}}catch(h){e=!0,n=h}finally{try{t||null==o.return||o.return()}finally{if(e)throw n}}this.currentConnections.splice(0,this.currentConnections.length)}if(this.currentNodes.length>0){var c=!0,a=!1,u=void 0;try{for(var s,f=this.currentNodes[Symbol.iterator]();!(c=(s=f.next()).done);c=!0){var l=s.value;this.removeNode(l)}}catch(h){a=!0,u=h}finally{try{c||null==f.return||f.return()}finally{if(a)throw u}}this.currentNodes.splice(0,this.currentNodes.length)}}},removeNode:function(t){var e=this.internalConnections.filter((function(e){return e.source.id===t.id||e.destination.id===t.id})),n=!0,r=!1,o=void 0;try{for(var i,c=e[Symbol.iterator]();!(n=(i=c.next()).done);n=!0){var a=i.value;this.internalConnections.splice(this.internalConnections.indexOf(a),1)}}catch(u){r=!0,o=u}finally{try{n||null==c.return||c.return()}finally{if(r)throw o}}this.internalNodes.splice(this.internalNodes.indexOf(t),1),this.$emit("delete",t,this.internalNodes,this.internalConnections)},removeConnection:function(t){var e=this.internalConnections.indexOf(t);this.internalConnections.splice(e,1),this.$emit("disconnect",t,this.internalNodes,this.internalConnections)},moveCurrentNode:function(t,e){if(this.currentNodes.length>0&&!this.readonly){var n=!0,r=!1,o=void 0;try{for(var i,c=this.currentNodes[Symbol.iterator]();!(n=(i=c.next()).done);n=!0){var a=i.value;a.x+t<0&&(t=-a.x),a.x+=t,a.y+e<0&&(e=-a.y),a.y+=e}}catch(u){r=!0,o=u}finally{try{n||null==c.return||c.return()}finally{if(r)throw o}}}},init:function(){var t=this,e=this;e.internalNodes.splice(0,e.internalNodes.length),e.internalConnections.splice(0,e.internalConnections.length),e.nodes.forEach((function(n){var r=Object.assign({},n);r.x=r.x-t.moveCoordinates.diffX,r.y=r.y+t.moveCoordinates.diffY,r.width=r.width||120,r.height=r.height||60,e.internalNodes.push(r)})),e.connections.forEach((function(t){e.internalConnections.push(JSON.parse(JSON.stringify(t)))}))}},mounted:function(){var t=this;t.init(),document.onkeydown=function(e){switch(e.keyCode){case 37:t.moveCurrentNode(-10,0);break;case 38:t.moveCurrentNode(0,-10);break;case 39:t.moveCurrentNode(10,0);break;case 40:t.moveCurrentNode(0,10);break;case 27:t.currentNodes.splice(0,t.currentNodes.length),t.currentConnections.splice(0,t.currentConnections.length);break;case 65:var n,r;if(document.activeElement===document.getElementById("chart"))t.currentNodes.splice(0,t.currentNodes.length),t.currentConnections.splice(0,t.currentConnections.length),(n=t.currentNodes).push.apply(n,w(t.internalNodes)),(r=t.currentConnections).push.apply(r,w(t.internalConnections)),e.preventDefault();break;case 46:case 8:t.remove();break;default:break}}},created:function(){},computed:{hoveredConnector:function(){var t=!0,e=!1,n=void 0;try{for(var r,o=this.internalNodes[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var i=r.value,c=this.getConnectorPosition(i);for(var a in c){var u=c[a];if(Math.hypot(u.x-this.cursorToChartOffset.x,u.y-this.cursorToChartOffset.y)<10)return{position:a,node:i}}}}catch(s){e=!0,n=s}finally{try{t||null==o.return||o.return()}finally{if(e)throw n}}return null},hoveredConnection:function(){var t=this,e=!0,n=!1,r=void 0;try{for(var o,i=function(){var e=o.value,n=O(e.sourceX,e.sourceY,e.destinationX,e.destinationY,t.cursorToChartOffset.x,t.cursorToChartOffset.y);if(n<5&&N(e.sourceX-2,e.destinationX+2,t.cursorToChartOffset.x)&&N(e.sourceY-2,e.destinationY+2,t.cursorToChartOffset.y)){var r=t.internalConnections.filter((function(t){return t.id===e.id}));return{v:r.length>0?r[0]:null}}},c=this.lines[Symbol.iterator]();!(e=(o=c.next()).done);e=!0){var a=i();if("object"===l(a))return a.v}}catch(u){n=!0,r=u}finally{try{e||null==c.return||c.return()}finally{if(n)throw r}}return null},cursor:function(){return this.connectingInfo.source||this.hoveredConnector?"crosshair":null!=this.hoveredConnection?"pointer":null}},watch:{internalNodes:{immediate:!0,deep:!0,handler:function(){this.renderNodes(),this.renderConnections()}},internalConnections:{immediate:!0,deep:!0,handler:function(){this.renderConnections()}},selectionInfo:{immediate:!0,deep:!0,handler:function(){this.renderSelection()}},currentNodes:{immediate:!0,deep:!0,handler:function(){this.$emit("select",this.currentNodes),this.renderNodes()}},currentConnections:{immediate:!0,deep:!0,handler:function(){this.$emit("selectconnection",this.currentConnections),this.renderConnections()}},cursorToChartOffset:{immediate:!0,deep:!0,handler:function(){this.selectionInfo?this.renderSelection():this.moveInfo&&this.moveAllElements()}},connectingInfo:{immediate:!0,deep:!0,handler:function(){this.renderConnections()}},nodes:{immediate:!0,deep:!0,handler:function(){this.init()}},connections:{immediate:!0,deep:!0,handler:function(){this.init()}}}},Ze=Qe;n("369f");function tn(t,e,n,r,o,i,c,a){var u,s="function"===typeof t?t.options:t;if(e&&(s.render=e,s.staticRenderFns=n,s._compiled=!0),r&&(s.functional=!0),i&&(s._scopeId="data-v-"+i),c?(u=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(c)},s._ssrRegister=u):o&&(u=a?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(s.functional){s._injectStyles=u;var f=s.render;s.render=function(t,e){return u.call(e),f(t,e)}}else{var l=s.beforeCreate;s.beforeCreate=l?[].concat(l,u):[u]}return{exports:t,options:s}}var en=tn(Ze,o,i,!1,null,null,null),nn=en.exports;nn.install=function(t){t.component(nn.name,nn)};var rn=nn;e["default"]=rn},fdef:function(t,e){t.exports="\t\n\v\f\r \u2028\u2029\ufeff"}})}));
2 | //# sourceMappingURL=FlowChart.umd.min.js.map
--------------------------------------------------------------------------------
/dist/demo.html:
--------------------------------------------------------------------------------
1 |
2 | FlowChart demo
3 |
4 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flowchart-vue",
3 | "version": "0.32.0",
4 | "license": "MIT",
5 | "main": "dist/FlowChart.umd.min.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/joyceworks/flowchart-vue.git"
9 | },
10 | "keywords": [
11 | "flowchart",
12 | "flowchart designer"
13 | ],
14 | "private": false,
15 | "scripts": {
16 | "build-lib": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build --target lib --name FlowChart src/components/flowchart/index.js",
17 | "analyze": "source-map-explorer 'dist/FlowChart.umd.min.js'"
18 | },
19 | "dependencies": {
20 | "d3-selection": "1.4.1",
21 | "d3-drag": "1.2.5"
22 | },
23 | "peerDependencies": {
24 | "vue": "^2.5.22"
25 | },
26 | "devDependencies": {
27 | "@vue/cli-plugin-babel": "^3.1.0",
28 | "@vue/cli-plugin-eslint": "^3.1.0",
29 | "@vue/cli-service": "^3.1.0",
30 | "babel-eslint": "^10.0.1",
31 | "cz-conventional-changelog": "^3.1.0",
32 | "eslint": "^5.8.0",
33 | "eslint-plugin-vue": "^5.0.0",
34 | "prettier": "^2.0.5",
35 | "source-map-explorer": "^2.5.2",
36 | "vue-template-compiler": "^2.5.22"
37 | },
38 | "eslintConfig": {
39 | "root": true,
40 | "env": {
41 | "node": true
42 | },
43 | "extends": [
44 | "plugin:vue/essential",
45 | "eslint:recommended"
46 | ],
47 | "rules": {},
48 | "parserOptions": {
49 | "parser": "babel-eslint"
50 | }
51 | },
52 | "postcss": {
53 | "plugins": {
54 | "autoprefixer": {}
55 | }
56 | },
57 | "browserslist": [
58 | "> 1%",
59 | "last 2 versions",
60 | "not ie <= 8"
61 | ],
62 | "config": {
63 | "commitizen": {
64 | "path": "./node_modules/cz-conventional-changelog"
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Flowchart
9 |
10 |
11 |
12 |
18 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joyceworks/flowchart-vue/87265e615bcd9a1c734915d1ff3141b05105ee85/src/.DS_Store
--------------------------------------------------------------------------------
/src/assets/modal.css:
--------------------------------------------------------------------------------
1 | .modal {
2 | border: 1px solid #d3d3d3;
3 | box-shadow: 2px 2px 1px #d3d3d3;
4 | background-color: white;
5 | position: absolute;
6 | top: 100px;
7 | left: 0;
8 | right: 0;
9 | margin-left: auto;
10 | margin-right: auto;
11 | }
12 |
13 | .form-control {
14 | display: block;
15 | width: 100%;
16 | height: 30px;
17 | margin-bottom: 10px;
18 | }
19 |
20 | .footer {
21 | padding: 10px;
22 | text-align: right;
23 | }
24 |
25 | .footer > button {
26 | margin-left: 10px;
27 | }
28 |
29 | .body {
30 | padding: 10px;
31 | }
32 |
33 | .header {
34 | padding: 10px;
35 | border-bottom: 1px solid #d3d3d3;
36 | }
--------------------------------------------------------------------------------
/src/components/ConnectionDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
23 |
24 |
25 |
26 |
80 |
--------------------------------------------------------------------------------
/src/components/NodeDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
25 |
26 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/flowchart/Flowchart.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 | {{ cursorToChartOffset.x + ", " + cursorToChartOffset.y }}
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
1007 |
--------------------------------------------------------------------------------
/src/components/flowchart/index.css:
--------------------------------------------------------------------------------
1 | #svg {
2 | background-size: 20px 20px, 20px 20px, 10px 10px, 10px 10px;
3 | background-image: linear-gradient(to right, #dfdfdf 1px, transparent 1px),
4 | linear-gradient(to bottom, #dfdfdf 1px, transparent 1px),
5 | linear-gradient(to right, #f1f1f1 1px, transparent 1px),
6 | linear-gradient(to bottom, #f1f1f1 1px, transparent 1px);
7 | background-position: left -1px top -1px, left -1px top -1px, left -1px top -1px, left -1px top -1px;
8 | height: 100%;
9 | width: 100%;
10 | }
11 |
12 | #chart {
13 | position: relative;
14 | width: 800px;
15 | height: 600px;
16 | border: 1px solid #dfdfdf;
17 | }
18 |
19 | #position {
20 | position: absolute;
21 | right: 4px;
22 | }
23 |
24 | .unselectable {
25 | moz-user-select: -moz-none;
26 | -moz-user-select: none;
27 | -o-user-select: none;
28 | -khtml-user-select: none;
29 | -webkit-user-select: none;
30 | -ms-user-select: none;
31 | user-select: none;
32 | }
33 |
34 | .connector {
35 | cursor: crosshair;
36 | opacity: 0;
37 | }
38 |
39 | .connector.active {
40 | opacity: 1;
41 | fill: white;
42 | stroke: #bbbbbb;
43 | stroke-width: 1px;
44 | }
45 |
46 | .connector:hover {
47 | stroke: red;
48 | }
49 |
50 | #svg .selection {
51 | stroke: lightblue;
52 | fill: lightblue;
53 | fill-opacity: 0.8;
54 | display: none;
55 | }
56 |
57 | #svg .selection.active {
58 | display: block;
59 | }
--------------------------------------------------------------------------------
/src/components/flowchart/index.js:
--------------------------------------------------------------------------------
1 | import FlowChart from './Flowchart';
2 |
3 | FlowChart.install = function(Vue) {
4 | Vue.component(FlowChart.name, FlowChart);
5 | };
6 |
7 | export default FlowChart;
--------------------------------------------------------------------------------
/src/components/flowchart/render.js:
--------------------------------------------------------------------------------
1 | import { select } from "d3-selection";
2 | import { roundTo20 } from "@/utils/math";
3 |
4 | function render(g, node, isSelected) {
5 | node.width = node.width || 120;
6 | node.height = node.height || 60;
7 | let header = null;
8 | let title = null;
9 |
10 | const theme = !node.theme ? {} : node.theme;
11 | const headerBackgroundColor = theme.headerBackgroundColor ? theme.headerBackgroundColor : "#f1f3f4";
12 | const bodyBackgroundColor = theme.bodyBackgroundColor ? theme.bodyBackgroundColor : "white";
13 | const bodyTextColor = theme.bodyTextColor ? theme.bodyTextColor : "black";
14 | const headerTextColor = theme.headerTextColor ? theme.headerTextColor : "black";
15 |
16 | let borderColor = isSelected ? "#666666" : "#bbbbbb";
17 | if (theme.borderColor) {
18 | if (isSelected) {
19 | borderColor = theme.borderColorSelected;
20 | } else {
21 | borderColor = theme.borderColor;
22 | }
23 | }
24 |
25 | if (node.type !== "start" && node.type !== "end") {
26 | // title
27 | header = g
28 | .append("rect")
29 | .attr("x", node.x)
30 | .attr("y", node.y)
31 | .attr("stroke", borderColor)
32 | .attr("class", "title")
33 | .style("height", "20px")
34 | .style("fill", headerBackgroundColor)
35 | .style("stroke-width", "1px")
36 | .style("width", node.width + "px");
37 | title = g
38 | .append("text")
39 | .attr("fill", headerTextColor)
40 | .attr("x", node.x + 4)
41 | .attr("y", node.y + 15)
42 | .attr("class", "unselectable")
43 | .text(() => node.name)
44 | .each(function wrap() {
45 | let self = select(this),
46 | textLength = self.node().getComputedTextLength(),
47 | text = self.text();
48 | while (textLength > node.width - 2 * 4 && text.length > 0) {
49 | text = text.slice(0, -1);
50 | self.text(text + "...");
51 | textLength = self.node().getComputedTextLength();
52 | }
53 | });
54 | }
55 | // body
56 | let body = g.append("rect").attr("class", "body");
57 | body
58 | .style("width", node.width + "px")
59 | .style("fill", bodyBackgroundColor)
60 | .style("stroke-width", "1px");
61 | if (node.type !== "start" && node.type !== "end") {
62 | body.attr("x", node.x).attr("y", node.y + 20);
63 | body.style("height", roundTo20(node.height - 20) + "px");
64 | } else {
65 | body
66 | .attr("x", node.x)
67 | .attr("y", node.y)
68 | .classed(node.type, true)
69 | .attr("rx", 30);
70 | body.style("height", roundTo20(node.height) + "px");
71 | }
72 | body.attr("stroke", borderColor);
73 |
74 | // body text
75 | let text =
76 | node.type === "start"
77 | ? "Start"
78 | : node.type === "end"
79 | ? "End"
80 | : !node.approvers || node.approvers.length === 0
81 | ? "No approver"
82 | : node.approvers.length > 1
83 | ? `${node.approvers[0].name + "..."}`
84 | : node.approvers[0].name;
85 | let bodyTextY;
86 | if (node.type !== "start" && node.type !== "end") {
87 | bodyTextY = node.y + 25 + roundTo20(node.height - 20) / 2;
88 | } else {
89 | bodyTextY = node.y + 5 + roundTo20(node.height) / 2;
90 | }
91 | let content = g
92 | .append("text")
93 | .attr("fill", bodyTextColor)
94 | .attr("x", node.x + node.width / 2)
95 | .attr("y", bodyTextY)
96 | .attr("class", "unselectable")
97 | .attr("text-anchor", "middle")
98 | .text(function () {
99 | return text;
100 | })
101 | .each(function wrap() {
102 | let self = select(this),
103 | textLength = self.node().getComputedTextLength(),
104 | text = self.text();
105 | while (textLength > node.width - 2 * 4 && text.length > 0) {
106 | text = text.slice(0, -1);
107 | self.text(text + "...");
108 | textLength = self.node().getComputedTextLength();
109 | }
110 | });
111 | return { header, title, body, content };
112 | }
113 |
114 | export default render;
115 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Flowchart from './components/flowchart/Flowchart';
2 |
3 | const components = [
4 | Flowchart,
5 | ];
6 |
7 | const install = function(Vue) {
8 | components.map(component => {
9 | Vue.component(component.name, component);
10 | });
11 | };
12 |
13 | if (typeof window !== 'undefined' && window.Vue) {
14 | install(window.Vue);
15 | }
16 |
17 | export default {
18 | install,
19 | Flowchart,
20 | };
21 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './views/App';
3 |
4 | Vue.config.productionTip = false;
5 |
6 | new Vue({
7 | el: '#app',
8 | mounted() {},
9 | components: {
10 | App,
11 | },
12 | });
--------------------------------------------------------------------------------
/src/utils/dom.js:
--------------------------------------------------------------------------------
1 | function ifElementContainChildNode(parentSelector, checkedNode) {
2 | const parentElement = document.querySelector(parentSelector);
3 | const childrenNodes = Array.from(parentElement.childNodes);
4 | return childrenNodes.some((node) => node.contains(checkedNode));
5 | }
6 |
7 | export {
8 | ifElementContainChildNode
9 | };
10 |
--------------------------------------------------------------------------------
/src/utils/math.js:
--------------------------------------------------------------------------------
1 | function distanceOfPointToLine(beginX, beginY, endX, endY, ptX, ptY) {
2 | const k = (endY - beginY || 1) / (endX - beginX || 1);
3 | const b = beginY - k * beginX;
4 | return Math.abs(k * ptX - ptY + b) / Math.sqrt(k * k + 1);
5 | }
6 |
7 | function between(num1, num2, num) {
8 | return (num > num1 && num < num2) || (num > num2 && num < num1);
9 | }
10 |
11 | function approximatelyEquals(n, m) {
12 | return Math.abs(m - n) <= 3;
13 | }
14 |
15 | function getEdgeOfPoints(points) {
16 | let minX = points.reduce((prev, point) => {
17 | return point.x < prev ? point.x : prev;
18 | }, Infinity);
19 | let maxX = points.reduce((prev, point) => {
20 | return point.x > prev ? point.x : prev;
21 | }, 0);
22 | let minY = points.reduce((prev, point) => {
23 | return point.y < prev ? point.y : prev;
24 | }, Infinity);
25 | let maxY = points.reduce((prev, point) => {
26 | return point.y > prev ? point.y : prev;
27 | }, 0);
28 | return {start: {x: minX, y: minY}, end: {x: maxX, y: maxY}};
29 | }
30 |
31 | function pointRectangleIntersection(p, r) {
32 | return p.x > r.start.x && p.x < r.end.x && p.y > r.start.y && p.y < r.end.y;
33 | }
34 |
35 | function roundTo20(number) {
36 | return number < 20 ? 20 : number;
37 | }
38 |
39 | export {
40 | distanceOfPointToLine,
41 | between,
42 | approximatelyEquals,
43 | getEdgeOfPoints,
44 | pointRectangleIntersection,
45 | roundTo20,
46 | };
47 |
--------------------------------------------------------------------------------
/src/utils/svg.js:
--------------------------------------------------------------------------------
1 | import {approximatelyEquals} from './math';
2 |
3 | function lineTo(g, x1, y1, x2, y2, lineWidth, strokeStyle, dash) {
4 | let sta = [x1, y1];
5 | let end = [x2, y2];
6 | let path = g.append('path').
7 | attr('stroke', strokeStyle).
8 | attr('stroke-width', lineWidth).
9 | attr('fill', 'none').
10 | attr('d', `M ${sta[0]} ${sta[1]} L ${end[0]} ${end[1]}`);
11 | if (dash) {
12 | path.style('stroke-dasharray', dash.join(','));
13 | }
14 | return path;
15 | }
16 |
17 | function connect(g, x1, y1, x2, y2, startPosition, endPosition, lineWidth,
18 | strokeStyle, markered) {
19 | if (!endPosition) {
20 | endPosition = x1 > x2 ? 'right' : 'left';
21 | }
22 |
23 | let points = [];
24 | let start = [x1, y1];
25 | let end = [x2, y2];
26 | let centerX = start[0] + (end[0] - start[0]) / 2;
27 | let centerY = start[1] + (end[1] - start[1]) / 2;
28 | let second;
29 | let addVerticalCenterLine = function() {
30 | let third = [centerX, second[1]];
31 | let forth = [centerX, penult[1]];
32 | points.push(third);
33 | points.push(forth);
34 | };
35 | let addHorizontalCenterLine = function() {
36 | let third = [second[0], centerY];
37 | let forth = [penult[0], centerY];
38 | points.push(third);
39 | points.push(forth);
40 | };
41 | let addHorizontalTopLine = function() {
42 | points.push([second[0], start[1] - 50]);
43 | points.push([penult[0], start[1] - 50]);
44 | };
45 | let addHorizontalBottomLine = function() {
46 | points.push([second[0], start[1] + 50]);
47 | points.push([penult[0], start[1] + 50]);
48 | };
49 | let addVerticalRightLine = function() {
50 | points.push([start[0] + 80, second[1]]);
51 | points.push([start[0] + 80, penult[1]]);
52 | };
53 | let addVerticalLeftLine = function() {
54 | points.push([start[0] - 80, second[1]]);
55 | points.push([start[0] - 80, penult[1]]);
56 | };
57 | let addSecondXPenultY = function() {
58 | points.push([second[0], penult[1]]);
59 | };
60 | let addPenultXSecondY = function() {
61 | points.push([penult[0], second[1]]);
62 | };
63 | switch (startPosition) {
64 | case 'left':
65 | second = [start[0] - 20, start[1]];
66 | break;
67 | case 'top':
68 | second = [start[0], start[1] - 20];
69 | break;
70 | case 'bottom':
71 | second = [start[0], start[1] + 20];
72 | break;
73 | default:
74 | second = [start[0] + 20, start[1]];
75 | break;
76 | }
77 | let penult = null;
78 | switch (endPosition) {
79 | case 'right':
80 | penult = [end[0] + 20, end[1]];
81 | break;
82 | case 'top':
83 | penult = [end[0], end[1] - 20];
84 | break;
85 | case 'bottom':
86 | penult = [end[0], end[1] + 20];
87 | break;
88 | default:
89 | penult = [end[0] - 20, end[1]];
90 | break;
91 | }
92 | points.push(start);
93 | points.push(second);
94 | startPosition = startPosition || 'right';
95 | endPosition = endPosition || 'left';
96 | let direction = getDirection(x1, y1, x2, y2);
97 | if (direction.indexOf('r') > -1) {
98 | if (startPosition === 'right' || endPosition === 'left') {
99 | if (second[0] > centerX) {
100 | second[0] = centerX;
101 | }
102 | if (penult[0] < centerX) {
103 | penult[0] = centerX;
104 | }
105 | }
106 | }
107 | if (direction.indexOf('d') > -1) {
108 | if (startPosition === 'bottom' || endPosition === 'top') {
109 | if (second[1] > centerY) {
110 | second[1] = centerY;
111 | }
112 | if (penult[1] < centerY) {
113 | penult[1] = centerY;
114 | }
115 | }
116 | }
117 | if (direction.indexOf('l') > -1) {
118 | if (startPosition === 'left' || endPosition === 'right') {
119 | if (second[0] < centerX) {
120 | second[0] = centerX;
121 | }
122 | if (penult[0] > centerX) {
123 | penult[0] = centerX;
124 | }
125 | }
126 | }
127 | if (direction.indexOf('u') > -1) {
128 | if (startPosition === 'top' || endPosition === 'bottom') {
129 | if (second[1] < centerY) {
130 | second[1] = centerY;
131 | }
132 | if (penult[1] > centerY) {
133 | penult[1] = centerY;
134 | }
135 | }
136 | }
137 | switch (direction) {
138 | case 'lu': {
139 | if (startPosition === 'right') {
140 | switch (endPosition) {
141 | case 'top':
142 | case 'right':
143 | addSecondXPenultY();
144 | break;
145 | default: {
146 | addHorizontalCenterLine();
147 | break;
148 | }
149 | }
150 | } else if (startPosition === 'bottom') {
151 | switch (endPosition) {
152 | case 'top':
153 | addVerticalCenterLine();
154 | break;
155 | default: {
156 | addPenultXSecondY();
157 | break;
158 | }
159 | }
160 | } else if (startPosition === 'top') {
161 | switch (endPosition) {
162 | case 'top':
163 | case 'right':
164 | addSecondXPenultY();
165 | break;
166 | default: {
167 | addHorizontalCenterLine();
168 | break;
169 | }
170 | }
171 | } else {
172 | // startPosition is left
173 | switch (endPosition) {
174 | case 'top':
175 | case 'right':
176 | addVerticalCenterLine();
177 | break;
178 | default: {
179 | addPenultXSecondY();
180 | break;
181 | }
182 | }
183 | }
184 | break;
185 | }
186 | case 'u':
187 | if (startPosition === 'right') {
188 | switch (endPosition) {
189 | case 'right': {
190 | break;
191 | }
192 | case 'top': {
193 | addSecondXPenultY();
194 | break;
195 | }
196 | default: {
197 | addHorizontalCenterLine();
198 | break;
199 | }
200 | }
201 | } else if (startPosition === 'bottom') {
202 | switch (endPosition) {
203 | case 'left':
204 | case 'right':
205 | addPenultXSecondY();
206 | break;
207 | default: {
208 | addVerticalRightLine();
209 | break;
210 | }
211 | }
212 | } else if (startPosition === 'top') {
213 | switch (endPosition) {
214 | case 'left': {
215 | addPenultXSecondY();
216 | break;
217 | }
218 | case 'right': {
219 | addHorizontalCenterLine();
220 | break;
221 | }
222 | case 'top':
223 | addVerticalRightLine();
224 | break;
225 | default: {
226 | break;
227 | }
228 | }
229 | } else {
230 | // left
231 | switch (endPosition) {
232 | case 'left':
233 | case 'right':
234 | break;
235 | default: {
236 | points.push([second[0], penult[1]]);
237 | break;
238 | }
239 | }
240 | }
241 | break;
242 | case 'ru':
243 | if (startPosition === 'right') {
244 | switch (endPosition) {
245 | case 'left': {
246 | addVerticalCenterLine();
247 | break;
248 | }
249 | case 'top': {
250 | addSecondXPenultY();
251 | break;
252 | }
253 | default: {
254 | addPenultXSecondY();
255 | break;
256 | }
257 | }
258 | } else if (startPosition === 'bottom') {
259 | switch (endPosition) {
260 | case 'top': {
261 | addVerticalCenterLine();
262 | break;
263 | }
264 | default: {
265 | addPenultXSecondY();
266 | break;
267 | }
268 | }
269 | } else if (startPosition === 'top') {
270 | switch (endPosition) {
271 | case 'right': {
272 | addVerticalCenterLine();
273 | break;
274 | }
275 | default: {
276 | addSecondXPenultY();
277 | break;
278 | }
279 | }
280 | } else {
281 | // left
282 | switch (endPosition) {
283 | case 'left':
284 | case 'top':
285 | addSecondXPenultY();
286 | break;
287 | default: {
288 | addHorizontalCenterLine();
289 | break;
290 | }
291 | }
292 | }
293 | break;
294 | case 'l':
295 | if (startPosition === 'right') {
296 | switch (endPosition) {
297 | case 'left':
298 | case 'right':
299 | case 'top':
300 | addHorizontalTopLine();
301 | break;
302 | default: {
303 | addHorizontalBottomLine();
304 | break;
305 | }
306 | }
307 | } else if (startPosition === 'bottom') {
308 | switch (endPosition) {
309 | case 'left': {
310 | addHorizontalBottomLine();
311 | break;
312 | }
313 | case 'right': {
314 | addSecondXPenultY();
315 | break;
316 | }
317 | case 'top': {
318 | addVerticalCenterLine();
319 | break;
320 | }
321 | default: {
322 | break;
323 | }
324 | }
325 | } else if (startPosition === 'top') {
326 | switch (endPosition) {
327 | case 'left': {
328 | addHorizontalTopLine();
329 | break;
330 | }
331 | case 'right': {
332 | addSecondXPenultY();
333 | break;
334 | }
335 | case 'top': {
336 | break;
337 | }
338 | default: {
339 | addVerticalCenterLine();
340 | break;
341 | }
342 | }
343 | } else {
344 | // left
345 | switch (endPosition) {
346 | case 'left': {
347 | addHorizontalTopLine();
348 | break;
349 | }
350 | case 'right': {
351 | break;
352 | }
353 | default: {
354 | addSecondXPenultY();
355 | break;
356 | }
357 | }
358 | }
359 | break;
360 | case 'r':
361 | if (startPosition === 'right') {
362 | switch (endPosition) {
363 | case 'left': {
364 | break;
365 | }
366 | case 'right': {
367 | addHorizontalTopLine();
368 | break;
369 | }
370 | default: {
371 | addSecondXPenultY();
372 | break;
373 | }
374 | }
375 | } else if (startPosition === 'bottom') {
376 | switch (endPosition) {
377 | case 'left': {
378 | addSecondXPenultY();
379 | break;
380 | }
381 | case 'right': {
382 | addHorizontalBottomLine();
383 | break;
384 | }
385 | case 'top': {
386 | addVerticalCenterLine();
387 | break;
388 | }
389 | default: {
390 | break;
391 | }
392 | }
393 | } else if (startPosition === 'top') {
394 | switch (endPosition) {
395 | case 'left': {
396 | addPenultXSecondY();
397 | break;
398 | }
399 | case 'right': {
400 | addHorizontalTopLine();
401 | break;
402 | }
403 | case 'top': {
404 | break;
405 | }
406 | default: {
407 | addVerticalCenterLine();
408 | break;
409 | }
410 | }
411 | } else {
412 | // left
413 | switch (endPosition) {
414 | case 'left':
415 | case 'right':
416 | case 'top':
417 | addHorizontalTopLine();
418 | break;
419 | default: {
420 | addHorizontalBottomLine();
421 | break;
422 | }
423 | }
424 | }
425 | break;
426 | case 'ld':
427 | if (startPosition === 'right') {
428 | switch (endPosition) {
429 | case 'left': {
430 | addHorizontalCenterLine();
431 | break;
432 | }
433 | default: {
434 | addSecondXPenultY();
435 | break;
436 | }
437 | }
438 | } else if (startPosition === 'bottom') {
439 | switch (endPosition) {
440 | case 'left': {
441 | addPenultXSecondY();
442 | break;
443 | }
444 | case 'top': {
445 | addHorizontalCenterLine();
446 | break;
447 | }
448 | default: {
449 | addSecondXPenultY();
450 | break;
451 | }
452 | }
453 | } else if (startPosition === 'top') {
454 | switch (endPosition) {
455 | case 'left':
456 | case 'right':
457 | case 'top':
458 | addPenultXSecondY();
459 | break;
460 | default: {
461 | addVerticalCenterLine();
462 | break;
463 | }
464 | }
465 | } else {
466 | // left
467 | switch (endPosition) {
468 | case 'left':
469 | case 'top':
470 | addPenultXSecondY();
471 | break;
472 | case 'right': {
473 | addVerticalCenterLine();
474 | break;
475 | }
476 | default: {
477 | addSecondXPenultY();
478 | break;
479 | }
480 | }
481 | }
482 | break;
483 | case 'd':
484 | if (startPosition === 'right') {
485 | switch (endPosition) {
486 | case 'left': {
487 | addHorizontalCenterLine();
488 | break;
489 | }
490 | case 'right': {
491 | addPenultXSecondY();
492 | break;
493 | }
494 | case 'top': {
495 | addSecondXPenultY();
496 | break;
497 | }
498 | default: {
499 | addVerticalRightLine();
500 | break;
501 | }
502 | }
503 | } else if (startPosition === 'bottom') {
504 | switch (endPosition) {
505 | case 'left':
506 | case 'right':
507 | addPenultXSecondY();
508 | break;
509 | case 'top': {
510 | break;
511 | }
512 | default: {
513 | addVerticalRightLine();
514 | break;
515 | }
516 | }
517 | } else if (startPosition === 'top') {
518 | switch (endPosition) {
519 | case 'left': {
520 | addVerticalLeftLine();
521 | break;
522 | }
523 | default: {
524 | addVerticalRightLine();
525 | break;
526 | }
527 | }
528 | } else {
529 | // left
530 | switch (endPosition) {
531 | case 'left': {
532 | break;
533 | }
534 | case 'right': {
535 | addHorizontalCenterLine();
536 | break;
537 | }
538 | case 'top': {
539 | addSecondXPenultY();
540 | break;
541 | }
542 | default: {
543 | addVerticalLeftLine();
544 | break;
545 | }
546 | }
547 | }
548 | break;
549 | case 'rd': {
550 | if (startPosition === 'right' && endPosition === 'left') {
551 | addVerticalCenterLine();
552 | } else if (startPosition === 'right' && endPosition === 'bottom') {
553 | addSecondXPenultY();
554 | } else if (
555 | (startPosition === 'right' && endPosition === 'top') ||
556 | (startPosition === 'right' && endPosition === 'right')
557 | ) {
558 | addPenultXSecondY();
559 | } else if (startPosition === 'bottom' && endPosition === 'left') {
560 | addSecondXPenultY();
561 | } else if (startPosition === 'bottom' && endPosition === 'right') {
562 | addPenultXSecondY();
563 | } else if (startPosition === 'bottom' && endPosition === 'top') {
564 | addHorizontalCenterLine();
565 | } else if (startPosition === 'bottom' && endPosition === 'bottom') {
566 | addSecondXPenultY();
567 | } else if (startPosition === 'top' && endPosition === 'left') {
568 | addPenultXSecondY();
569 | } else if (startPosition === 'top' && endPosition === 'right') {
570 | addPenultXSecondY();
571 | } else if (startPosition === 'top' && endPosition === 'top') {
572 | addPenultXSecondY();
573 | } else if (startPosition === 'top' && endPosition === 'bottom') {
574 | addVerticalCenterLine();
575 | } else if (startPosition === 'left' && endPosition === 'left') {
576 | addSecondXPenultY();
577 | } else if (startPosition === 'left' && endPosition === 'right') {
578 | addHorizontalCenterLine();
579 | } else if (startPosition === 'left' && endPosition === 'top') {
580 | addHorizontalCenterLine();
581 | } else if (startPosition === 'left' && endPosition === 'bottom') {
582 | addSecondXPenultY();
583 | }
584 | break;
585 | }
586 | }
587 | points.push(penult);
588 | points.push(end);
589 |
590 | let lines = [];
591 | let paths = [];
592 | for (let i = 0; i < points.length; i++) {
593 | let source = points[i];
594 | let destination = points[i + 1];
595 | lines.push({
596 | sourceX: source[0],
597 | sourceY: source[1],
598 | destinationX: destination[0],
599 | destinationY: destination[1],
600 | });
601 | let finish = i === points.length - 2;
602 | if (finish && markered) {
603 | let path = arrowTo(g, source[0], source[1], destination[0],
604 | destination[1], lineWidth, strokeStyle);
605 | paths.push(path);
606 | break;
607 | } else {
608 | let path = lineTo(g, source[0], source[1], destination[0], destination[1],
609 | lineWidth, strokeStyle);
610 | paths.push(path);
611 | }
612 | if (finish) {
613 | break;
614 | }
615 | }
616 | return {lines, paths};
617 | }
618 |
619 | function arrowTo(g, x1, y1, x2, y2, lineWidth, strokeStyle) {
620 | let path = lineTo(g, x1, y1, x2, y2, lineWidth, strokeStyle);
621 | const id = 'arrow' + strokeStyle.replace('#', '');
622 | g.append('marker').
623 | attr('id', id).
624 | attr('markerUnits', 'strokeWidth').
625 | attr('viewBox', '0 0 12 12').
626 | attr('refX', 9).
627 | attr('refY', 6).
628 | attr('markerWidth', 12).
629 | attr('markerHeight', 12).
630 | attr('orient', 'auto').
631 | append('path').
632 | attr('d', 'M2,2 L10,6 L2,10 L6,6 L2,2').
633 | attr('fill', strokeStyle);
634 | path.attr('marker-end', 'url(#' + id + ')');
635 | return path;
636 | }
637 |
638 | function getDirection(x1, y1, x2, y2) {
639 | // Use approximatelyEquals to fix the problem of css position presicion
640 | if (x2 < x1 && approximatelyEquals(y2, y1)) {
641 | return 'l';
642 | }
643 | if (x2 > x1 && approximatelyEquals(y2, y1)) {
644 | return 'r';
645 | }
646 | if (approximatelyEquals(x2, x1) && y2 < y1) {
647 | return 'u';
648 | }
649 | if (approximatelyEquals(x2, x1) && y2 > y1) {
650 | return 'd';
651 | }
652 | if (x2 < x1 && y2 < y1) {
653 | return 'lu';
654 | }
655 | if (x2 > x1 && y2 < y1) {
656 | return 'ru';
657 | }
658 | if (x2 < x1 && y2 > y1) {
659 | return 'ld';
660 | }
661 | return 'rd';
662 | }
663 |
664 | export {
665 | arrowTo,
666 | lineTo,
667 | getDirection,
668 | connect,
669 | };
670 |
--------------------------------------------------------------------------------
/src/views/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Flowchart Vue
4 |
5 | Flowchart & Flowchart designer component for Vue.js.
6 |
7 |
8 |
22 |
23 |
26 |
27 |
28 |
42 |
43 |
47 |
52 |
53 |
54 |
55 |
187 |
210 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | runtimeCompiler: true,
3 | css: {
4 | loaderOptions: {
5 | less: {
6 | modifyVars: {},
7 | },
8 | postcss: {
9 | plugins: [],
10 | },
11 | },
12 | extract: false,
13 | },
14 | baseUrl: process.env.NODE_ENV === "production" ? "/flowchart-vue" : "/"
15 | };
16 |
--------------------------------------------------------------------------------