UNPKG

arrowjoin

Version:

ArrowJoin is a creative and functional React library that effortlessly connects two React components with a sleek arrow.

2 lines (1 loc) 16.4 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("lodash"),r=require("prop-types");function n(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=n(e);const a=e=>{let t;return t="string"==typeof e?document.getElementById(e):e?.current,t},s=(e,t)=>{let r,n=1/0,o=1/0;return e.forEach((e=>{t.forEach((t=>{var a,s;a=e,s=t,o=Math.sqrt((a.x-s.x)**2+(a.y-s.y)**2),o<n&&(n=o,r={chosenStart:e,chosenEnd:t})}))})),r},l=e=>{if(!e)return{x:0,y:0,right:0,bottom:0};const t=e.getBoundingClientRect();return{x:t.left,y:t.top,right:t.right,bottom:t.bottom}},i=["middle","left","right","top","bottom","auto"],c=["smooth","grid","straight"],u={arrow1:{svgElem:o.createElement("path",{d:"M 0 0 L 1 0.5 L 0 1 L 0.25 0.5 z"}),offsetForward:.25},heart:{svgElem:o.createElement("path",{d:"M 0,0.25 A 0.125,0.125 0,0,1 0.5,0.25 A 0.125,0.125 0,0,1 1,0.25 Q 1,0.625 0.5,1 Q 0,0.625 0,0.25 z"}),offsetForward:.1},circle:{svgElem:o.createElement("circle",{r:.5,cx:.5,cy:.5}),offsetForward:0}},f=Object.keys(u),d=e=>{let t=(Array.isArray(e)?e:[e]).map((e=>"string"==typeof e?{position:e}:e));t=t.filter((e=>i.includes(e.position))),0==t.length&&(t=[{position:"auto"}]);let r=t.filter((e=>"auto"===e.position));r.length>0&&(t=t.filter((e=>"auto"!==e.position)),t.push(...r.flatMap((e=>["left","right","top","bottom"].map((t=>({...e,position:t})))))));let n=t.map((e=>{if("object"==typeof e){let t=e;return t.position||(t.position="auto"),t.offset||(t.offset={x:0,y:0}),t.offset.y||(t.offset.y=0),t.offset.x||(t.offset.x=0),t}return e}));return n},p=e=>("string"==typeof e&&(e in u?e=u[e]:(console.warn(`'${e}' is not supported arrow shape. the supported arrow shapes is one of ${f}.\n reverting to default shape.`),e=u.arrow1)),void 0===e?.offsetForward&&(e.offsetForward=.25),void 0===e?.svgElem&&(e.svgElem="path"),e),h=e=>{let t=(e=>{if("string"!=typeof e)return{abs:0,relative:.5};let t=e.split("%"),r=0,n=0;if(1==t.length){let e=parseFloat(t[0]);if(!isNaN(e))return r=e,{abs:r,relative:0}}else if(2==t.length){let[e,o]=[parseFloat(t[0]),parseFloat(t[1])];if(isNaN(e)||(n=e/100),isNaN(o)||(r=o),!isNaN(e)||!isNaN(o))return{abs:r,relative:n}}})(e);return t||(t={relative:.5,abs:0}),t},m=(e,t)=>(t&&(t.current=!0),e),y=e=>e,x=(e,t,r)=>m(e,r),b=(e,t,r)=>m(Number(e),r),g={start:e=>a(e),end:e=>a(e),startAnchor:(e,t,r)=>m(d(e),r),endAnchor:(e,t,r)=>m(d(e),r),labels:t=>(t=>{let r={start:null,middle:null,end:null};if(t)if("string"==typeof t||e.isValidElement(t))r.middle=t;else for(let e in t)r[e]=t[e];return r})(t),color:y,lineColor:(e,t)=>e||t.color,headColor:(e,t)=>e||t.color,tailColor:(e,t)=>e||t.color,strokeWidth:b,showHead:x,headSize:b,showTail:x,tailSize:b,path:x,curveness:b,gridBreak:(e,t,r)=>m(h(e),r),dashness:(e,t)=>((e,t)=>{let r,n=0,o=0;return"object"==typeof e?(n=e.strokeLen||2*t.strokeWidth,o=e.strokeLen?e.nonStrokeLen:t.strokeWidth,r=e.animation?e.animation:null):"boolean"==typeof e&&e&&(n=2*t.strokeWidth,o=t.strokeWidth,r=null),{strokeLen:n,nonStrokeLen:o,animation:r,animDirection:1}})(e,t),headShape:e=>p(e),tailShape:e=>p(e),showXarrow:y,animateDrawing:y,zIndex:e=>Number(e),passProps:y,className:null,onClick:null,arrowBodyProps:x,arrowHeadProps:x,arrowTailProps:x,SVGcanvasProps:x,divContainerProps:x,divContainerStyle:x,SVGcanvasStyle:x,_extendSVGcanvas:x,_debug:x,_cpx1Offset:x,_cpy1Offset:x,_cpx2Offset:x,_cpy2Offset:x},v={};for(let e in g)v[e]=[e];for(let e of["lineColor","headColor","tailColor"])v[e].push("color");const w={start:null,end:null,startAnchor:"auto",endAnchor:"auto",labels:null,color:"CornflowerBlue",lineColor:null,headColor:null,tailColor:null,strokeWidth:4,showHead:!0,headSize:6,showTail:!1,tailSize:6,path:"smooth",curveness:.8,gridBreak:"50%",dashness:!1,headShape:"arrow1",tailShape:"arrow1",showXarrow:!0,animateDrawing:!1,zIndex:0,passProps:{},arrowBodyProps:{},arrowHeadProps:{},arrowTailProps:{},SVGcanvasProps:{},divContainerProps:{},divContainerStyle:{},SVGcanvasStyle:{},_extendSVGcanvas:0,className:null,onClick:null,_debug:!1,_cpx1Offset:0,_cpy1Offset:0,_cpx2Offset:0,_cpy2Offset:0};let E={};E=((e,t)=>{for(let[r,n]of Object.entries(e))t[r]=g?.[r]?.(n,t);return t})(w,E),console.log("initialParsedProps",E);const S={startPos:{x:0,y:0,right:0,bottom:0},endPos:{x:0,y:0,right:0,bottom:0}};function P(r){const n=e.useRef();var o,a;return o=r,a=n.current,t.isEqual(o,a)||(n.current=r),n.current}function O(t,r){e.useLayoutEffect(t,r.map(P))}const k=e.createContext(null),C=e.createContext(null),L={};let R=0;const M=({children:t,instanceCount:r})=>{const[,n]=e.useState({}),o=()=>n({});return e.useEffect((()=>{r.current=R,L[r.current]=o}),[]),e.createElement(C.Provider,{value:o},t)},$=({children:t,instanceCount:r})=>e.createElement(k.Provider,{value:L[r.current]},t),T=r.oneOf(i),N=r.exact({position:T.isRequired,offset:r.exact({x:r.number,y:r.number}).isRequired}),_=r.oneOfType([T,N]),z=r.oneOfType([_,r.arrayOf(_)]),D=r.oneOfType([r.string,r.exact({current:r.any})]),j=r.oneOfType([r.element,r.string]),A=r.exact({start:j,middle:j,end:j}),F=r.oneOf(Object.keys(u)),H=r.any,q=r.oneOfType([F,r.exact({svgElem:H,offsetForward:r.number}).isRequired]),B={start:D.isRequired,end:D.isRequired,startAnchor:z,endAnchor:z,labels:r.oneOfType([j,A]),color:r.string,lineColor:r.string,showHead:r.bool,headColor:r.string,headSize:r.number,tailSize:r.number,tailColor:r.string,strokeWidth:r.number,showTail:r.bool,path:r.oneOf(c),showXarrow:r.bool,curveness:r.number,gridBreak:r.string,dashness:r.oneOfType([r.bool,r.object]),headShape:q,tailShape:q,animateDrawing:r.oneOfType([r.bool,r.number]),zIndex:r.number,passProps:r.object,arrowBodyProps:r.object,arrowHeadProps:r.object,arrowTailProps:r.object,SVGcanvasProps:r.object,divContainerProps:r.object,_extendSVGcanvas:r.number,_debug:r.bool,_cpx1Offset:r.number,_cpy1Offset:r.number,_cpx2Offset:r.number,_cpy2Offset:r.number},V=(e,t)=>e.map((e=>{let r=(n=t.right-t.x,o=t.bottom-t.y,{middle:{x:.5*n,y:.5*o},left:{x:0,y:.5*o},right:{x:n,y:.5*o},top:{x:.5*n,y:0},bottom:{x:.5*n,y:o}});var n,o;let{x:a,y:s}=r[e.position];return{x:t.x+a+e.offset.x,y:t.y+s+e.offset.y,anchor:e}})),G=(e,t,r,n)=>o=>(1-o)**3*e+3*(1-o)**2*o*t+3*(1-o)*o**2*r+o**3*n,W=(e,t,r,n)=>{const o=G(e,t,r,n),a=-6*e+12*t-6*r,s=(-6*e+12*t-6*r)**2-4*(3*t-3*e)*(-3*e+9*t-9*r+3*n),l=2*(-3*e+9*t-9*r+3*n);return[o((a+Math.sqrt(s))/l),o((a-Math.sqrt(s))/l)]},I=(e,r)=>{let[n,o]=e,{startAnchor:a,endAnchor:l,strokeWidth:i,showHead:u,headSize:f,showTail:d,tailSize:p,path:h,curveness:m,gridBreak:y,headShape:x,tailShape:b,_extendSVGcanvas:g,_cpx1Offset:v,_cpy1Offset:w,_cpx2Offset:E,_cpy2Offset:S}=n;const{startPos:P,endPos:O}=o,{svgRef:k,lineRef:C}=r.current;let L=0,R=0,M=V(a,P),$=V(l,O),{chosenStart:T,chosenEnd:N}=s(M,$),_=T.anchor.position,z=N.anchor.position,D=t.pick(T,["x","y"]),j=t.pick(N,["x","y"]),A=(e=>{if(!e.current)return{x:0,y:0};let{left:t,top:r}=e.current.getBoundingClientRect(),n=getComputedStyle(e.current);return{x:t-Number(n.left.slice(0,-2)),y:r-Number(n.top.slice(0,-2))}})(k),F=Math.min(D.x,j.x)-A.x,H=Math.min(D.y,j.y)-A.y,q=j.x-D.x,B=j.y-D.y,I=Math.abs(j.x-D.x),X=Math.abs(j.y-D.y),U=q>0?1:-1,Q=B>0?1:-1,[J,K]=[x.offsetForward,b.offsetForward],Y=f*i,Z=p*i,ee=0,te=0,re=0,ne=0,oe=Y*J,ae=Z*K,se=Number(m);c.includes(h)||(h="smooth"),"straight"===h&&(se=0,h="smooth");let le=i+i*(f>p?f:p)/2,ie=le,ce=le,ue=le,fe=le;ce+=Number(g),ie+=Number(g),ue+=Number(g),fe+=Number(g);let de=0,pe=I,he=0,me=X;if(q<0&&([de,pe]=[pe,de]),B<0&&([he,me]=[me,he]),0===se){let e=Math.atan(X/I);u&&(pe-=Y*(1-J)*U*Math.cos(e),me-=Y*(1-J)*Q*Math.sin(e),e*=Q,U<0&&(e=(Math.PI-e*U)*U),ee=Math.cos(e)*oe-Math.sin(e)*Y/2,te=Math.cos(e)*Y/2+Math.sin(e)*oe,L=180*e/Math.PI);let t=Math.atan(X/I);d&&(de+=Z*(1-K)*U*Math.cos(t),he+=Z*(1-K)*Q*Math.sin(t),t*=-Q,U>0&&(t=(Math.PI-t*U)*U),re=Math.cos(t)*ae-Math.sin(t)*Z/2,ne=Math.cos(t)*Z/2+Math.sin(t)*ae,R=180*t/Math.PI)}else"middle"===z&&(z=I>X?U?"left":"right":Q?"top":"bottom"),u&&(["left","right"].includes(z)?(ee+=oe*U,pe-=Y*(1-J)*U,te+=Y*U/2,"left"===z?(L=0,U<0&&(L+=180)):(L=180,U>0&&(L+=180))):["top","bottom"].includes(z)&&(ee+=Y*-Q/2,te+=oe*Q,me-=Y*Q-te,"top"===z?(L=270,Q>0&&(L+=180)):(L=90,Q<0&&(L+=180))));d&&0!==se&&(["left","right"].includes(_)?(re+=ae*-U,de+=Z*U+re,ne+=-Z*U/2,"left"===_?(R=180,U<0&&(R+=180)):(R=0,U>0&&(R+=180))):["top","bottom"].includes(_)&&(ne+=ae*-Q,he+=Z*Q+ne,re+=Z*Q/2,"top"===_?(R=90,Q>0&&(R+=180)):(R=270,Q<0&&(R+=180))));let ye={x:ee,y:te},xe={x:re,y:ne},be=de,ge=he,ve=pe,we=me,Ee={};"smooth"===h?Ee={hh:()=>{be+=I*se*U,ve-=I*se*U},vv:()=>{ge+=X*se*Q,we-=X*se*Q},hv:()=>{be+=I*se*U,we-=X*se*Q},vh:()=>{ge+=X*se*Q,ve-=I*se*U}}:"grid"===h&&(Ee={hh:()=>{be+=(I*y.relative+y.abs)*U,ve-=(I*(1-y.relative)-y.abs)*U,u&&(be-=Y*(1-J)/2*U,ve+=Y*(1-J)/2*U),d&&(be-=Z*(1-K)/2*U,ve+=Z*(1-K)/2*U)},vv:()=>{ge+=(X*y.relative+y.abs)*Q,we-=(X*(1-y.relative)-y.abs)*Q,u&&(ge-=Y*(1-J)/2*Q,we+=Y*(1-J)/2*Q),d&&(ge-=Z*(1-K)/2*Q,we+=Z*(1-K)/2*Q)},hv:()=>{be=pe},vh:()=>{ge=me}});let Se="";["left","right"].includes(_)?Se+="h":["bottom","top"].includes(_)?Se+="v":"middle"===_&&(Se+="m"),["left","right"].includes(z)?Se+="h":["bottom","top"].includes(z)?Se+="v":"middle"===z&&(Se+="m"),Se=I>X?Se.replace(/m/g,"h"):Se.replace(/m/g,"v"),Ee[Se](),be+=v,ge+=w,ve+=E,we+=S;const[Pe,Oe]=W(de,be,ve,pe),[ke,Ce]=W(he,ge,we,me);Pe<0&&(ce+=-Pe),Oe>I&&(ie+=Oe-I),ke<0&&(ue+=-ke),Ce>X&&(fe+=Ce-X),"grid"===h&&(ce+=le,ie+=le,ue+=le,fe+=le),de+=ce,pe+=ce,he+=ue,me+=ue,be+=ce,ve+=ce,ge+=ue,we+=ue;const Le=I+ce+ie,Re=X+ue+fe;F-=ce,H-=ue;const Me=G(de,be,ve,pe),$e=G(he,ge,we,me),Te={x:Me(.01),y:$e(.01)},Ne={x:Me(.5),y:$e(.5)},_e={x:Me(.99),y:$e(.99)};let ze;return"grid"===h?ze=`M ${de} ${he} L ${be} ${ge} L ${ve} ${we} ${pe} ${me}`:"smooth"===h&&(ze=`M ${de} ${he} C ${be} ${ge}, ${ve} ${we}, ${pe} ${me}`),{cx0:F,cy0:H,x1:de,x2:pe,y1:he,y2:me,cw:Le,ch:Re,cpx1:be,cpy1:ge,cpx2:ve,cpy2:we,dx:q,dy:B,absDx:I,absDy:X,headOrient:L,tailOrient:R,labelStartPos:Te,labelMiddlePos:Ne,labelEndPos:_e,excLeft:ce,excRight:ie,excUp:ue,excDown:fe,headOffset:oe,arrowHeadOffset:ye,arrowTailOffset:xe,startPoints:M,endPoints:$,mainDivPos:A,xSign:U,ySign:Q,lineLength:C.current?.getTotalLength()??0,fHeadSize:Y,fTailSize:Z,arrowPath:ze}},X=t=>{const r=e.useRef({svgRef:e.useRef(null),lineRef:e.useRef(null),headRef:e.useRef(null),tailRef:e.useRef(null),lineDrawAnimRef:e.useRef(null),lineDashAnimRef:e.useRef(null),headOpacityAnimRef:e.useRef(null)}),{svgRef:n,lineRef:o,headRef:a,lineDrawAnimRef:s,lineDashAnimRef:i,headOpacityAnimRef:c}=r.current;e.useContext(C);const u=(t=>{const[r,n]=e.useState(E),o=e.useRef(!1);r.shouldUpdatePosition=o;const a={...w,...t};for(let s in w)e.useLayoutEffect((()=>{r[s]=g?.[s]?.(a[s],r,o),n({...r})}),v[s].map((e=>t[e])));const[s,i]=e.useState(S),c=l(r.start);O((()=>{s.startPos=c,o.current=!0,i({...s})}),[c]);const u=l(r.end);return O((()=>{s.endPos=u,o.current=!0,i({...s})}),[u]),e.useLayoutEffect((()=>{o.current=!0,i({...s})}),[r.headShape.svgElem,r.tailShape.svgElem]),[r,s]})(t,r.current),[f]=u;let{labels:d,lineColor:p,headColor:h,tailColor:m,strokeWidth:y,showHead:x,showTail:b,dashness:P,headShape:k,tailShape:L,showXarrow:R,animateDrawing:M,zIndex:$,passProps:T,arrowBodyProps:N,arrowHeadProps:_,arrowTailProps:z,SVGcanvasProps:D,divContainerProps:j,divContainerStyle:A,SVGcanvasStyle:F,_debug:H,shouldUpdatePosition:q}=f;M=t.animateDrawing;const[B,V]=e.useState(!M),[,G]=e.useState({}),W=()=>G({}),[X,U]=e.useState({cx0:0,cy0:0,cw:0,ch:0,x1:0,y1:0,x2:0,y2:0,dx:0,dy:0,absDx:0,absDy:0,cpx1:0,cpy1:0,cpx2:0,cpy2:0,headOrient:0,tailOrient:0,arrowHeadOffset:{x:0,y:0},arrowTailOffset:{x:0,y:0},headOffset:0,excRight:0,excLeft:0,excUp:0,excDown:0,startPoints:[],endPoints:[],mainDivPos:{x:0,y:0},xSign:1,ySign:1,lineLength:0,fHeadSize:1,fTailSize:1,arrowPath:"",labelStartPos:{x:0,y:0},labelMiddlePos:{x:0,y:0},labelEndPos:{x:0,y:0}});e.useLayoutEffect((()=>{if(q.current){const e=I(u,r);U(e),q.current=!1}}));const Q=X.x2-X.arrowHeadOffset.x,J=X.y2-X.arrowHeadOffset.y,K=X.x1-X.arrowTailOffset.x,Y=X.y1-X.arrowTailOffset.y;let Z=P.strokeLen+P.nonStrokeLen,ee=1;P.animation<0&&(P.animation*=-1,ee=-1);let te,re,ne,oe,ae=0;return M&&0==B?("boolean"==typeof M&&(M=1),re=M+"s",te=X.lineLength,oe=X.lineLength,ne=1,M<0&&([oe,ae]=[ae,oe],re=-1*M+"s")):(te=`${P.strokeLen} ${P.nonStrokeLen}`,re=1/P.animation+"s",oe=Z*ee,ne="indefinite",ae=0),e.useLayoutEffect((()=>{o.current&&U((e=>({...e,lineLength:o.current?.getTotalLength()??0})))}),[o.current]),e.useEffect((()=>{const e=(()=>{window.addEventListener("resize",W);const e=()=>{V(!0),c.current?.beginElement(),i.current?.beginElement()},t=()=>a.current.style.opacity="0";return s.current&&a.current&&(s.current.addEventListener("endEvent",e),s.current.addEventListener("beginEvent",t)),()=>{window.removeEventListener("resize",W),s.current&&(s.current.removeEventListener("endEvent",e),a.current&&s.current.removeEventListener("beginEvent",t))}})();return()=>{V(!1),e()}}),[R]),e.createElement("div",Object.assign({},j,{style:{position:"absolute",zIndex:$,...A}}),R?e.createElement(e.Fragment,null,e.createElement("svg",Object.assign({ref:n,width:X.cw,height:X.ch,onClick:()=>{t.onClick&&t.onClick(o)},style:{position:"absolute",cursor:"pointer",left:X.cx0,top:X.cy0,pointerEvents:"none",border:H?"1px dashed yellow":null,...F},overflow:"auto"},D),e.createElement("path",Object.assign({ref:o,d:X.arrowPath,stroke:p,strokeDasharray:te,className:t.className,strokeWidth:y,fill:"transparent",pointerEvents:"visibleStroke"},T,N,{onClick:()=>{t.onClick&&t.onClick(o)}}),e.createElement(e.Fragment,null,B?e.createElement(e.Fragment,null,P.animation?e.createElement("animate",{ref:i,attributeName:"stroke-dashoffset",values:Z*ee+";0",dur:1/P.animation+"s",repeatCount:"indefinite"}):null):e.createElement(e.Fragment,null,M?e.createElement("animate",{ref:s,id:"svgEndAnimate",attributeName:"stroke-dashoffset",values:`${oe};${ae}`,dur:re,repeatCount:ne}):null))),b?e.createElement("g",Object.assign({fill:m,pointerEvents:"auto",transform:`translate(${K},${Y}) rotate(${X.tailOrient}) scale(${X.fTailSize})`},T,z),L.svgElem):null,x?e.createElement("g",Object.assign({ref:a,fill:h,pointerEvents:"auto",transform:`translate(${Q},${J}) rotate(${X.headOrient}) scale(${X.fHeadSize})`,opacity:M&&!B?0:1},T,_),e.createElement("animate",{ref:c,dur:"0.4",attributeName:"opacity",from:"0",to:"1",begin:"indefinite",repeatCount:"0",fill:"freeze"}),k.svgElem):null,H?e.createElement(e.Fragment,null,e.createElement("circle",{r:"5",cx:X.cpx1,cy:X.cpy1,fill:"green"}),e.createElement("circle",{r:"5",cx:X.cpx2,cy:X.cpy2,fill:"blue"}),e.createElement("rect",{x:X.excLeft,y:X.excUp,width:X.absDx,height:X.absDy,fill:"none",stroke:"pink",strokeWidth:"2px"})):null),d.start?e.createElement("div",{style:{transform:X.dx<0?"translate(-100% , -50%)":"translate(-0% , -50%)",width:"max-content",position:"absolute",left:X.cx0+X.labelStartPos.x,top:X.cy0+X.labelStartPos.y-y-5}},d.start):null,d.middle?e.createElement("div",{style:{display:"table",width:"max-content",transform:"translate(-50% , -50%)",position:"absolute",left:X.cx0+X.labelMiddlePos.x,top:X.cy0+X.labelMiddlePos.y}},d.middle):null,d.end?e.createElement("div",{style:{transform:X.dx>0?"translate(-100% , -50%)":"translate(-0% , -50%)",width:"max-content",position:"absolute",left:X.cx0+X.labelEndPos.x,top:X.cy0+X.labelEndPos.y+y+5}},d.end):null,H?e.createElement(e.Fragment,null,[...X.startPoints,...X.endPoints].map(((t,r)=>e.createElement("div",{key:r,style:{background:"gray",opacity:.5,borderRadius:"50%",transform:"translate(-50%, -50%)",height:5,width:5,position:"absolute",left:t.x-X.mainDivPos.x,top:t.y-X.mainDivPos.y}})))):null):null)};X.propTypes=B;const U=()=>{};exports.Xwrapper=({children:t})=>{const r=e.useRef(R),[,n]=e.useState({});return e.useEffect((()=>(R++,n({}),()=>{delete L[r.current]})),[]),e.createElement($,{instanceCount:r},e.createElement(M,{instanceCount:r},t))},exports.arrowShapes=u,exports.cAnchorEdge=i,exports.cArrowShapes=f,exports.cPaths=c,exports.cSvgElems=["circle","ellipse","line","path","polygon","polyline","rect"],exports.default=X,exports.useXarrow=()=>{const[,t]=e.useState({});let r=e.useContext(k);return r||(r=U),e.useLayoutEffect((()=>{r()})),()=>t({})};