json-canvas-viewer 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +105 -41
  2. package/dist/bridges.cjs +2 -0
  3. package/dist/bridges.cjs.map +1 -0
  4. package/dist/bridges.js +2 -0
  5. package/dist/bridges.js.map +1 -0
  6. package/dist/chimp.cjs +1 -0
  7. package/dist/chimp.js +1 -0
  8. package/dist/controller--Q72jFEw.cjs +2 -0
  9. package/dist/controller--Q72jFEw.cjs.map +1 -0
  10. package/dist/controller-siZ5v-SD.js +2 -0
  11. package/dist/controller-siZ5v-SD.js.map +1 -0
  12. package/dist/dev.cjs +2 -0
  13. package/dist/dev.cjs.map +1 -0
  14. package/dist/dev.js +2 -0
  15. package/dist/dev.js.map +1 -0
  16. package/dist/index-BSkMdAcV.cjs +2 -0
  17. package/dist/index-BSkMdAcV.cjs.map +1 -0
  18. package/dist/index-u8PUIMyl.js +2 -0
  19. package/dist/index-u8PUIMyl.js.map +1 -0
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/modules.cjs +2 -0
  25. package/dist/modules.cjs.map +1 -0
  26. package/dist/modules.js +2 -0
  27. package/dist/modules.js.map +1 -0
  28. package/dist/renderer-CZ85ZN6O.js +2 -0
  29. package/dist/renderer-CZ85ZN6O.js.map +1 -0
  30. package/dist/renderer-D9iInH9_.cjs +2 -0
  31. package/dist/renderer-D9iInH9_.cjs.map +1 -0
  32. package/dist/types/bridges/renderToString.d.ts +6 -0
  33. package/dist/types/bridges/vitePlugin.d.ts +8 -0
  34. package/dist/types/bridges/vueComponent.vue.d.ts +23 -0
  35. package/dist/types/bridges.d.ts +3 -0
  36. package/dist/types/chimp.d.ts +7 -0
  37. package/dist/types/core/baseModule.d.ts +15 -0
  38. package/dist/types/{controller.d.ts → core/controller.d.ts} +4 -8
  39. package/dist/types/{dataManager.d.ts → core/dataManager.d.ts} +17 -17
  40. package/dist/types/{declarations.d.ts → core/declarations.d.ts} +22 -22
  41. package/dist/types/core/index.d.ts +14 -0
  42. package/dist/types/{interactionHandler.d.ts → core/interactionHandler.d.ts} +3 -3
  43. package/dist/types/{overlayManager.d.ts → core/overlayManager.d.ts} +4 -4
  44. package/dist/types/{renderer.d.ts → core/renderer.d.ts} +1 -1
  45. package/dist/types/{utilities.d.ts → core/utilities.d.ts} +1 -3
  46. package/dist/types/dev.d.ts +8 -0
  47. package/dist/types/index.d.ts +2 -21
  48. package/dist/types/{controls → modules/controls}/index.d.ts +2 -2
  49. package/dist/types/{debugPanel → modules/debugPanel}/index.d.ts +2 -2
  50. package/dist/types/{minimap → modules/minimap}/index.d.ts +3 -3
  51. package/dist/types/{mistouchPreventer → modules/mistouchPreventer}/index.d.ts +2 -2
  52. package/dist/types/modules.d.ts +4 -0
  53. package/package.json +33 -8
  54. package/dist/types/baseModule.d.ts +0 -11
  55. package/dist/types/canvasViewer.d.ts +0 -25
  56. package/dist/types/renderToString.d.ts +0 -2
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@needle-di/core"),e=require("pointeract"),i=require("micromark");class n{constructor(t,e){this.container=t,Object.assign(this.options,e)}options={};dispose}const s={round:function(t,e){const i=10**e;return Math.round(t*i)/i},resizeCanvasForDPR:function(t,e,i){const n=window.devicePixelRatio||1,s=t.getContext("2d");if(!s)throw new Error("[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.");t.width=Math.round(e*n),t.height=Math.round(i*n),s.setTransform(1,0,0,1,0,0),s.scale(n,n)},applyStyles:function(t,e){const i=document.createElement("style");i.innerHTML=e,t.appendChild(i)},drawRoundRect:function(t,e,i,n,s,o){t.beginPath(),t.moveTo(e+o,i),t.lineTo(e+n-o,i),t.quadraticCurveTo(e+n,i,e+n,i+o),t.lineTo(e+n,i+s-o),t.quadraticCurveTo(e+n,i+s,e+n-o,i+s),t.lineTo(e+o,i+s),t.quadraticCurveTo(e,i+s,e,i+s-o),t.lineTo(e,i+o),t.quadraticCurveTo(e,i,e+o,i),t.closePath()},getAnchorCoord:function(t,e){const i=t.x+t.width/2,n=t.y+t.height/2;switch(e){case"top":return[i,t.y];case"bottom":return[i,t.y+t.height];case"left":return[t.x,n];case"right":return[t.x+t.width,n];default:return[i,n]}},getColor:function(t="0"){let e=null;if(1===t.length)switch(t){case"1":e="rgba(255, 120, 129, ?)";break;case"2":e="rgba(251, 187, 131, ?)";break;case"3":e="rgba(255, 232, 139, ?)";break;case"4":e="rgba(124, 211, 124, ?)";break;case"5":e="rgba(134, 223, 226, ?)";break;case"6":e="rgba(203, 158, 255, ?)";break;default:e="rgba(140, 140, 140, ?)"}else{const i=function(t){const e=t.replace("#","");return{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16)}}(t);e=`rgba(${i.r}, ${i.g}, ${i.b}, ?)`}return{border:e.replace("?","0.75"),background:e.replace("?","0.1"),active:e.replace("?","1")}},resolvePath:function(t){if(/^https?:\/\//.test(t))return t.substring(0,t.lastIndexOf("/")+1);{const e=t.lastIndexOf("/");return-1!==e?t.substring(0,e+1):"./"}},makeHook:function(){const t=(...e)=>{t.subs.forEach(t=>{t(...e)})};return t.subs=new Set,t.subscribe=e=>{t.subs.add(e)},t.unsubscribe=e=>{t.subs.delete(e)},t}},o=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");const a=800;class r extends n{spatialGrid=null;hooks={onToggleFullscreen:s.makeHook(),onCanvasFetched:s.makeHook()};data={canvasData:void 0,nodeMap:{},canvasBaseDir:void 0,nodeBounds:void 0,offsetX:0,offsetY:0,scale:1,container:document.createElement("div")};loadCanvas=async()=>{const t=this.options.canvasPath;try{this.data.canvasBaseDir=s.resolvePath(t),this.data.canvasData=Object.assign({nodes:[],edges:[]},await fetch(t).then(t=>t.json())),this.data.canvasData.nodes.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=e[e.length-1]}this.data.nodeMap[t.id]=t}),this.data.nodeBounds=this.calculateNodeBounds(),this.buildSpatialGrid(),this.hooks.onCanvasFetched()}catch(e){console.error("Failed to load canvas data:",e)}};findNodeAt=t=>{const{x:e,y:i}=this.C2W(this.C2C({x:t.x,y:t.y}));let n=[];if(this.spatialGrid){const t=`${Math.floor(e/a)},${Math.floor(i/a)}`;n=this.spatialGrid[t]||[]}else n=this.data.canvasData.nodes;for(const s of n)if(!(e<s.x||e>s.x+s.width||i<s.y||i>s.y+s.height||"non-interactive"===this.judgeInteract(s)))return s;return null};judgeInteract=t=>{switch(t?.type){case"text":case"link":return"select";case"file":return t.file.match(/\.(md|wav|mp3)$/i)?"select":"non-interactive";default:return"non-interactive"}};calculateNodeBounds(){let t=1/0,e=1/0,i=-1/0,n=-1/0;this.data.canvasData.nodes.forEach(s=>{t=Math.min(t,s.x),e=Math.min(e,s.y),i=Math.max(i,s.x+s.width),n=Math.max(n,s.y+s.height)});const s=i-t,o=n-e;return{minX:t,minY:e,maxX:i,maxY:n,width:s,height:o,centerX:t+s/2,centerY:e+o/2}}buildSpatialGrid(){const t=this.data.canvasData;if(!(t.nodes.length<50)){this.spatialGrid={};for(const e of t.nodes){const t=Math.floor(e.x/a),i=Math.floor((e.x+e.width)/a),n=Math.floor(e.y/a),s=Math.floor((e.y+e.height)/a);for(let o=t;o<=i;o++)for(let t=n;t<=s;t++){const i=`${o},${t}`;this.spatialGrid[i]||(this.spatialGrid[i]=[]),this.spatialGrid[i].push(e)}}}}zoom=(t,e)=>{const i=this.data.scale*t;this.zoomToScale(i,e)};zoomToScale=(t,e)=>{const i=Math.max(Math.min(t,20),.05),n=this.data.scale;if(i===n)return;const s=this.C2C(e);this.data.offsetX=e.x-s.x*i/n,this.data.offsetY=e.y-s.y*i/n,this.data.scale=i};pan=({x:t,y:e})=>{this.data.offsetX=this.data.offsetX+t,this.data.offsetY=this.data.offsetY+e};panToCoords=({x:t,y:e})=>{this.data.offsetX=t,this.data.offsetY=e};shiftFullscreen=(t="toggle")=>{document.fullscreenElement||"toggle"!==t&&"enter"!==t?!document.fullscreenElement||"toggle"!==t&&"exit"!==t||(document.exitFullscreen(),this.hooks.onToggleFullscreen(!1)):(this.data.container.requestFullscreen(),this.hooks.onToggleFullscreen(!0))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const i=t.width+200,n=t.height+200,s=e.clientWidth,o=e.clientHeight,a=s/i,r=o/n,l=Math.round(1e3*Math.min(a,r))/1e3,c={scale:l,offsetX:s/2-t.centerX*l,offsetY:o/2-t.centerY*l};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.scale};C2C=({x:t,y:e})=>({x:t-this.data.offsetX,y:e-this.data.offsetY});C2W=({x:t,y:e})=>({x:t/this.data.scale,y:e/this.data.scale});middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>this.data.container.remove()}class l extends n{animationId=null;resizeAnimationId=null;DM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};hooks={onResize:s.makeHook(),onRefresh:s.makeHook()};constructor(...t){super(...t),this.DM=this.container.get(r),this.DM.hooks.onCanvasFetched.subscribe(this.onFetched);const e=this.options.container;for(;e.firstElementChild;)e.firstElementChild.remove();e.innerHTML="";const i=this.options.noShadow||!1?e:e.attachShadow({mode:"open"});s.applyStyles(i,".full,.click-layer,.link-iframe,.audio{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.overlay-container.markdown-content{display:flex;justify-content:center;align-items:center}.container{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:#fff;fill:#fff;stroke:#fff;position:relative;width:100%;height:100%;overflow:hidden;background-color:#141414}.container.numb,.container.numb *{pointer-events:none!important}.main-canvas{width:100%;height:100%;transform-origin:top left}.overlays{position:absolute;top:0;left:0;width:100%;height:100%;transform-origin:top left;will-change:transform}.parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.parsed-content-wrapper{padding:10px}}.overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;overflow:hidden;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto}.overlay-container:hover{box-shadow:0 2px 12px #00000080}.overlay-container{transition:var(--containerTransition)}.overlay-container .overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%;border-width:2px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.overlay-container img{width:100%;height:100%;object-fit:cover;pointer-events:none}.overlay-container.active .overlay-border{border:6px solid var(--active-color)}.overlay-container.markdown-content{position:absolute;padding:0 7px}.overlay-container.markdown-content.active .parsed-content-wrapper{overflow:auto;-webkit-user-select:text;user-select:text;pointer-events:auto}.overlay-container.markdown-content.rtl{direction:rtl;text-align:right}.link-iframe,.audio{border:none;background:transparent}.click-layer{background:transparent;pointer-events:auto}.active .click-layer{pointer-events:none}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background-color:transparent}::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}p{font-size:16px;line-height:21px}.parsed-content-wrapper img{width:100%;border-radius:8px}h1{font-size:25px}h2{font-size:23px}h3{font-size:22px}h4{font-size:20px}h5{font-size:19px}h6{font-size:17px}p,h1,h2,h3,h4,h5,h6,ol,ul{margin:0}h1,h2{font-weight:800}h3,h4{font-weight:700}h5,h6{font-weight:600}code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre code{display:block;box-sizing:border-box;width:100%}pre:has(code),table{margin:6px 0}strong{color:#fe8e7c}em{color:#5affb2}a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}a:hover{color:#86d3fd}hr{height:1px;width:100%;background-color:#fff3;border:none}li{margin:5px 0}ul{padding-left:16px}ol{padding-left:15px;padding-right:7.5px}table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}table th,table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}table th{background:#ffffff1f;font-weight:700}");const n=this.DM.data.container;n.classList.add("container"),i.appendChild(n),this.resizeObserver=new ResizeObserver(this.onResize)}onFetched=()=>{this.DM.resetView(),this.resizeObserver.observe(this.DM.data.container),this.animationId=requestAnimationFrame(this.draw)};draw=()=>{this.perFrame.lastScale===this.DM.data.scale&&this.perFrame.lastOffsets.x===this.DM.data.offsetX&&this.perFrame.lastOffsets.y===this.DM.data.offsetY||this.refresh(),this.animationId=requestAnimationFrame(this.draw)};refresh=()=>{this.perFrame.lastScale=this.DM.data.scale,this.perFrame.lastOffsets={x:this.DM.data.offsetX,y:this.DM.data.offsetY},this.hooks.onRefresh()};onResize=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const t=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+t.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+t.y-this.lastResizeCenter.y),this.lastResizeCenter.x=t.x,this.lastResizeCenter.y=t.y,this.hooks.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}class c extends n{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;eventListeners={};DM;IH;parse;get overlaysLayer(){if(!this._overlaysLayer)throw o;return this._overlaysLayer}hooks={onInteractionStart:s.makeHook(),onInteractionEnd:s.makeHook()};constructor(...t){super(...t),this.parse=t=>i.micromark(t,this.options.micromark),this.DM=this.container.get(r),this.IH=this.container.get(h,{lazy:!0});const e=this.container.get(l);this.DM.hooks.onCanvasFetched.subscribe(this.onFetched),e.hooks.onRefresh.subscribe(this.updateOverlays),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="overlays",this.DM.data.container.appendChild(this.overlaysLayer)}onFetched=()=>{this.IH().onClick.subscribe(this.select);const t=this.DM.data.canvasBaseDir,e=async e=>{switch(e.type){case"text":this.updateOverlay(e,e.text,"text");break;case"file":e.file.match(/\.md$/i)?this.loadMarkdownForNode(e):e.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(e,t+e.file,"image"):e.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(e,t+e.file,"audio");break;case"link":this.updateOverlay(e,e.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(t=>{e(t)})};select=t=>{const e=this.selectedId?this.overlays[this.selectedId]:null,i=t?this.overlays[t]:null;e&&e.classList.remove("active"),i?(i.classList.add("active"),this.hooks.onInteractionStart()):this.hooks.onInteractionEnd(),this.selectedId=t};loadMarkdownForNode=async t=>{let e;this.updateOverlay(t,"Loading...","text");try{const i=await fetch(this.DM.data.canvasBaseDir+t.file),n=await i.text(),s=n.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=s?this.parse(s[2]):this.parse(n)}catch(i){console.error("[JSONCanvasViewer] Failed to load markdown:",i),e="Failed to load content."}this.updateOverlay(t,e,"text")};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};updateOverlay(t,e,i){let n=this.overlays[t.id];if(n){if("text"===i){n.getElementsByClassName("parsed-content-wrapper")[0].innerHTML=e}}else n=this.constructOverlay(t,e,i),this.overlaysLayer.appendChild(n),this.overlays[t.id]=n,n.style.left=`${t.x}px`,n.style.top=`${t.y}px`,n.style.width=`${t.width}px`,n.style.height=`${t.height}px`}constructOverlay(t,e,i){const n=s.getColor(t.color),o=document.createElement("div");switch(o.classList.add("overlay-container"),o.id=t.id,o.style.backgroundColor=n.background,o.style.setProperty("--active-color",n.active),i){case"text":{o.classList.add("markdown-content");const t=document.createElement("div");t.innerHTML=this.parse(e||""),t.classList.add("parsed-content-wrapper"),o.appendChild(t);break}case"link":{const t=document.createElement("iframe");t.src=e,t.sandbox="allow-scripts allow-same-origin",t.className="link-iframe",t.loading="lazy",o.appendChild(t);break}case"audio":{const t=document.createElement("audio");t.className="audio",t.src=e,t.controls=!0,o.appendChild(t);break}case"image":{const t=document.createElement("img");t.src=e,t.loading="lazy",o.appendChild(t)}}switch(i){case"link":case"audio":{const t=document.createElement("div");t.className="click-layer",o.appendChild(t)}}const a=document.createElement("div");a.className="overlay-border",a.style.borderColor=n.border,o.appendChild(a);const r=()=>{t.id===this.selectedId&&this.hooks.onInteractionStart()},l=()=>{t.id===this.selectedId&&this.hooks.onInteractionEnd()};return o.addEventListener("pointerenter",r),o.addEventListener("pointerleave",l),o.addEventListener("touchstart",r),o.addEventListener("touchend",l),this.eventListeners[t.id]=[r,l],o}dispose=()=>{for(;this.overlaysLayer.firstElementChild;){const t=this.overlaysLayer.firstElementChild;if(this.eventListeners[t.id]){const e=this.eventListeners[t.id][0],i=this.eventListeners[t.id][1];if(!e||!i)throw o;t.removeEventListener("pointerenter",e),t.removeEventListener("pointerleave",i),t.removeEventListener("touchstart",e),t.removeEventListener("touchend",i),this.eventListeners[t.id][0]=null,this.eventListeners[t.id][1]=null}t.remove()}this.overlaysLayer.remove(),this._overlaysLayer=null}}class h extends n{pointeract;DM;onClick=s.makeHook();constructor(...t){super(...t),this.DM=this.container.get(r);const i=Object.assign(this.options.pointeract||{},{coordinateOutput:"relative"});this.pointeract=new e.Pointeract(this.DM.data.container,[e.Click,e.Drag,e.WheelPanZoom,e.PreventDefault,e.MultitouchPanZoom],i),this.startInteraction=this.pointeract.start,this.stopInteraction=this.pointeract.stop;const n=this.container.get(c);n.hooks.onInteractionStart.subscribe(this.stopInteraction),n.hooks.onInteractionEnd.subscribe(this.startInteraction),this.DM.hooks.onCanvasFetched.subscribe(this.onFetched)}stopInteraction;startInteraction;onFetched=()=>{this.pointeract.on("pan",this.onPan),this.pointeract.on("drag",this.onPan),this.pointeract.on("zoom",this.onZoom),this.pointeract.on("trueClick",this.onTrueClick),this.pointeract.start()};onPan=t=>{this.DM.pan(t.detail)};onZoom=t=>{const e=t.detail;this.DM.zoom(e.factor,{x:e.x,y:e.y})};onTrueClick=t=>{const e=t.detail;if((i=t.detail.target)&&(i.closest(".controls")||i.closest("button")||i.closest("input")))return;var i;const n=this.DM.findNodeAt({x:e.x,y:e.y});this.onClick(n?n.id:null)};dispose=()=>{this.pointeract.off("pan",this.onPan),this.pointeract.off("zoom",this.onZoom),this.pointeract.off("trueClick",this.onTrueClick),this.pointeract.dispose()}}const d="#fff";class p extends n{_canvas;ctx;DM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(null===this._canvas)throw o;return this._canvas}constructor(...t){super(...t);const e=this.container.get(l);e.hooks.onRefresh.subscribe(this.redraw),e.hooks.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(r),this._canvas=document.createElement("canvas"),this._canvas.className="main-canvas",this.ctx=this._canvas.getContext("2d"),this.DM.data.container.appendChild(this._canvas)}optimizeDPR=()=>{const t=this.DM.data.container;s.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const t=Date.now(),e=this.DM.data.offsetX,i=this.DM.data.offsetY,n=this.DM.data.scale,s=this.getCurrentViewport(e,i,n);if(this.isViewportInside(s,this.zoomInOptimize.lastDrawnViewport)&&n!==this.zoomInOptimize.lastDrawnScale){if(t-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(e,i,n,s),this.zoomInOptimize.lastCallTime=t,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(s,n)}this.zoomInOptimize.lastCallTime=t,this.trueRedraw(e,i,n,s)};trueRedraw(t,e,i,n){this.zoomInOptimize.lastDrawnViewport=n,this.zoomInOptimize.lastDrawnScale=i,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(i,i);const s=this.DM.data.canvasData;s.nodes.forEach(t=>{switch(t.type){case"group":this.drawGroup(t,i);break;case"file":this.drawFileNode(t)}}),s.edges.forEach(t=>{this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,e){const i=e/this.zoomInOptimize.lastDrawnScale,n=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*e,s=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*e;this.canvas.style.transform=`translate(${n}px, ${s}px) scale(${i})`}isViewportInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;getCurrentViewport=(t,e,i)=>{const n=-t/i,s=-e/i,o=this.DM.data.container;return{left:n,top:s,right:n+o.clientWidth/i,bottom:s+o.clientHeight/i}};drawLabelBar=(t,e,i,n,s)=>{const o=30*s,a=6*s,r=8*s,l=16*s,c=6*s;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/s,1/s),this.ctx.font=`${l}px 'Inter', sans-serif`;const h=this.ctx.measureText(i).width+2*c;this.ctx.translate(0,-o-r),this.ctx.fillStyle=n,this.ctx.beginPath(),this.ctx.moveTo(a,0),this.ctx.lineTo(h-a,0),this.ctx.quadraticCurveTo(h,0,h,a),this.ctx.lineTo(h,o-a),this.ctx.quadraticCurveTo(h,o,h-a,o),this.ctx.lineTo(a,o),this.ctx.quadraticCurveTo(0,o,0,o-a),this.ctx.lineTo(0,a),this.ctx.quadraticCurveTo(0,0,a,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=d,this.ctx.fillText(i,c,.65*o),this.ctx.restore()};drawNodeBackground=t=>{const e=s.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=e.background,s.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=e.border,this.ctx.lineWidth=2,s.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,e)=>{this.drawNodeBackground(t),t.label&&this.drawLabelBar(t.x,t.y,t.label,s.getColor(t.color).active,e)};drawFileNode=t=>{this.ctx.fillStyle=d,this.ctx.font="16px sans-serif",this.ctx.fillText(t.file,t.x+5,t.y-10)};drawEdge=t=>{const{fromNode:e,toNode:i}=this.getEdgeNodes(t),n=s.getAnchorCoord,[o,a]=n(e,t.fromSide),[r,l]=n(i,t.toSide),{active:c}=s.getColor(t.color);let[h,d,p,m]=[0,0,0,0];if(t.controlPoints?[h,d,p,m]=t.controlPoints:([h,d,p,m]=this.getControlPoints(o,a,r,l,t.fromSide,t.toSide),t.controlPoints=[h,d,p,m]),this.drawCurvedPath(o,a,r,l,h,d,p,m,c),this.drawArrowhead(r,l,p,m,c),t.label){const e=.5,i=(1-e)**3*o+3*(1-e)**2*e*h+3*(1-e)*e*e*p+e**3*r,n=(1-e)**3*a+3*(1-e)**2*e*d+3*(1-e)*e*e*m+e**3*l;this.ctx.font="18px sans-serif";const c=8,u=this.ctx.measureText(t.label).width+2*c,g=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),s.drawRoundRect(this.ctx,i-u/2,n-g/2-2,u,g,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(t.label,i,n-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getEdgeNodes=t=>({fromNode:this.DM.data.nodeMap[t.fromNode],toNode:this.DM.data.nodeMap[t.toNode]});getControlPoints=(t,e,i,n,s,o)=>{const a=i-t,r=n-e,l=Math.min(Math.abs(a),Math.abs(r))+.3*Math.max(Math.abs(a),Math.abs(r)),c=(h=.5*l,d=60,p=300,Math.max(d,Math.min(p,h)));var h,d,p;let m=t,u=e,g=i,f=n;switch(s){case"top":u=e-c;break;case"bottom":u=e+c;break;case"left":m=t-c;break;case"right":m=t+c}switch(o){case"top":f=n-c;break;case"bottom":f=n+c;break;case"left":g=i-c;break;case"right":g=i+c}return[m,u,g,f]};drawCurvedPath=(t,e,i,n,s,o,a,r,l)=>{this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.bezierCurveTo(s,o,a,r,i,n),this.ctx.strokeStyle=l,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,e,i,n,s)=>{const o=t-i,a=e-n,r=Math.sqrt(o*o+a*a);if(0===r)return;const l=o/r,c=a/r,h=t-12*l-7*c,d=e-12*c+7*l,p=t-12*l+7*c,m=e-12*c-7*l;this.ctx.beginPath(),this.ctx.fillStyle=s,this.ctx.moveTo(t,e),this.ctx.lineTo(h,d),this.ctx.lineTo(p,m),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null),this.canvas.remove(),this._canvas=null}}const m='<svg viewBox="-5.28 -5.28 34.56 34.56" fill="none"><path d="M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15" stroke-width="2.4" stroke-linecap="round"/></svg>';const u={Controller:l,DataManager:r,InteractionHandler:h,Renderer:p,OverlayManager:c};exports.BaseModule=n,exports.Controls=class extends n{_controlsPanel=null;_toggleCollapseBtn=null;_toggleFullscreenBtn=null;_zoomOutBtn=null;_zoomSlider=null;_zoomInBtn=null;_resetViewBtn=null;DM;collapsed;get controlsPanel(){if(null===this._controlsPanel)throw o;return this._controlsPanel}get toggleCollapseBtn(){if(null===this._toggleCollapseBtn)throw o;return this._toggleCollapseBtn}get toggleFullscreenBtn(){if(null===this._toggleFullscreenBtn)throw o;return this._toggleFullscreenBtn}get zoomOutBtn(){if(null===this._zoomOutBtn)throw o;return this._zoomOutBtn}get zoomSlider(){if(null===this._zoomSlider)throw o;return this._zoomSlider}get zoomInBtn(){if(null===this._zoomInBtn)throw o;return this._zoomInBtn}get resetViewBtn(){if(null===this._resetViewBtn)throw o;return this._resetViewBtn}constructor(...t){super(...t),this.collapsed=this.options.controlsCollapsed||!1,this.DM=this.container.get(r),this.DM.hooks.onToggleFullscreen.subscribe(this.updateFullscreenBtn),this.container.get(l).hooks.onRefresh.subscribe(this.updateSlider),this._controlsPanel=document.createElement("div"),this._controlsPanel.className="controls",this._controlsPanel.classList.toggle("collapsed",this.collapsed),s.applyStyles(this._controlsPanel,".collapse-button{border-radius:8px;transition:transform .2s}.collapse-button:hover{background:#444c}button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);text-align:center;background-color:#444;width:32px;padding:5px 0}button svg{width:100%;height:100%}.controls{position:absolute;top:10px;right:10px;display:flex;align-items:center;transition:transform .2s;border-radius:8px;gap:10px}.controls.collapsed{transform:translate(calc(100% - 32px))}.controls.collapsed .collapse-button{transform:rotate(180deg)}.controls .controls-content{display:flex;gap:1px;align-items:center;border-radius:8px;overflow:hidden;background:#333c}.controls button:hover{background:#555}.zoom-slider{width:100px;margin:0 10px}"),this._toggleCollapseBtn=document.createElement("button"),this._toggleCollapseBtn.className="collapse-button",this._toggleCollapseBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._controlsPanel.appendChild(this._toggleCollapseBtn);const e=document.createElement("div");e.className="controls-content",this._toggleFullscreenBtn=document.createElement("button"),this._toggleFullscreenBtn.innerHTML=m,e.appendChild(this._toggleFullscreenBtn),this._zoomOutBtn=document.createElement("button"),this._zoomOutBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomOutBtn),this._zoomSlider=document.createElement("input"),this._zoomSlider.type="range",this._zoomSlider.className="zoom-slider",this._zoomSlider.min="-30",this._zoomSlider.max="30",this._zoomSlider.value="0",e.appendChild(this._zoomSlider),this._zoomInBtn=document.createElement("button"),this._zoomInBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12m-6-6v12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomInBtn),this._resetViewBtn=document.createElement("button"),this._resetViewBtn.innerHTML='<svg viewBox="-6 -6 30 30" stroke-width=".08"><path d="m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z" /></svg>',e.appendChild(this._resetViewBtn),this._controlsPanel.appendChild(e),this.DM.data.container.appendChild(this._controlsPanel),this._toggleCollapseBtn.addEventListener("click",this.toggleCollapse),this._zoomInBtn.addEventListener("click",this.zoomIn),this._zoomOutBtn.addEventListener("click",this.zoomOut),this._zoomSlider.addEventListener("input",this.slide),this._resetViewBtn.addEventListener("click",this.DM.resetView),this._toggleFullscreenBtn.addEventListener("click",this.toggleFullscreen)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.controlsPanel.classList.toggle("collapsed",this.collapsed),this.collapsed||this.updateSlider()};zoomIn=()=>this.DM.zoom(1.1,this.DM.middleViewer());zoomOut=()=>this.DM.zoom(1/1.1,this.DM.middleViewer());slide=()=>this.DM.zoomToScale(1.1**Number(this.zoomSlider.value),this.DM.middleViewer());updateFullscreenBtn=t=>{this.toggleFullscreenBtn.innerHTML=t?'<svg viewBox="-40.32 -40.32 176.64 176.64"><path d="M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z"/></svg>':m};toggleFullscreen=()=>this.DM.shiftFullscreen("toggle");updateSlider=()=>{this.collapsed||(this.zoomSlider.value=String(this.scaleToSlider(this.DM.data.scale)))};scaleToSlider=t=>Math.log(t)/Math.log(1.1);dispose=()=>{this.toggleCollapseBtn.removeEventListener("click",this.toggleCollapse),this.zoomInBtn.removeEventListener("click",this.zoomIn),this.zoomOutBtn.removeEventListener("click",this.zoomOut),this.zoomSlider.removeEventListener("input",this.slide),this.resetViewBtn.removeEventListener("click",this.DM.resetView),this.toggleFullscreenBtn.removeEventListener("click",this.toggleFullscreen),this.controlsPanel.remove(),this._controlsPanel=null,this._toggleCollapseBtn=null,this._zoomInBtn=null,this._zoomOutBtn=null,this._zoomSlider=null,this._resetViewBtn=null,this._toggleFullscreenBtn=null}},exports.DebugPanel=class extends n{_debugPanel=null;DM;get debugPanel(){if(!this._debugPanel)throw o;return this._debugPanel}constructor(...t){super(...t),this.DM=this.container.get(r),this.container.get(l).hooks.onRefresh.subscribe(this.update),this._debugPanel=document.createElement("div"),this._debugPanel.className="debug-panel";const e=this.DM.data.container;s.applyStyles(e,".debug-panel{position:absolute;bottom:12px;left:12px;background:#0006;border-radius:12px;padding:12px;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);color:#fff;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);pointer-events:none}"),e.appendChild(this._debugPanel)}update=()=>{const t=s.round,e=this.DM.data;this.debugPanel.innerHTML=`<p>Scale: ${t(e.scale,3)}</p><p>Offset: ${t(e.offsetX,1)}, ${t(e.offsetY,1)}</p>`};dispose=()=>{this.debugPanel.remove(),this._debugPanel=null}},exports.JSONCanvasViewer=class{options;allModules;IO=null;container;constructor(e,i){this.container=new t.Container,this.options=e;this.allModules=[r,l,c,h,p,...i||[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options)})}),this.options.lazyLoad?(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container)):this.load()}load=()=>{this.allModules.forEach(t=>{this.container.get(t)}),this.container.get(r).loadCanvas()};onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};dispose=()=>{this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.allModules.reverse(),this.allModules.forEach(t=>{const e=this.container.get(t);e.dispose&&e.dispose()}),this.container.unbindAll()}},exports.Minimap=class extends n{_minimapCtx=null;_viewportRectangle=null;_minimap=null;_minimapContainer=null;_toggleMinimapBtn=null;minimapCache={scale:1,centerX:0,centerY:0};DM;collapsed;get minimap(){if(null===this._minimap)throw o;return this._minimap}get minimapCtx(){if(null===this._minimapCtx)throw o;return this._minimapCtx}get viewportRectangle(){if(null===this._viewportRectangle)throw o;return this._viewportRectangle}get minimapContainer(){if(null===this._minimapContainer)throw o;return this._minimapContainer}get toggleMinimapBtn(){if(null===this._toggleMinimapBtn)throw o;return this._toggleMinimapBtn}constructor(...t){super(...t),this.collapsed=this.options.minimapCollapsed||!1,this.container.get(l).hooks.onRefresh.subscribe(this.updateViewportRectangle),this.DM=this.container.get(r),this.DM.hooks.onCanvasFetched.subscribe(this.drawMinimap),this._minimapContainer=document.createElement("div"),this._minimapContainer.className="minimap-container",s.applyStyles(this._minimapContainer,".collapse-button{border-radius:8px;transition:transform .2s}.collapse-button:hover{background:#444c}button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);text-align:center;background-color:#444;width:32px;padding:5px 0}button svg{width:100%;height:100%}.minimap-container{position:absolute;bottom:10px;right:10px;display:flex;pointer-events:none;transition:transform .2s}.minimap-container.collapsed{transform:translate(calc(100% - 32px))}.toggle-minimap{margin:auto 10px 0 0;pointer-events:auto}.collapsed .toggle-minimap{transform:rotate(180deg)}.minimap{position:relative;width:200px;height:150px;overflow:hidden;border-radius:12px;background:#202020;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);transform-origin:0 0}.minimap .minimap-canvas{width:100%;height:100%}.minimap .viewport-rectangle{position:absolute;top:0;left:0;pointer-events:none;border:2px solid #fff;border-radius:6px;box-sizing:border-box;background:transparent}@container (max-width: 768px){.container .minimap{transform:scale(.6)}.container .toggle-minimap{transform:translateY(-60px)}.collapsed .container .toggle-minimap{transform:translateY(-60px) rotate(180deg)}.container .minimap-container{transform:translateY(60px) translate(80px)}.container .minimap-container.collapsed{transform:translateY(60px) translate(calc(100% - 32px))}}"),this._toggleMinimapBtn=document.createElement("button"),this._toggleMinimapBtn.className="toggle-minimap collapse-button",this._toggleMinimapBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._minimapContainer.appendChild(this._toggleMinimapBtn),this._minimap=document.createElement("div"),this._minimap.className="minimap";const e=document.createElement("canvas");e.className="minimap-canvas",e.width=200,e.height=150,this._minimap.appendChild(e),this._minimapCtx=e.getContext("2d"),this._viewportRectangle=document.createElement("div"),this._viewportRectangle.className="viewport-rectangle",this._minimap.appendChild(this._viewportRectangle),this._minimapContainer.appendChild(this._minimap),this.DM.data.container.appendChild(this._minimapContainer),this._minimapContainer.classList.toggle("collapsed",this.collapsed),this._toggleMinimapBtn.addEventListener("click",this.toggleCollapse),s.resizeCanvasForDPR(e,e.width,e.height)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.minimapContainer.classList.toggle("collapsed",this.collapsed),this.collapsed||this.updateViewportRectangle()};drawMinimap=()=>{const t=this.DM.data.nodeBounds;if(!t)return;const e=this.minimap.clientWidth,i=this.minimap.clientHeight,n=e/t.width,s=i/t.height;this.minimapCache.scale=.9*Math.min(n,s),this.minimapCache.centerX=e/2,this.minimapCache.centerY=i/2,this.minimapCtx.clearRect(0,0,e,i),this.minimapCtx.save(),this.minimapCtx.translate(this.minimapCache.centerX,this.minimapCache.centerY),this.minimapCtx.scale(this.minimapCache.scale,this.minimapCache.scale),this.minimapCtx.translate(-t.centerX,-t.centerY);const o=this.DM.data.canvasData;for(const a of o.edges)this.drawMinimapEdge(a);for(const a of o.nodes)this.drawMinimapNode(a);this.minimapCtx.restore()};drawMinimapNode=t=>{const e=s.getColor(t.color);this.minimapCtx.fillStyle=e.border,this.minimapCtx.globalAlpha=.3,s.drawRoundRect(this.minimapCtx,t.x,t.y,t.width,t.height,25),this.minimapCtx.fill(),this.minimapCtx.globalAlpha=1};drawMinimapEdge=t=>{const e=this.DM.data.nodeMap,i=e[t.fromNode],n=e[t.toNode];if(!i||!n)return;const[o,a]=s.getAnchorCoord(i,t.fromSide),[r,l]=s.getAnchorCoord(n,t.toSide);this.minimapCtx.beginPath(),this.minimapCtx.moveTo(o,a),this.minimapCtx.lineTo(r,l),this.minimapCtx.strokeStyle="#555",this.minimapCtx.lineWidth=10,this.minimapCtx.stroke()};updateViewportRectangle=()=>{if(this.collapsed)return;const t=this.DM.data.nodeBounds,e=this.DM.data.container,i=this.DM.data.scale;if(!t)return;const n=e.clientWidth/i,s=e.clientHeight/i,o=-this.DM.data.offsetX/i+e.clientWidth/(2*i),a=-this.DM.data.offsetY/i+e.clientHeight/(2*i),r=this.minimapCache.centerX+(o-n/2-t.centerX)*this.minimapCache.scale,l=this.minimapCache.centerY+(a-s/2-t.centerY)*this.minimapCache.scale,c=n*this.minimapCache.scale,h=s*this.minimapCache.scale;this.viewportRectangle.style.left=`${r}px`,this.viewportRectangle.style.top=`${l}px`,this.viewportRectangle.style.width=`${c}px`,this.viewportRectangle.style.height=`${h}px`};dispose=()=>{this.toggleMinimapBtn.removeEventListener("click",this.toggleCollapse),this.minimapCtx.clearRect(0,0,this.minimap.clientWidth,this.minimap.clientHeight),this.minimapContainer.remove(),this._minimapContainer=null,this._toggleMinimapBtn=null,this._viewportRectangle=null,this._minimap=null}},exports.MistouchPreventer=class extends n{_preventionContainer=null;preventMt=!1;DM;preventMistouch={record:!1,lastX:0,lastY:0,initialX:0,initialY:0};get preventionContainer(){if(null===this._preventionContainer)throw o;return this._preventionContainer}constructor(...t){super(...t);const e=Object.assign({preventAtStart:!0,labelText:"Click on to unlock."},this.options.mistouchPreventer||{}),i=document.createElement("div");i.className="prevention-banner",i.textContent=e.labelText,this.DM=this.container.get(r),this._preventionContainer=document.createElement("div"),this._preventionContainer.className="prevention-container hidden",s.applyStyles(this._preventionContainer,".full,.prevention-container{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.prevention-container{display:flex;justify-content:center;align-items:center}.prevention-container{overflow:visible;transition:background .2s,opacity .2s,box-shadow .2s,border .2s,filter .2s,backdrop-filter .2s}.prevention-container.hidden{pointer-events:none;opacity:0}.prevention-container .prevention-banner{background:#0006;border-radius:12px;padding:12px;margin:12px;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);color:#fff;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);text-align:center}"),this._preventionContainer.appendChild(i),this.DM.data.container.appendChild(this._preventionContainer),e.preventAtStart&&this.startPrevention(),window.addEventListener("pointerdown",this.onPointerDown),window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp)}onPointerDown=t=>{const e=this.DM.data.container.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=t.clientX,this.preventMistouch.initialY=t.clientY,this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY,this.preventMistouch.record=!0)};onPointerMove=t=>{this.preventMistouch.record&&(this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY)};onPointerUp=()=>{this.preventMistouch.record&&(this.preventMistouch.record=!1,Math.abs(this.preventMistouch.lastX-this.preventMistouch.initialX)+Math.abs(this.preventMistouch.lastY-this.preventMistouch.initialY)<5&&this.endPrevention())};startPrevention=()=>{this.preventionContainer.classList.remove("hidden"),this.DM.data.container.classList.add("numb"),this.preventMt=!0};endPrevention=()=>{this.preventMt=!1,this.preventionContainer.classList.add("hidden"),setTimeout(()=>this.DM.data.container.classList.remove("numb"),50)};dispose=()=>{window.removeEventListener("pointerdown",this.onPointerDown),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),this.preventionContainer.remove(),this._preventionContainer=null}},exports.canvasUtils=s,exports.developerSuite=u,exports.renderToString=async function(t,e){const n=t=>i.micromark(t,e),o=t=>function(t,e){switch(t.type){case"text":return e(t.text);case"file":return function(t,e){if(t.file.match(/\.md$/i))return async function(t,e){let i;try{const n=await fetch(t),s=await n.text(),o=s.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);i=e(o?o[2]:s)}catch{i="Failed to load content."}return i}(t.file,e);if(t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i))return`<img src="${t.file}" alt="${t.file.split("/").pop()}">`;if(t.file.match(/\.(mp3|wav)$/i))return`<audio src="${t.file}" controls></audio>`}(t,e);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow noreferrer">${t.url}</a>`;default:return""}}(t,n),a=Object.assign({nodes:[],edges:[]},await fetch(t).then(t=>t.json())).nodes,r=s.resolvePath(t);a.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=r+e.pop()}});let l="";return a.forEach(t=>{l+=o(t)}),l};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BSkMdAcV.cjs");exports.JSONCanvasViewer=e.JSONCanvasViewer;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/baseModule.ts","../src/utilities.ts","../src/dataManager.ts","../src/controller.ts","../src/overlayManager.ts","../src/interactionHandler.ts","../src/renderer.ts","../src/controls/index.ts","../src/index.ts","../src/debugPanel/index.ts","../src/canvasViewer.ts","../src/minimap/index.ts","../src/mistouchPreventer/index.ts","../src/renderToString.ts"],"sourcesContent":["import type { Container } from '@needle-di/core';\nimport type { DefaultOptions, Empty, GeneralFunction, GeneralObject } from '@/declarations';\n\nexport type BaseArgs = [Container, GeneralObject];\n\nexport type GeneralModuleCtor = typeof BaseModule<GeneralObject>;\nexport type GeneralModule = InstanceType<GeneralModuleCtor>;\n\nexport class BaseModule<O extends GeneralObject = Empty> {\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t) {\n\t\tObject.assign(this.options, options);\n\t}\n\n\toptions = {} as DefaultOptions & O;\n\n\tdispose?: GeneralFunction;\n}\n","import type { GeneralArguments } from '@/declarations';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tgetColor,\n\tresolvePath,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\");\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn [midX, node.y];\n\t\tcase 'bottom':\n\t\t\treturn [midX, node.y + node.height];\n\t\tcase 'left':\n\t\t\treturn [node.x, midY];\n\t\tcase 'right':\n\t\t\treturn [node.x + node.width, midY];\n\t\tdefault:\n\t\t\treturn [midX, midY];\n\t}\n}\n\nfunction getColor(colorIndex: string = '0') {\n\tlet themeColor = null;\n\n\tfunction hexToRgb(hex: string) {\n\t\tconst cleanHex = hex.replace('#', '');\n\t\tconst r = parseInt(cleanHex.substring(0, 2), 16);\n\t\tconst g = parseInt(cleanHex.substring(2, 4), 16);\n\t\tconst b = parseInt(cleanHex.substring(4, 6), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (colorIndex.length === 1) {\n\t\tswitch (colorIndex) {\n\t\t\tcase '1':\n\t\t\t\tthemeColor = 'rgba(255, 120, 129, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '2':\n\t\t\t\tthemeColor = 'rgba(251, 187, 131, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '3':\n\t\t\t\tthemeColor = 'rgba(255, 232, 139, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '4':\n\t\t\t\tthemeColor = 'rgba(124, 211, 124, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '5':\n\t\t\t\tthemeColor = 'rgba(134, 223, 226, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '6':\n\t\t\t\tthemeColor = 'rgba(203, 158, 255, ?)';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthemeColor = 'rgba(140, 140, 140, ?)';\n\t\t}\n\t} else {\n\t\tconst rgb = hexToRgb(colorIndex);\n\t\tthemeColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ?)`;\n\t}\n\treturn {\n\t\tborder: themeColor.replace('?', '0.75'),\n\t\tbackground: themeColor.replace('?', '0.1'),\n\t\tactive: themeColor.replace('?', '1'),\n\t};\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio || 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx)\n\t\tthrow new Error(\n\t\t\t'[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.',\n\t\t);\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n\nfunction resolvePath(path: string) {\n\tif (/^https?:\\/\\//.test(path)) return path.substring(0, path.lastIndexOf('/') + 1);\n\telse {\n\t\tconst lastSlash = path.lastIndexOf('/');\n\t\treturn lastSlash !== -1 ? path.substring(0, lastSlash + 1) : './';\n\t}\n}\n\nfunction makeHook<Args extends GeneralArguments = []>() {\n\ttype MatchingFunc = (...args: Args) => unknown;\n\ttype Hook = {\n\t\t(...args: Args): void;\n\t\tsubs: Set<MatchingFunc>;\n\t\tsubscribe(callback: MatchingFunc): void;\n\t\tunsubscribe(callback: MatchingFunc): void;\n\t};\n\tconst result: Hook = (...args: Args) => {\n\t\tresult.subs.forEach(callback => {\n\t\t\tcallback(...args);\n\t\t});\n\t};\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import { BaseModule } from '@/baseModule';\nimport type { Coordinates, NodeBounds } from '@/declarations';\nimport utilities from '@/utilities';\n\nconst GRID_CELL_SIZE = 800;\nconst INITIAL_VIEWPORT_PADDING = 100;\n\nexport default class DataManager extends BaseModule {\n\tprivate spatialGrid: Record<string, Array<JSONCanvasNode>> | null = null;\n\thooks = {\n\t\tonToggleFullscreen: utilities.makeHook<[boolean]>(),\n\t\tonCanvasFetched: utilities.makeHook(),\n\t};\n\tdata = {\n\t\tcanvasData: undefined as unknown as Required<JSONCanvas>,\n\t\tnodeMap: {} as Record<string, JSONCanvasNode>,\n\t\tcanvasBaseDir: undefined as unknown as string,\n\t\tnodeBounds: undefined as unknown as NodeBounds,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\n\t\tcontainer: document.createElement('div'),\n\t};\n\n\tloadCanvas = async () => {\n\t\tconst path = this.options.canvasPath;\n\t\ttry {\n\t\t\tthis.data.canvasBaseDir = utilities.resolvePath(path);\n\t\t\tthis.data.canvasData = Object.assign(\n\t\t\t\t{\n\t\t\t\t\tnodes: [],\n\t\t\t\t\tedges: [],\n\t\t\t\t},\n\t\t\t\tawait fetch(path).then(res => res.json()),\n\t\t\t);\n\t\t\tthis.data.canvasData.nodes.forEach(node => {\n\t\t\t\tif (node.type === 'file' && !node.file.includes('http')) {\n\t\t\t\t\tconst file = node.file.split('/');\n\t\t\t\t\tnode.file = file[file.length - 1];\n\t\t\t\t}\n\t\t\t\tthis.data.nodeMap[node.id] = node;\n\t\t\t});\n\t\t\tthis.data.nodeBounds = this.calculateNodeBounds();\n\t\t\tthis.buildSpatialGrid();\n\t\t\tthis.hooks.onCanvasFetched();\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to load canvas data:', err);\n\t\t}\n\t};\n\n\tfindNodeAt = (screenCoords: Coordinates) => {\n\t\tconst { x, y } = this.C2W(this.C2C({ x: screenCoords.x, y: screenCoords.y }));\n\t\tlet candidates: Array<JSONCanvasNode> = [];\n\t\tif (!this.spatialGrid) candidates = this.data.canvasData.nodes;\n\t\telse {\n\t\t\tconst col = Math.floor(x / GRID_CELL_SIZE);\n\t\t\tconst row = Math.floor(y / GRID_CELL_SIZE);\n\t\t\tconst key = `${col},${row}`;\n\t\t\tcandidates = this.spatialGrid[key] || [];\n\t\t}\n\t\tfor (const node of candidates) {\n\t\t\tif (\n\t\t\t\tx < node.x ||\n\t\t\t\tx > node.x + node.width ||\n\t\t\t\ty < node.y ||\n\t\t\t\ty > node.y + node.height ||\n\t\t\t\tthis.judgeInteract(node) === 'non-interactive'\n\t\t\t)\n\t\t\t\tcontinue;\n\t\t\treturn node;\n\t\t}\n\t\treturn null;\n\t};\n\n\t// how should the app handle node interactions\n\tprivate judgeInteract = (node: JSONCanvasNode | null) => {\n\t\tswitch (node?.type) {\n\t\t\tcase 'text':\n\t\t\tcase 'link':\n\t\t\t\treturn 'select';\n\t\t\tcase 'file': {\n\t\t\t\tif (node.file.match(/\\.(md|wav|mp3)$/i)) return 'select';\n\t\t\t\telse return 'non-interactive';\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn 'non-interactive';\n\t\t}\n\t};\n\n\tprivate calculateNodeBounds() {\n\t\tlet minX = Infinity,\n\t\t\tminY = Infinity,\n\t\t\tmaxX = -Infinity,\n\t\t\tmaxY = -Infinity;\n\t\tthis.data.canvasData.nodes.forEach(node => {\n\t\t\tminX = Math.min(minX, node.x);\n\t\t\tminY = Math.min(minY, node.y);\n\t\t\tmaxX = Math.max(maxX, node.x + node.width);\n\t\t\tmaxY = Math.max(maxY, node.y + node.height);\n\t\t});\n\t\tconst width = maxX - minX;\n\t\tconst height = maxY - minY;\n\t\tconst centerX = minX + width / 2;\n\t\tconst centerY = minY + height / 2;\n\t\treturn { minX, minY, maxX, maxY, width, height, centerX, centerY };\n\t}\n\n\tprivate buildSpatialGrid() {\n\t\tconst canvasData = this.data.canvasData;\n\t\tif (canvasData.nodes.length < 50) return;\n\t\tthis.spatialGrid = {};\n\t\tfor (const node of canvasData.nodes) {\n\t\t\tconst minCol = Math.floor(node.x / GRID_CELL_SIZE);\n\t\t\tconst maxCol = Math.floor((node.x + node.width) / GRID_CELL_SIZE);\n\t\t\tconst minRow = Math.floor(node.y / GRID_CELL_SIZE);\n\t\t\tconst maxRow = Math.floor((node.y + node.height) / GRID_CELL_SIZE);\n\t\t\tfor (let col = minCol; col <= maxCol; col++) {\n\t\t\t\tfor (let row = minRow; row <= maxRow; row++) {\n\t\t\t\t\tconst key = `${col},${row}`;\n\t\t\t\t\tif (!this.spatialGrid[key]) this.spatialGrid[key] = [];\n\t\t\t\t\tthis.spatialGrid[key].push(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tzoom = (factor: number, origin: Coordinates) => {\n\t\tconst newScale = this.data.scale * factor;\n\t\tthis.zoomToScale(newScale, origin);\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst validNewScale = Math.max(Math.min(newScale, 20), 0.05);\n\t\tconst scale = this.data.scale;\n\t\tif (validNewScale === scale) return;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.data.offsetX = origin.x - (canvasCoords.x * validNewScale) / scale;\n\t\tthis.data.offsetY = origin.y - (canvasCoords.y * validNewScale) / scale;\n\t\tthis.data.scale = validNewScale;\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = this.data.offsetX + x;\n\t\tthis.data.offsetY = this.data.offsetY + y;\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = x;\n\t\tthis.data.offsetY = y;\n\t};\n\tshiftFullscreen = (option: string = 'toggle') => {\n\t\tif (!document.fullscreenElement && (option === 'toggle' || option === 'enter')) {\n\t\t\tthis.data.container.requestFullscreen();\n\t\t\tthis.hooks.onToggleFullscreen(true);\n\t\t} else if (document.fullscreenElement && (option === 'toggle' || option === 'exit')) {\n\t\t\tdocument.exitFullscreen();\n\t\t\tthis.hooks.onToggleFullscreen(false);\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\t// Container to Canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.data.offsetX,\n\t\ty: containerY - this.data.offsetY,\n\t});\n\t// Canvas to World\n\tprivate C2W = ({ x: canvasX, y: canvasY }: Coordinates) => ({\n\t\tx: canvasX / this.data.scale,\n\t\ty: canvasY / this.data.scale,\n\t});\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tdispose = () => this.data.container.remove();\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport style from '@/styles.scss?inline';\nimport utilities from '@/utilities';\n\ntype Options = {\n\tnoShadow?: boolean;\n};\n\nexport default class Controller extends BaseModule<Options> {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\thooks = {\n\t\tonResize: utilities.makeHook<[number, number]>(),\n\t\tonRefresh: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\n\t\tconst parentContainer = this.options.container;\n\t\twhile (parentContainer.firstElementChild) parentContainer.firstElementChild.remove();\n\t\tparentContainer.innerHTML = '';\n\n\t\tconst noShadow = this.options.noShadow || false;\n\t\tconst realContainer = noShadow ? parentContainer : parentContainer.attachShadow({ mode: 'open' });\n\n\t\tutilities.applyStyles(realContainer, style);\n\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tHTMLContainer.classList.add('container');\n\t\trealContainer.appendChild(HTMLContainer);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResize);\n\t}\n\n\tprivate onFetched = () => {\n\t\tthis.DM.resetView();\n\t\tthis.resizeObserver.observe(this.DM.data.container);\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate draw = () => {\n\t\tif (\n\t\t\tthis.perFrame.lastScale !== this.DM.data.scale ||\n\t\t\tthis.perFrame.lastOffsets.x !== this.DM.data.offsetX ||\n\t\t\tthis.perFrame.lastOffsets.y !== this.DM.data.offsetY\n\t\t)\n\t\t\tthis.refresh();\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate refresh = () => {\n\t\tthis.perFrame.lastScale = this.DM.data.scale;\n\t\tthis.perFrame.lastOffsets = {\n\t\t\tx: this.DM.data.offsetX,\n\t\t\ty: this.DM.data.offsetY,\n\t\t};\n\t\tthis.hooks.onRefresh();\n\t};\n\n\tprivate onResize = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.hooks.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\tdispose = () => {\n\t\tif (this.animationId) cancelAnimationFrame(this.animationId);\n\t\tif (this.resizeAnimationId) cancelAnimationFrame(this.resizeAnimationId);\n\t\tthis.resizeObserver.disconnect();\n\t};\n}\n","import { micromark } from 'micromark';\nimport { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport InteractionHandler from '@/interactionHandler';\nimport utilities, { destroyError } from '@/utilities';\n\ntype Options = {\n\tmicromark?: Parameters<typeof micromark>[1];\n};\n\nexport default class OverlayManager extends BaseModule<Options> {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate IH: () => InteractionHandler;\n\tprivate parse: (markdown: string) => string;\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\thooks = {\n\t\tonInteractionStart: utilities.makeHook(),\n\t\tonInteractionEnd: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = (markdown: string) => micromark(markdown, this.options.micromark);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler, { lazy: true });\n\t\tconst controller = this.container.get(Controller);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\t\tcontroller.hooks.onRefresh.subscribe(this.updateOverlays);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\t}\n\n\tprivate onFetched = () => {\n\t\tthis.IH().onClick.subscribe(this.select);\n\t\tconst cbd = this.DM.data.canvasBaseDir;\n\t\tconst createOverlay = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.updateOverlay(node, node.text, 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tif (node.file.match(/\\.md$/i)) this.loadMarkdownForNode(node);\n\t\t\t\t\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'image');\n\t\t\t\t\telse if (node.file.match(/\\.(mp3|wav)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'audio');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.updateOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(node => {\n\t\t\tcreateOverlay(node);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previous = !this.selectedId ? null : this.overlays[this.selectedId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous) previous.classList.remove('active');\n\t\tif (current) {\n\t\t\tcurrent.classList.add('active');\n\t\t\tthis.hooks.onInteractionStart();\n\t\t} else this.hooks.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate loadMarkdownForNode = async (node: JSONCanvasFileNode) => {\n\t\tthis.updateOverlay(node, 'Loading...', 'text');\n\t\tlet parsedContent: string;\n\t\ttry {\n\t\t\tconst response = await fetch(this.DM.data.canvasBaseDir + node.file);\n\t\t\tconst result = await response.text();\n\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\tif (frontmatterMatch) parsedContent = this.parse(frontmatterMatch[2]);\n\t\t\telse parsedContent = this.parse(result);\n\t\t} catch (err) {\n\t\t\tconsole.error('[JSONCanvasViewer] Failed to load markdown:', err);\n\t\t\tparsedContent = 'Failed to load content.';\n\t\t}\n\t\tthis.updateOverlay(node, parsedContent, 'text');\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate updateOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = this.constructOverlay(node, content, type);\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t} else if (type === 'text') {\n\t\t\tconst parsedContentContainer = element.getElementsByClassName('parsed-content-wrapper')[0];\n\t\t\tparsedContentContainer.innerHTML = content;\n\t\t}\n\t}\n\n\tprivate constructOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tconst color = utilities.getColor(node.color);\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('overlay-container');\n\t\toverlay.id = node.id;\n\t\toverlay.style.backgroundColor = color.background;\n\t\toverlay.style.setProperty('--active-color', color.active);\n\t\tswitch (type) {\n\t\t\tcase 'text': {\n\t\t\t\toverlay.classList.add('markdown-content');\n\t\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\t\tparsedContentWrapper.innerHTML = this.parse(content || '');\n\t\t\t\tparsedContentWrapper.classList.add('parsed-content-wrapper');\n\t\t\t\toverlay.appendChild(parsedContentWrapper);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'link': {\n\t\t\t\tconst iframe = document.createElement('iframe');\n\t\t\t\tiframe.src = content;\n\t\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\t\tiframe.className = 'link-iframe';\n\t\t\t\tiframe.loading = 'lazy';\n\t\t\t\toverlay.appendChild(iframe);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'audio': {\n\t\t\t\tconst audio = document.createElement('audio');\n\t\t\t\taudio.className = 'audio';\n\t\t\t\taudio.src = content;\n\t\t\t\taudio.controls = true;\n\t\t\t\toverlay.appendChild(audio);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst img = document.createElement('img');\n\t\t\t\timg.src = content;\n\t\t\t\timg.loading = 'lazy';\n\t\t\t\toverlay.appendChild(img);\n\t\t\t}\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase 'link':\n\t\t\tcase 'audio': {\n\t\t\t\tconst clickLayer = document.createElement('div');\n\t\t\t\tclickLayer.className = 'click-layer';\n\t\t\t\toverlay.appendChild(clickLayer);\n\t\t\t}\n\t\t}\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'overlay-border';\n\t\toverlayBorder.style.borderColor = color.border;\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t}\n\n\tdispose = () => {\n\t\twhile (this.overlaysLayer.firstElementChild) {\n\t\t\tconst child = this.overlaysLayer.firstElementChild;\n\t\t\tif (this.eventListeners[child.id]) {\n\t\t\t\tconst onStart = this.eventListeners[child.id][0];\n\t\t\t\tconst onEnd = this.eventListeners[child.id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\tchild.removeEventListener('pointerenter', onStart);\n\t\t\t\tchild.removeEventListener('pointerleave', onEnd);\n\t\t\t\tchild.removeEventListener('touchstart', onStart);\n\t\t\t\tchild.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[child.id][0] = null;\n\t\t\t\tthis.eventListeners[child.id][1] = null;\n\t\t\t}\n\t\t\tchild.remove();\n\t\t}\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import {\n\tClick,\n\ttype Ctors,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype StdEvents,\n\tWheelPanZoom,\n} from 'pointeract';\nimport { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport OverlayManager from '@/overlayManager';\nimport utilities from '@/utilities';\n\ntype Options = {\n\tpointeract?: PointeractOptions<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n};\n\nexport default class InteractionHandler extends BaseModule<Options> {\n\tprivate pointeract: Pointeract<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n\tprivate DM: DataManager;\n\tonClick = utilities.makeHook<[string | null]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tconst options = Object.assign(this.options.pointeract || {}, {\n\t\t\tcoordinateOutput: 'relative',\n\t\t});\n\t\tthis.pointeract = new Pointeract(\n\t\t\tthis.DM.data.container,\n\t\t\t[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom],\n\t\t\toptions,\n\t\t);\n\t\tthis.startInteraction = this.pointeract.start;\n\t\tthis.stopInteraction = this.pointeract.stop;\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.hooks.onInteractionStart.subscribe(this.stopInteraction);\n\t\tOM.hooks.onInteractionEnd.subscribe(this.startInteraction);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\t}\n\tstopInteraction: Pointeract['stop'];\n\tstartInteraction: Pointeract['start'];\n\n\tprivate onFetched = () => {\n\t\tthis.pointeract.on('pan', this.onPan);\n\t\tthis.pointeract.on('drag', this.onPan);\n\t\tthis.pointeract.on('zoom', this.onZoom);\n\t\tthis.pointeract.on('trueClick', this.onTrueClick);\n\t\tthis.pointeract.start();\n\t};\n\n\tprivate onPan = (event: StdEvents['pan']) => {\n\t\tthis.DM.pan(event.detail);\n\t};\n\tprivate onZoom = (event: StdEvents['zoom']) => {\n\t\tconst detail = event.detail;\n\t\tthis.DM.zoom(detail.factor, { x: detail.x, y: detail.y });\n\t};\n\n\tprivate onTrueClick = (e: StdEvents['trueClick']) => {\n\t\tconst detail = e.detail;\n\t\tfunction isUIControl(target: HTMLElement | null) {\n\t\t\tif (!target) return false;\n\t\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t\t}\n\t\tif (isUIControl(e.detail.target as HTMLElement | null)) return;\n\t\tconst node = this.DM.findNodeAt({ x: detail.x, y: detail.y });\n\t\tthis.onClick(node ? node.id : null);\n\t};\n\n\tdispose = () => {\n\t\tthis.pointeract.off('pan', this.onPan);\n\t\tthis.pointeract.off('zoom', this.onZoom);\n\t\tthis.pointeract.off('trueClick', this.onTrueClick);\n\t\tthis.pointeract.dispose();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport utilities, { destroyError } from '@/utilities';\n\ninterface viewport {\n\tleft: number;\n\tright: number;\n\ttop: number;\n\tbottom: number;\n}\n\ninterface RuntimeJSONCanvasEdge extends JSONCanvasEdge {\n\tcontrolPoints?: Array<number>;\n}\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 7;\nconst NODE_RADIUS = 12;\nconst FONT_COLOR = '#fff';\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\n\nexport default class Renderer extends BaseModule {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: viewport;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (this._canvas === null) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.redraw);\n\t\tcontroller.hooks.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t}\n\n\tprivate optimizeDPR = () => {\n\t\tconst container = this.DM.data.container;\n\t\tutilities.resizeCanvasForDPR(this.canvas, container.offsetWidth, container.offsetHeight);\n\t};\n\n\tprivate redraw = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (\n\t\t\tthis.isViewportInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: viewport) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tcanvasData.nodes.forEach(node => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'group':\n\t\t\t\t\tthis.drawGroup(node, scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'file':\n\t\t\t\t\tthis.drawFileNode(node);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\tcanvasData.edges.forEach(edge => {\n\t\t\tthis.drawEdge(edge);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: viewport, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX = (this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY = (this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isViewportInside = (inner: viewport, outer: viewport) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (x: number, y: number, label: string, color: string, scale: number) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = utilities.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tutilities.drawRoundRect(this.ctx, node.x + 1, node.y + 1, node.width - 2, node.height - 2, radius);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = 2;\n\t\tutilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasGroupNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label)\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, utilities.getColor(node.color).active, scale);\n\t};\n\n\tprivate drawFileNode = (node: JSONCanvasFileNode) => {\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(node.file, node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (edge: RuntimeJSONCanvasEdge) => {\n\t\tconst { fromNode, toNode } = this.getEdgeNodes(edge);\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst [startX, startY] = gac(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = gac(toNode, edge.toSide);\n\t\tconst { active } = utilities.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!edge.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\tedge.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = edge.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\tactive,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, active);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = '#222';\n\t\t\tthis.ctx.beginPath();\n\t\t\tutilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = '#ccc';\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getEdgeNodes = (edge: JSONCanvasEdge) => ({\n\t\tfromNode: this.DM.data.nodeMap[edge.fromNode],\n\t\ttoNode: this.DM.data.nodeMap[edge.toNode],\n\t});\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t\tcolor: string,\n\t) => {\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(startX, startY);\n\t\tthis.ctx.bezierCurveTo(c1x, c1y, c2x, c2y, endX, endY);\n\t\tthis.ctx.strokeStyle = color;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (tipX: number, tipY: number, fromX: number, fromY: number, color: string) => {\n\t\tconst dx = tipX - fromX;\n\t\tconst dy = tipY - fromY;\n\t\tconst length = Math.sqrt(dx * dx + dy * dy);\n\t\tif (length === 0) return;\n\t\tconst unitX = dx / length;\n\t\tconst unitY = dy / length;\n\t\tconst leftX = tipX - unitX * ARROW_LENGTH - unitY * ARROW_WIDTH;\n\t\tconst leftY = tipY - unitY * ARROW_LENGTH + unitX * ARROW_WIDTH;\n\t\tconst rightX = tipX - unitX * ARROW_LENGTH + unitY * ARROW_WIDTH;\n\t\tconst rightY = tipY - unitY * ARROW_LENGTH - unitX * ARROW_WIDTH;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.moveTo(tipX, tipY);\n\t\tthis.ctx.lineTo(leftX, leftY);\n\t\tthis.ctx.lineTo(rightX, rightY);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t};\n\n\tdispose = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tthis.canvas.remove();\n\t\tthis._canvas = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport utilities, { destroyError } from '@/utilities';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tcontrolsCollapsed?: boolean;\n};\n\nconst resetIcon =\n\t'<svg viewBox=\"-6 -6 30 30\" stroke-width=\".08\"><path d=\"m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z\" /></svg>';\nconst enterFullscreenIcon =\n\t'<svg viewBox=\"-5.28 -5.28 34.56 34.56\" fill=\"none\"><path d=\"M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15\" stroke-width=\"2.4\" stroke-linecap=\"round\"/></svg>';\nconst exitFullscreenIcon =\n\t'<svg viewBox=\"-40.32 -40.32 176.64 176.64\"><path d=\"M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z\"/></svg>';\nconst zoomInIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12m-6-6v12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst zoomOutIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Controls extends BaseModule<Options> {\n\tprivate _controlsPanel: HTMLDivElement | null = null;\n\tprivate _toggleCollapseBtn: HTMLButtonElement | null = null;\n\tprivate _toggleFullscreenBtn: HTMLButtonElement | null = null;\n\tprivate _zoomOutBtn: HTMLButtonElement | null = null;\n\tprivate _zoomSlider: HTMLInputElement | null = null;\n\tprivate _zoomInBtn: HTMLButtonElement | null = null;\n\tprivate _resetViewBtn: HTMLButtonElement | null = null;\n\tprivate DM: DataManager;\n\tprivate collapsed: boolean;\n\n\tprivate get controlsPanel() {\n\t\tif (this._controlsPanel === null) throw destroyError;\n\t\treturn this._controlsPanel;\n\t}\n\tprivate get toggleCollapseBtn() {\n\t\tif (this._toggleCollapseBtn === null) throw destroyError;\n\t\treturn this._toggleCollapseBtn;\n\t}\n\tprivate get toggleFullscreenBtn() {\n\t\tif (this._toggleFullscreenBtn === null) throw destroyError;\n\t\treturn this._toggleFullscreenBtn;\n\t}\n\tprivate get zoomOutBtn() {\n\t\tif (this._zoomOutBtn === null) throw destroyError;\n\t\treturn this._zoomOutBtn;\n\t}\n\tprivate get zoomSlider() {\n\t\tif (this._zoomSlider === null) throw destroyError;\n\t\treturn this._zoomSlider;\n\t}\n\tprivate get zoomInBtn() {\n\t\tif (this._zoomInBtn === null) throw destroyError;\n\t\treturn this._zoomInBtn;\n\t}\n\tprivate get resetViewBtn() {\n\t\tif (this._resetViewBtn === null) throw destroyError;\n\t\treturn this._resetViewBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.controlsCollapsed || false;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onToggleFullscreen.subscribe(this.updateFullscreenBtn);\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.updateSlider);\n\n\t\tthis._controlsPanel = document.createElement('div');\n\t\tthis._controlsPanel.className = 'controls';\n\t\tthis._controlsPanel.classList.toggle('collapsed', this.collapsed);\n\n\t\tutilities.applyStyles(this._controlsPanel, style);\n\n\t\tthis._toggleCollapseBtn = document.createElement('button');\n\t\tthis._toggleCollapseBtn.className = 'collapse-button';\n\t\tthis._toggleCollapseBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._controlsPanel.appendChild(this._toggleCollapseBtn);\n\n\t\tconst controlsContent = document.createElement('div');\n\t\tcontrolsContent.className = 'controls-content';\n\n\t\tthis._toggleFullscreenBtn = document.createElement('button');\n\t\tthis._toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t\tcontrolsContent.appendChild(this._toggleFullscreenBtn);\n\n\t\tthis._zoomOutBtn = document.createElement('button');\n\t\tthis._zoomOutBtn.innerHTML = zoomOutIcon;\n\t\tcontrolsContent.appendChild(this._zoomOutBtn);\n\n\t\tthis._zoomSlider = document.createElement('input');\n\t\tthis._zoomSlider.type = 'range';\n\t\tthis._zoomSlider.className = 'zoom-slider';\n\t\tthis._zoomSlider.min = '-30';\n\t\tthis._zoomSlider.max = '30';\n\t\tthis._zoomSlider.value = '0';\n\t\tcontrolsContent.appendChild(this._zoomSlider);\n\n\t\tthis._zoomInBtn = document.createElement('button');\n\t\tthis._zoomInBtn.innerHTML = zoomInIcon;\n\t\tcontrolsContent.appendChild(this._zoomInBtn);\n\n\t\tthis._resetViewBtn = document.createElement('button');\n\t\tthis._resetViewBtn.innerHTML = resetIcon;\n\t\tcontrolsContent.appendChild(this._resetViewBtn);\n\n\t\tthis._controlsPanel.appendChild(controlsContent);\n\n\t\tthis.DM.data.container.appendChild(this._controlsPanel);\n\n\t\tthis._toggleCollapseBtn.addEventListener('click', this.toggleCollapse);\n\t\tthis._zoomInBtn.addEventListener('click', this.zoomIn);\n\t\tthis._zoomOutBtn.addEventListener('click', this.zoomOut);\n\t\tthis._zoomSlider.addEventListener('input', this.slide);\n\t\tthis._resetViewBtn.addEventListener('click', this.DM.resetView);\n\t\tthis._toggleFullscreenBtn.addEventListener('click', this.toggleFullscreen);\n\t}\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.controlsPanel.classList.toggle('collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateSlider();\n\t};\n\tprivate zoomIn = () => this.DM.zoom(1.1, this.DM.middleViewer());\n\tprivate zoomOut = () => this.DM.zoom(1 / 1.1, this.DM.middleViewer());\n\tprivate slide = () => this.DM.zoomToScale(1.1 ** Number(this.zoomSlider.value), this.DM.middleViewer());\n\n\tprivate updateFullscreenBtn = (enter: boolean) => {\n\t\tif (enter) this.toggleFullscreenBtn.innerHTML = exitFullscreenIcon;\n\t\telse this.toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t};\n\tprivate toggleFullscreen = () => this.DM.shiftFullscreen('toggle');\n\n\tprivate updateSlider = () => {\n\t\tif (this.collapsed) return;\n\t\tthis.zoomSlider.value = String(this.scaleToSlider(this.DM.data.scale));\n\t};\n\tprivate scaleToSlider = (scale: number) => Math.log(scale) / Math.log(1.1);\n\n\tdispose = () => {\n\t\tthis.toggleCollapseBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.zoomInBtn.removeEventListener('click', this.zoomIn);\n\t\tthis.zoomOutBtn.removeEventListener('click', this.zoomOut);\n\t\tthis.zoomSlider.removeEventListener('input', this.slide);\n\t\tthis.resetViewBtn.removeEventListener('click', this.DM.resetView);\n\t\tthis.toggleFullscreenBtn.removeEventListener('click', this.toggleFullscreen);\n\t\tthis.controlsPanel.remove();\n\t\tthis._controlsPanel = null;\n\t\tthis._toggleCollapseBtn = null;\n\t\tthis._zoomInBtn = null;\n\t\tthis._zoomOutBtn = null;\n\t\tthis._zoomSlider = null;\n\t\tthis._resetViewBtn = null;\n\t\tthis._toggleFullscreenBtn = null;\n\t};\n}\n","export { type BaseArgs, BaseModule } from '@/baseModule';\nexport { default as JSONCanvasViewer } from '@/canvasViewer';\nexport { default as Controls } from '@/controls';\nexport { default as DebugPanel } from '@/debugPanel';\nexport type { UserOptions as Options } from '@/declarations';\nexport { default as Minimap } from '@/minimap';\nexport { default as MistouchPreventer } from '@/mistouchPreventer';\nexport { default as renderToString } from '@/renderToString';\nexport { default as canvasUtils } from '@/utilities';\n\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport InteractionHandler from '@/interactionHandler';\nimport OverlayManager from '@/overlayManager';\nimport Renderer from '@/renderer';\nexport const developerSuite = {\n\tController,\n\tDataManager,\n\tInteractionHandler,\n\tRenderer,\n\tOverlayManager,\n};\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport utilities, { destroyError } from '@/utilities';\nimport style from './styles.scss?inline';\n\nexport default class DebugPanel extends BaseModule {\n\tprivate _debugPanel: HTMLDivElement | null = null;\n\tprivate DM: DataManager;\n\n\tprivate get debugPanel() {\n\t\tif (!this._debugPanel) throw destroyError;\n\t\treturn this._debugPanel;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.update);\n\t\tthis._debugPanel = document.createElement('div');\n\t\tthis._debugPanel.className = 'debug-panel';\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tutilities.applyStyles(HTMLContainer, style);\n\t\tHTMLContainer.appendChild(this._debugPanel);\n\t}\n\n\tprivate update = () => {\n\t\tconst round = utilities.round;\n\t\tconst data = this.DM.data;\n\t\tthis.debugPanel.innerHTML = `<p>Scale: ${round(data.scale, 3)}</p><p>Offset: ${round(data.offsetX, 1)}, ${round(data.offsetY, 1)}</p>`;\n\t};\n\n\tdispose = () => {\n\t\tthis.debugPanel.remove();\n\t\tthis._debugPanel = null;\n\t};\n}\n","import { Container } from '@needle-di/core';\nimport type { GeneralModuleCtor } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport type { ModuleInput, Options } from '@/declarations';\nimport InteractionHandler from '@/interactionHandler';\nimport OverlayManager from '@/overlayManager';\nimport Renderer from '@/renderer';\n\ntype InternalModules = [\n\ttypeof DataManager,\n\ttypeof Controller,\n\ttypeof OverlayManager,\n\ttypeof InteractionHandler,\n\ttypeof Renderer,\n];\n\nexport default class JSONCanvasViewer<M extends ModuleInput = []> {\n\tprivate options: Options<[...InternalModules, ...M]>;\n\tprivate allModules: ModuleInput;\n\tprivate IO: IntersectionObserver | null = null;\n\tcontainer: Container;\n\n\tconstructor(options: Options<[...InternalModules, ...M]>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () => new Class(this.container, this.options),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [\n\t\t\tDataManager,\n\t\t\tController,\n\t\t\tOverlayManager,\n\t\t\tInteractionHandler,\n\t\t\tRenderer,\n\t\t\t...(modules || []),\n\t\t];\n\n\t\tthis.allModules.forEach(bind);\n\t\tif (this.options.lazyLoad) {\n\t\t\tthis.IO = new IntersectionObserver(this.onVisibilityCheck, {\n\t\t\t\troot: null,\n\t\t\t\trootMargin: '50px',\n\t\t\t\tthreshold: 0,\n\t\t\t});\n\t\t\tthis.IO.observe(this.options.container);\n\t\t} else this.load();\n\t}\n\n\tprivate load = () => {\n\t\tthis.allModules.forEach(Module => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\t\tthis.container.get(DataManager).loadCanvas();\n\t};\n\n\tprivate onVisibilityCheck = (entries: Array<IntersectionObserverEntry>) => {\n\t\tentries.forEach(entry => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tthis.load();\n\t\t\t\tthis.IO?.disconnect();\n\t\t\t\tthis.IO = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t});\n\t};\n\n\tdispose = () => {\n\t\tthis.IO?.disconnect();\n\t\tthis.IO = null;\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.allModules.reverse();\n\t\tthis.allModules.forEach(Module => {\n\t\t\tconst module = this.container.get(Module);\n\t\t\tif (module.dispose) module.dispose();\n\t\t});\n\t\tthis.container.unbindAll();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport utilities, { destroyError } from '@/utilities';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tminimapCollapsed?: boolean;\n};\n\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Minimap extends BaseModule<Options> {\n\tprivate _minimapCtx: CanvasRenderingContext2D | null = null;\n\tprivate _viewportRectangle: HTMLDivElement | null = null;\n\tprivate _minimap: HTMLDivElement | null = null;\n\tprivate _minimapContainer: HTMLDivElement | null = null;\n\tprivate _toggleMinimapBtn: HTMLButtonElement | null = null;\n\tprivate minimapCache: { scale: number; centerX: number; centerY: number } = {\n\t\tscale: 1,\n\t\tcenterX: 0,\n\t\tcenterY: 0,\n\t};\n\tprivate DM: DataManager;\n\tprivate collapsed: boolean;\n\n\tprivate get minimap() {\n\t\tif (this._minimap === null) throw destroyError;\n\t\treturn this._minimap;\n\t}\n\tprivate get minimapCtx() {\n\t\tif (this._minimapCtx === null) throw destroyError;\n\t\treturn this._minimapCtx;\n\t}\n\tprivate get viewportRectangle() {\n\t\tif (this._viewportRectangle === null) throw destroyError;\n\t\treturn this._viewportRectangle;\n\t}\n\tprivate get minimapContainer() {\n\t\tif (this._minimapContainer === null) throw destroyError;\n\t\treturn this._minimapContainer;\n\t}\n\tprivate get toggleMinimapBtn() {\n\t\tif (this._toggleMinimapBtn === null) throw destroyError;\n\t\treturn this._toggleMinimapBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.minimapCollapsed || false;\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.updateViewportRectangle);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.drawMinimap);\n\n\t\tthis._minimapContainer = document.createElement('div');\n\t\tthis._minimapContainer.className = 'minimap-container';\n\n\t\tutilities.applyStyles(this._minimapContainer, style);\n\n\t\tthis._toggleMinimapBtn = document.createElement('button');\n\t\tthis._toggleMinimapBtn.className = 'toggle-minimap collapse-button';\n\t\tthis._toggleMinimapBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._minimapContainer.appendChild(this._toggleMinimapBtn);\n\n\t\tthis._minimap = document.createElement('div');\n\t\tthis._minimap.className = 'minimap';\n\t\tconst minimapCanvas = document.createElement('canvas');\n\t\tminimapCanvas.className = 'minimap-canvas';\n\t\tminimapCanvas.width = 200;\n\t\tminimapCanvas.height = 150;\n\n\t\tthis._minimap.appendChild(minimapCanvas);\n\t\tthis._minimapCtx = minimapCanvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis._viewportRectangle = document.createElement('div');\n\t\tthis._viewportRectangle.className = 'viewport-rectangle';\n\t\tthis._minimap.appendChild(this._viewportRectangle);\n\t\tthis._minimapContainer.appendChild(this._minimap);\n\n\t\tthis.DM.data.container.appendChild(this._minimapContainer);\n\n\t\tthis._minimapContainer.classList.toggle('collapsed', this.collapsed);\n\n\t\tthis._toggleMinimapBtn.addEventListener('click', this.toggleCollapse);\n\t\tutilities.resizeCanvasForDPR(minimapCanvas, minimapCanvas.width, minimapCanvas.height);\n\t}\n\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.minimapContainer.classList.toggle('collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateViewportRectangle();\n\t};\n\n\tprivate drawMinimap = () => {\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tif (!bounds) return;\n\t\tconst displayWidth = this.minimap.clientWidth;\n\t\tconst displayHeight = this.minimap.clientHeight;\n\t\tconst scaleX = displayWidth / bounds.width;\n\t\tconst scaleY = displayHeight / bounds.height;\n\t\tthis.minimapCache.scale = Math.min(scaleX, scaleY) * 0.9;\n\t\tthis.minimapCache.centerX = displayWidth / 2;\n\t\tthis.minimapCache.centerY = displayHeight / 2;\n\t\tthis.minimapCtx.clearRect(0, 0, displayWidth, displayHeight);\n\t\tthis.minimapCtx.save();\n\t\tthis.minimapCtx.translate(this.minimapCache.centerX, this.minimapCache.centerY);\n\t\tthis.minimapCtx.scale(this.minimapCache.scale, this.minimapCache.scale);\n\t\tthis.minimapCtx.translate(-bounds.centerX, -bounds.centerY);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tfor (const edge of canvasData.edges) this.drawMinimapEdge(edge);\n\t\tfor (const node of canvasData.nodes) this.drawMinimapNode(node);\n\t\tthis.minimapCtx.restore();\n\t};\n\n\tprivate drawMinimapNode = (node: JSONCanvasNode) => {\n\t\tconst colors = utilities.getColor(node.color);\n\t\tconst radius = 25;\n\t\tthis.minimapCtx.fillStyle = colors.border;\n\t\tthis.minimapCtx.globalAlpha = 0.3;\n\t\tutilities.drawRoundRect(this.minimapCtx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.minimapCtx.fill();\n\t\tthis.minimapCtx.globalAlpha = 1.0;\n\t};\n\n\tprivate drawMinimapEdge = (edge: JSONCanvasEdge) => {\n\t\tconst nodeMap = this.DM.data.nodeMap;\n\t\tconst fromNode = nodeMap[edge.fromNode];\n\t\tconst toNode = nodeMap[edge.toNode];\n\t\tif (!fromNode || !toNode) return;\n\t\tconst [startX, startY] = utilities.getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = utilities.getAnchorCoord(toNode, edge.toSide);\n\t\tthis.minimapCtx.beginPath();\n\t\tthis.minimapCtx.moveTo(startX, startY);\n\t\tthis.minimapCtx.lineTo(endX, endY);\n\t\tthis.minimapCtx.strokeStyle = '#555';\n\t\tthis.minimapCtx.lineWidth = 10;\n\t\tthis.minimapCtx.stroke();\n\t};\n\n\tprivate updateViewportRectangle = () => {\n\t\tif (this.collapsed) return;\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tconst container = this.DM.data.container;\n\t\tconst scale = this.DM.data.scale;\n\t\tif (!bounds) return;\n\t\tconst viewWidth = container.clientWidth / scale;\n\t\tconst viewHeight = container.clientHeight / scale;\n\t\tconst viewportCenterX = -this.DM.data.offsetX / scale + container.clientWidth / (2 * scale);\n\t\tconst viewportCenterY = -this.DM.data.offsetY / scale + container.clientHeight / (2 * scale);\n\t\tconst viewRectX =\n\t\t\tthis.minimapCache.centerX +\n\t\t\t(viewportCenterX - viewWidth / 2 - bounds.centerX) * this.minimapCache.scale;\n\t\tconst viewRectY =\n\t\t\tthis.minimapCache.centerY +\n\t\t\t(viewportCenterY - viewHeight / 2 - bounds.centerY) * this.minimapCache.scale;\n\t\tconst viewRectWidth = viewWidth * this.minimapCache.scale;\n\t\tconst viewRectHeight = viewHeight * this.minimapCache.scale;\n\t\tthis.viewportRectangle.style.left = `${viewRectX}px`;\n\t\tthis.viewportRectangle.style.top = `${viewRectY}px`;\n\t\tthis.viewportRectangle.style.width = `${viewRectWidth}px`;\n\t\tthis.viewportRectangle.style.height = `${viewRectHeight}px`;\n\t};\n\n\tdispose = () => {\n\t\tthis.toggleMinimapBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.minimapCtx.clearRect(0, 0, this.minimap.clientWidth, this.minimap.clientHeight);\n\t\tthis.minimapContainer.remove();\n\t\tthis._minimapContainer = null;\n\t\tthis._toggleMinimapBtn = null;\n\t\tthis._viewportRectangle = null;\n\t\tthis._minimap = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport utilities, { destroyError } from '@/utilities';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tmistouchPreventer?: {\n\t\tpreventAtStart?: boolean;\n\t\tlabelText?: string;\n\t};\n};\n\nexport default class MistouchPreventer extends BaseModule<Options> {\n\tprivate _preventionContainer: HTMLDivElement | null = null;\n\tprivate preventMt: boolean = false;\n\tprivate DM: DataManager;\n\tprivate preventMistouch: {\n\t\trecord: boolean;\n\t\tlastX: number;\n\t\tlastY: number;\n\t\tinitialX: number;\n\t\tinitialY: number;\n\t} = {\n\t\trecord: false,\n\t\tlastX: 0,\n\t\tlastY: 0,\n\t\tinitialX: 0,\n\t\tinitialY: 0,\n\t};\n\n\tprivate get preventionContainer() {\n\t\tif (this._preventionContainer === null) throw destroyError;\n\t\treturn this._preventionContainer;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst options = Object.assign(\n\t\t\t{\n\t\t\t\tpreventAtStart: true,\n\t\t\t\tlabelText: 'Click on to unlock.',\n\t\t\t},\n\t\t\tthis.options.mistouchPreventer || {},\n\t\t);\n\n\t\tconst preventionBanner = document.createElement('div');\n\t\tpreventionBanner.className = 'prevention-banner';\n\t\tpreventionBanner.textContent = options.labelText;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._preventionContainer = document.createElement('div');\n\t\tthis._preventionContainer.className = 'prevention-container hidden';\n\n\t\tutilities.applyStyles(this._preventionContainer, style);\n\t\tthis._preventionContainer.appendChild(preventionBanner);\n\t\tthis.DM.data.container.appendChild(this._preventionContainer);\n\n\t\tif (options.preventAtStart) this.startPrevention();\n\n\t\twindow.addEventListener('pointerdown', this.onPointerDown);\n\t\twindow.addEventListener('pointermove', this.onPointerMove);\n\t\twindow.addEventListener('pointerup', this.onPointerUp);\n\t}\n\n\tprivate onPointerDown = (e: PointerEvent) => {\n\t\tconst bounds = this.DM.data.container.getBoundingClientRect();\n\t\tif (\n\t\t\te.clientX < bounds.left ||\n\t\t\te.clientX > bounds.right ||\n\t\t\te.clientY < bounds.top ||\n\t\t\te.clientY > bounds.bottom\n\t\t) {\n\t\t\tif (!this.preventMt) this.startPrevention();\n\t\t} else if (this.preventMt) {\n\t\t\tthis.preventMistouch.initialX = e.clientX;\n\t\t\tthis.preventMistouch.initialY = e.clientY;\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t\tthis.preventMistouch.record = true;\n\t\t}\n\t};\n\n\tprivate onPointerMove = (e: PointerEvent) => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t}\n\t};\n\n\tprivate onPointerUp = () => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.record = false;\n\t\t\tif (\n\t\t\t\tMath.abs(this.preventMistouch.lastX - this.preventMistouch.initialX) +\n\t\t\t\t\tMath.abs(this.preventMistouch.lastY - this.preventMistouch.initialY) <\n\t\t\t\t5\n\t\t\t)\n\t\t\t\tthis.endPrevention();\n\t\t}\n\t};\n\n\tstartPrevention = () => {\n\t\tthis.preventionContainer.classList.remove('hidden');\n\t\tthis.DM.data.container.classList.add('numb');\n\t\tthis.preventMt = true;\n\t};\n\n\tendPrevention = () => {\n\t\tthis.preventMt = false;\n\t\tthis.preventionContainer.classList.add('hidden');\n\t\tsetTimeout(() => this.DM.data.container.classList.remove('numb'), 50); // minimum delay to prevent triggering undesired button touch\n\t};\n\n\tdispose = () => {\n\t\twindow.removeEventListener('pointerdown', this.onPointerDown);\n\t\twindow.removeEventListener('pointermove', this.onPointerMove);\n\t\twindow.removeEventListener('pointerup', this.onPointerUp);\n\t\tthis.preventionContainer.remove();\n\t\tthis._preventionContainer = null;\n\t};\n}\n","import { micromark } from 'micromark';\nimport utilities from '@/utilities';\n\ntype Parse = (markdown: string) => string;\n\nexport default async function (path: string, micromarkOptions?: Parameters<typeof micromark>[1]) {\n\tconst parse = (markdown: string) => micromark(markdown, micromarkOptions);\n\tconst render = (node: JSONCanvasNode) => renderer(node, parse);\n\tconst nodes = Object.assign(\n\t\t{\n\t\t\tnodes: [],\n\t\t\tedges: [],\n\t\t},\n\t\tawait fetch(path).then(res => res.json()),\n\t).nodes as Array<JSONCanvasNode>;\n\tconst basePath = utilities.resolvePath(path);\n\tnodes.forEach(node => {\n\t\tif (node.type === 'file' && !node.file.includes('http')) {\n\t\t\tconst file = node.file.split('/');\n\t\t\tnode.file = basePath + file.pop();\n\t\t}\n\t});\n\tlet result = '';\n\tnodes.forEach(node => {\n\t\tresult += render(node);\n\t});\n\treturn result;\n}\n\nfunction renderer(node: JSONCanvasNode, parse: Parse) {\n\tswitch (node.type) {\n\t\tcase 'text':\n\t\t\treturn parse(node.text);\n\t\tcase 'file':\n\t\t\treturn fileProcessor(node, parse);\n\t\tcase 'link':\n\t\t\treturn `<a href=\"${node.url}\" target=\"_blank\" rel=\"nofollow noreferrer\">${node.url}</a>`;\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n\nfunction fileProcessor(node: JSONCanvasFileNode, parse: Parse) {\n\tif (node.file.match(/\\.md$/i)) return loadMarkdown(node.file, parse);\n\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\treturn `<img src=\"${node.file}\" alt=\"${node.file.split('/').pop()}\">`;\n\telse if (node.file.match(/\\.(mp3|wav)$/i)) return `<audio src=\"${node.file}\" controls></audio>`;\n}\n\nasync function loadMarkdown(path: string, parse: Parse) {\n\tlet parsedContent: string;\n\ttry {\n\t\tconst response = await fetch(path);\n\t\tconst result = await response.text();\n\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\tif (frontmatterMatch) parsedContent = parse(frontmatterMatch[2]);\n\t\telse parsedContent = parse(result);\n\t} catch {\n\t\tparsedContent = 'Failed to load content.';\n\t}\n\treturn parsedContent;\n}\n"],"names":["BaseModule","constructor","container","options","this","Object","assign","dispose","utilities","round","roundedNum","digits","factor","Math","resizeCanvasForDPR","canvas","width","height","dpr","window","devicePixelRatio","ctx","getContext","Error","setTransform","scale","applyStyles","styleString","style","document","createElement","innerHTML","appendChild","drawRoundRect","x","y","radius","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","getAnchorCoord","node","side","midX","midY","getColor","colorIndex","themeColor","length","rgb","hex","cleanHex","replace","r","parseInt","substring","g","b","hexToRgb","border","background","active","resolvePath","path","test","lastIndexOf","lastSlash","makeHook","result","args","subs","forEach","callback","Set","subscribe","add","unsubscribe","delete","destroyError","GRID_CELL_SIZE","DataManager","spatialGrid","hooks","onToggleFullscreen","onCanvasFetched","data","canvasData","nodeMap","canvasBaseDir","nodeBounds","offsetX","offsetY","loadCanvas","async","canvasPath","nodes","edges","fetch","then","res","json","type","file","includes","split","id","calculateNodeBounds","buildSpatialGrid","err","console","error","findNodeAt","screenCoords","C2W","C2C","candidates","key","floor","judgeInteract","match","minX","Infinity","minY","maxX","maxY","min","max","centerX","centerY","minCol","maxCol","minRow","maxRow","col","row","push","zoom","origin","newScale","zoomToScale","validNewScale","canvasCoords","pan","panToCoords","shiftFullscreen","option","fullscreenElement","exitFullscreen","requestFullscreen","resetView","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","initialView","containerX","containerY","canvasX","canvasY","middleViewer","remove","Controller","animationId","resizeAnimationId","DM","resizeObserver","perFrame","lastScale","lastOffsets","lastResizeCenter","onResize","onRefresh","super","get","onFetched","parentContainer","firstElementChild","realContainer","noShadow","attachShadow","mode","HTMLContainer","classList","ResizeObserver","observe","requestAnimationFrame","draw","refresh","center","cancelAnimationFrame","disconnect","OverlayManager","_overlaysLayer","overlays","selectedId","eventListeners","IH","parse","overlaysLayer","onInteractionStart","onInteractionEnd","markdown","micromark","InteractionHandler","lazy","controller","updateOverlays","className","onClick","select","cbd","createOverlay","updateOverlay","text","loadMarkdownForNode","url","values","previous","current","parsedContent","response","frontmatterMatch","transform","content","element","getElementsByClassName","constructOverlay","left","top","color","overlay","backgroundColor","setProperty","parsedContentWrapper","iframe","src","sandbox","loading","audio","controls","img","clickLayer","overlayBorder","borderColor","onStart","onEnd","addEventListener","child","removeEventListener","pointeract","coordinateOutput","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","startInteraction","start","stopInteraction","stop","OM","on","onPan","onZoom","onTrueClick","event","detail","e","target","closest","off","FONT_COLOR","Renderer","_canvas","zoomInOptimize","lastDrawnScale","lastDrawnViewport","right","bottom","timeout","lastCallTime","redraw","optimizeDPR","offsetWidth","offsetHeight","clearTimeout","now","Date","currentViewport","getCurrentViewport","isViewportInside","setTimeout","trueRedraw","fakeRedraw","clearRect","save","translate","drawGroup","drawFileNode","edge","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","drawLabelBar","label","barHeight","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","fill","fillText","drawNodeBackground","colors","globalAlpha","strokeStyle","lineWidth","stroke","fromNode","toNode","getEdgeNodes","gac","startX","startY","fromSide","endX","endY","toSide","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","abs","PADDING","val","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","sqrt","unitX","unitY","leftX","leftY","rightX","rightY","enterFullscreenIcon","developerSuite","_controlsPanel","_toggleCollapseBtn","_toggleFullscreenBtn","_zoomOutBtn","_zoomSlider","_zoomInBtn","_resetViewBtn","collapsed","controlsPanel","toggleCollapseBtn","toggleFullscreenBtn","zoomOutBtn","zoomSlider","zoomInBtn","resetViewBtn","controlsCollapsed","updateFullscreenBtn","updateSlider","toggle","controlsContent","value","toggleCollapse","zoomIn","zoomOut","slide","toggleFullscreen","Number","enter","String","scaleToSlider","log","_debugPanel","debugPanel","update","allModules","IO","modules","Container","Class","bind","provide","useFactory","lazyLoad","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","load","Module","entries","entry","isIntersecting","firstChild","reverse","module","unbindAll","_minimapCtx","_viewportRectangle","_minimap","_minimapContainer","_toggleMinimapBtn","minimapCache","minimap","minimapCtx","viewportRectangle","minimapContainer","toggleMinimapBtn","minimapCollapsed","updateViewportRectangle","drawMinimap","minimapCanvas","displayWidth","displayHeight","drawMinimapEdge","drawMinimapNode","viewportCenterX","viewportCenterY","viewRectX","viewRectY","viewRectWidth","viewRectHeight","_preventionContainer","preventMt","preventMistouch","record","lastX","lastY","initialX","initialY","preventionContainer","preventAtStart","labelText","mistouchPreventer","preventionBanner","textContent","startPrevention","onPointerDown","onPointerMove","onPointerUp","getBoundingClientRect","clientX","clientY","endPrevention","micromarkOptions","render","loadMarkdown","pop","fileProcessor","renderer","basePath"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{Container as t}from"@needle-di/core";import{Pointeract as e,Click as i,Drag as n,WheelPanZoom as s,PreventDefault as o,MultitouchPanZoom as a}from"pointeract";import{micromark as r}from"micromark";class l{constructor(t,e){this.container=t,Object.assign(this.options,e)}options={};dispose}const c={round:function(t,e){const i=10**e;return Math.round(t*i)/i},resizeCanvasForDPR:function(t,e,i){const n=window.devicePixelRatio||1,s=t.getContext("2d");if(!s)throw new Error("[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.");t.width=Math.round(e*n),t.height=Math.round(i*n),s.setTransform(1,0,0,1,0,0),s.scale(n,n)},applyStyles:function(t,e){const i=document.createElement("style");i.innerHTML=e,t.appendChild(i)},drawRoundRect:function(t,e,i,n,s,o){t.beginPath(),t.moveTo(e+o,i),t.lineTo(e+n-o,i),t.quadraticCurveTo(e+n,i,e+n,i+o),t.lineTo(e+n,i+s-o),t.quadraticCurveTo(e+n,i+s,e+n-o,i+s),t.lineTo(e+o,i+s),t.quadraticCurveTo(e,i+s,e,i+s-o),t.lineTo(e,i+o),t.quadraticCurveTo(e,i,e+o,i),t.closePath()},getAnchorCoord:function(t,e){const i=t.x+t.width/2,n=t.y+t.height/2;switch(e){case"top":return[i,t.y];case"bottom":return[i,t.y+t.height];case"left":return[t.x,n];case"right":return[t.x+t.width,n];default:return[i,n]}},getColor:function(t="0"){let e=null;if(1===t.length)switch(t){case"1":e="rgba(255, 120, 129, ?)";break;case"2":e="rgba(251, 187, 131, ?)";break;case"3":e="rgba(255, 232, 139, ?)";break;case"4":e="rgba(124, 211, 124, ?)";break;case"5":e="rgba(134, 223, 226, ?)";break;case"6":e="rgba(203, 158, 255, ?)";break;default:e="rgba(140, 140, 140, ?)"}else{const i=function(t){const e=t.replace("#","");return{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16)}}(t);e=`rgba(${i.r}, ${i.g}, ${i.b}, ?)`}return{border:e.replace("?","0.75"),background:e.replace("?","0.1"),active:e.replace("?","1")}},resolvePath:function(t){if(/^https?:\/\//.test(t))return t.substring(0,t.lastIndexOf("/")+1);{const e=t.lastIndexOf("/");return-1!==e?t.substring(0,e+1):"./"}},makeHook:function(){const t=(...e)=>{t.subs.forEach(t=>{t(...e)})};return t.subs=/* @__PURE__ */new Set,t.subscribe=e=>{t.subs.add(e)},t.unsubscribe=e=>{t.subs.delete(e)},t}},h=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");const d=800;class p extends l{spatialGrid=null;hooks={onToggleFullscreen:c.makeHook(),onCanvasFetched:c.makeHook()};data={canvasData:void 0,nodeMap:{},canvasBaseDir:void 0,nodeBounds:void 0,offsetX:0,offsetY:0,scale:1,container:document.createElement("div")};loadCanvas=async()=>{const t=this.options.canvasPath;try{this.data.canvasBaseDir=c.resolvePath(t),this.data.canvasData=Object.assign({nodes:[],edges:[]},await fetch(t).then(t=>t.json())),this.data.canvasData.nodes.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=e[e.length-1]}this.data.nodeMap[t.id]=t}),this.data.nodeBounds=this.calculateNodeBounds(),this.buildSpatialGrid(),this.hooks.onCanvasFetched()}catch(e){console.error("Failed to load canvas data:",e)}};findNodeAt=t=>{const{x:e,y:i}=this.C2W(this.C2C({x:t.x,y:t.y}));let n=[];if(this.spatialGrid){const t=`${Math.floor(e/d)},${Math.floor(i/d)}`;n=this.spatialGrid[t]||[]}else n=this.data.canvasData.nodes;for(const s of n)if(!(e<s.x||e>s.x+s.width||i<s.y||i>s.y+s.height||"non-interactive"===this.judgeInteract(s)))return s;return null};judgeInteract=t=>{switch(t?.type){case"text":case"link":return"select";case"file":return t.file.match(/\.(md|wav|mp3)$/i)?"select":"non-interactive";default:return"non-interactive"}};calculateNodeBounds(){let t=1/0,e=1/0,i=-1/0,n=-1/0;this.data.canvasData.nodes.forEach(s=>{t=Math.min(t,s.x),e=Math.min(e,s.y),i=Math.max(i,s.x+s.width),n=Math.max(n,s.y+s.height)});const s=i-t,o=n-e;return{minX:t,minY:e,maxX:i,maxY:n,width:s,height:o,centerX:t+s/2,centerY:e+o/2}}buildSpatialGrid(){const t=this.data.canvasData;if(!(t.nodes.length<50)){this.spatialGrid={};for(const e of t.nodes){const t=Math.floor(e.x/d),i=Math.floor((e.x+e.width)/d),n=Math.floor(e.y/d),s=Math.floor((e.y+e.height)/d);for(let o=t;o<=i;o++)for(let t=n;t<=s;t++){const i=`${o},${t}`;this.spatialGrid[i]||(this.spatialGrid[i]=[]),this.spatialGrid[i].push(e)}}}}zoom=(t,e)=>{const i=this.data.scale*t;this.zoomToScale(i,e)};zoomToScale=(t,e)=>{const i=Math.max(Math.min(t,20),.05),n=this.data.scale;if(i===n)return;const s=this.C2C(e);this.data.offsetX=e.x-s.x*i/n,this.data.offsetY=e.y-s.y*i/n,this.data.scale=i};pan=({x:t,y:e})=>{this.data.offsetX=this.data.offsetX+t,this.data.offsetY=this.data.offsetY+e};panToCoords=({x:t,y:e})=>{this.data.offsetX=t,this.data.offsetY=e};shiftFullscreen=(t="toggle")=>{document.fullscreenElement||"toggle"!==t&&"enter"!==t?!document.fullscreenElement||"toggle"!==t&&"exit"!==t||(document.exitFullscreen(),this.hooks.onToggleFullscreen(!1)):(this.data.container.requestFullscreen(),this.hooks.onToggleFullscreen(!0))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const i=t.width+200,n=t.height+200,s=e.clientWidth,o=e.clientHeight,a=s/i,r=o/n,l=Math.round(1e3*Math.min(a,r))/1e3,c={scale:l,offsetX:s/2-t.centerX*l,offsetY:o/2-t.centerY*l};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.scale};C2C=({x:t,y:e})=>({x:t-this.data.offsetX,y:e-this.data.offsetY});C2W=({x:t,y:e})=>({x:t/this.data.scale,y:e/this.data.scale});middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>this.data.container.remove()}class m extends l{animationId=null;resizeAnimationId=null;DM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};hooks={onResize:c.makeHook(),onRefresh:c.makeHook()};constructor(...t){super(...t),this.DM=this.container.get(p),this.DM.hooks.onCanvasFetched.subscribe(this.onFetched);const e=this.options.container;for(;e.firstElementChild;)e.firstElementChild.remove();e.innerHTML="";const i=this.options.noShadow||!1?e:e.attachShadow({mode:"open"});c.applyStyles(i,".full,.click-layer,.link-iframe,.audio{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.overlay-container.markdown-content{display:flex;justify-content:center;align-items:center}.container{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:#fff;fill:#fff;stroke:#fff;position:relative;width:100%;height:100%;overflow:hidden;background-color:#141414}.container.numb,.container.numb *{pointer-events:none!important}.main-canvas{width:100%;height:100%;transform-origin:top left}.overlays{position:absolute;top:0;left:0;width:100%;height:100%;transform-origin:top left;will-change:transform}.parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.parsed-content-wrapper{padding:10px}}.overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;overflow:hidden;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto}.overlay-container:hover{box-shadow:0 2px 12px #00000080}.overlay-container{transition:var(--containerTransition)}.overlay-container .overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%;border-width:2px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.overlay-container img{width:100%;height:100%;object-fit:cover;pointer-events:none}.overlay-container.active .overlay-border{border:6px solid var(--active-color)}.overlay-container.markdown-content{position:absolute;padding:0 7px}.overlay-container.markdown-content.active .parsed-content-wrapper{overflow:auto;-webkit-user-select:text;user-select:text;pointer-events:auto}.overlay-container.markdown-content.rtl{direction:rtl;text-align:right}.link-iframe,.audio{border:none;background:transparent}.click-layer{background:transparent;pointer-events:auto}.active .click-layer{pointer-events:none}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background-color:transparent}::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}p{font-size:16px;line-height:21px}.parsed-content-wrapper img{width:100%;border-radius:8px}h1{font-size:25px}h2{font-size:23px}h3{font-size:22px}h4{font-size:20px}h5{font-size:19px}h6{font-size:17px}p,h1,h2,h3,h4,h5,h6,ol,ul{margin:0}h1,h2{font-weight:800}h3,h4{font-weight:700}h5,h6{font-weight:600}code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre code{display:block;box-sizing:border-box;width:100%}pre:has(code),table{margin:6px 0}strong{color:#fe8e7c}em{color:#5affb2}a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}a:hover{color:#86d3fd}hr{height:1px;width:100%;background-color:#fff3;border:none}li{margin:5px 0}ul{padding-left:16px}ol{padding-left:15px;padding-right:7.5px}table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}table th,table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}table th{background:#ffffff1f;font-weight:700}");const n=this.DM.data.container;n.classList.add("container"),i.appendChild(n),this.resizeObserver=new ResizeObserver(this.onResize)}onFetched=()=>{this.DM.resetView(),this.resizeObserver.observe(this.DM.data.container),this.animationId=requestAnimationFrame(this.draw)};draw=()=>{this.perFrame.lastScale===this.DM.data.scale&&this.perFrame.lastOffsets.x===this.DM.data.offsetX&&this.perFrame.lastOffsets.y===this.DM.data.offsetY||this.refresh(),this.animationId=requestAnimationFrame(this.draw)};refresh=()=>{this.perFrame.lastScale=this.DM.data.scale,this.perFrame.lastOffsets={x:this.DM.data.offsetX,y:this.DM.data.offsetY},this.hooks.onRefresh()};onResize=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const t=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+t.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+t.y-this.lastResizeCenter.y),this.lastResizeCenter.x=t.x,this.lastResizeCenter.y=t.y,this.hooks.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}class u extends l{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;eventListeners={};DM;IH;parse;get overlaysLayer(){if(!this._overlaysLayer)throw h;return this._overlaysLayer}hooks={onInteractionStart:c.makeHook(),onInteractionEnd:c.makeHook()};constructor(...t){super(...t),this.parse=t=>r(t,this.options.micromark),this.DM=this.container.get(p),this.IH=this.container.get(g,{lazy:!0});const e=this.container.get(m);this.DM.hooks.onCanvasFetched.subscribe(this.onFetched),e.hooks.onRefresh.subscribe(this.updateOverlays),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="overlays",this.DM.data.container.appendChild(this.overlaysLayer)}onFetched=()=>{this.IH().onClick.subscribe(this.select);const t=this.DM.data.canvasBaseDir,e=async e=>{switch(e.type){case"text":this.updateOverlay(e,e.text,"text");break;case"file":e.file.match(/\.md$/i)?this.loadMarkdownForNode(e):e.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(e,t+e.file,"image"):e.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(e,t+e.file,"audio");break;case"link":this.updateOverlay(e,e.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(t=>{e(t)})};select=t=>{const e=this.selectedId?this.overlays[this.selectedId]:null,i=t?this.overlays[t]:null;e&&e.classList.remove("active"),i?(i.classList.add("active"),this.hooks.onInteractionStart()):this.hooks.onInteractionEnd(),this.selectedId=t};loadMarkdownForNode=async t=>{let e;this.updateOverlay(t,"Loading...","text");try{const i=await fetch(this.DM.data.canvasBaseDir+t.file),n=await i.text(),s=n.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=s?this.parse(s[2]):this.parse(n)}catch(i){console.error("[JSONCanvasViewer] Failed to load markdown:",i),e="Failed to load content."}this.updateOverlay(t,e,"text")};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};updateOverlay(t,e,i){let n=this.overlays[t.id];if(n){if("text"===i){n.getElementsByClassName("parsed-content-wrapper")[0].innerHTML=e}}else n=this.constructOverlay(t,e,i),this.overlaysLayer.appendChild(n),this.overlays[t.id]=n,n.style.left=`${t.x}px`,n.style.top=`${t.y}px`,n.style.width=`${t.width}px`,n.style.height=`${t.height}px`}constructOverlay(t,e,i){const n=c.getColor(t.color),s=document.createElement("div");switch(s.classList.add("overlay-container"),s.id=t.id,s.style.backgroundColor=n.background,s.style.setProperty("--active-color",n.active),i){case"text":{s.classList.add("markdown-content");const t=document.createElement("div");t.innerHTML=this.parse(e||""),t.classList.add("parsed-content-wrapper"),s.appendChild(t);break}case"link":{const t=document.createElement("iframe");t.src=e,t.sandbox="allow-scripts allow-same-origin",t.className="link-iframe",t.loading="lazy",s.appendChild(t);break}case"audio":{const t=document.createElement("audio");t.className="audio",t.src=e,t.controls=!0,s.appendChild(t);break}case"image":{const t=document.createElement("img");t.src=e,t.loading="lazy",s.appendChild(t)}}switch(i){case"link":case"audio":{const t=document.createElement("div");t.className="click-layer",s.appendChild(t)}}const o=document.createElement("div");o.className="overlay-border",o.style.borderColor=n.border,s.appendChild(o);const a=()=>{t.id===this.selectedId&&this.hooks.onInteractionStart()},r=()=>{t.id===this.selectedId&&this.hooks.onInteractionEnd()};return s.addEventListener("pointerenter",a),s.addEventListener("pointerleave",r),s.addEventListener("touchstart",a),s.addEventListener("touchend",r),this.eventListeners[t.id]=[a,r],s}dispose=()=>{for(;this.overlaysLayer.firstElementChild;){const t=this.overlaysLayer.firstElementChild;if(this.eventListeners[t.id]){const e=this.eventListeners[t.id][0],i=this.eventListeners[t.id][1];if(!e||!i)throw h;t.removeEventListener("pointerenter",e),t.removeEventListener("pointerleave",i),t.removeEventListener("touchstart",e),t.removeEventListener("touchend",i),this.eventListeners[t.id][0]=null,this.eventListeners[t.id][1]=null}t.remove()}this.overlaysLayer.remove(),this._overlaysLayer=null}}class g extends l{pointeract;DM;onClick=c.makeHook();constructor(...t){super(...t),this.DM=this.container.get(p);const r=Object.assign(this.options.pointeract||{},{coordinateOutput:"relative"});this.pointeract=new e(this.DM.data.container,[i,n,s,o,a],r),this.startInteraction=this.pointeract.start,this.stopInteraction=this.pointeract.stop;const l=this.container.get(u);l.hooks.onInteractionStart.subscribe(this.stopInteraction),l.hooks.onInteractionEnd.subscribe(this.startInteraction),this.DM.hooks.onCanvasFetched.subscribe(this.onFetched)}stopInteraction;startInteraction;onFetched=()=>{this.pointeract.on("pan",this.onPan),this.pointeract.on("drag",this.onPan),this.pointeract.on("zoom",this.onZoom),this.pointeract.on("trueClick",this.onTrueClick),this.pointeract.start()};onPan=t=>{this.DM.pan(t.detail)};onZoom=t=>{const e=t.detail;this.DM.zoom(e.factor,{x:e.x,y:e.y})};onTrueClick=t=>{const e=t.detail;if((i=t.detail.target)&&(i.closest(".controls")||i.closest("button")||i.closest("input")))return;var i;const n=this.DM.findNodeAt({x:e.x,y:e.y});this.onClick(n?n.id:null)};dispose=()=>{this.pointeract.off("pan",this.onPan),this.pointeract.off("zoom",this.onZoom),this.pointeract.off("trueClick",this.onTrueClick),this.pointeract.dispose()}}const f="#fff";class v extends l{_canvas;ctx;DM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(null===this._canvas)throw h;return this._canvas}constructor(...t){super(...t);const e=this.container.get(m);e.hooks.onRefresh.subscribe(this.redraw),e.hooks.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(p),this._canvas=document.createElement("canvas"),this._canvas.className="main-canvas",this.ctx=this._canvas.getContext("2d"),this.DM.data.container.appendChild(this._canvas)}optimizeDPR=()=>{const t=this.DM.data.container;c.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const t=Date.now(),e=this.DM.data.offsetX,i=this.DM.data.offsetY,n=this.DM.data.scale,s=this.getCurrentViewport(e,i,n);if(this.isViewportInside(s,this.zoomInOptimize.lastDrawnViewport)&&n!==this.zoomInOptimize.lastDrawnScale){if(t-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(e,i,n,s),this.zoomInOptimize.lastCallTime=t,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(s,n)}this.zoomInOptimize.lastCallTime=t,this.trueRedraw(e,i,n,s)};trueRedraw(t,e,i,n){this.zoomInOptimize.lastDrawnViewport=n,this.zoomInOptimize.lastDrawnScale=i,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(i,i);const s=this.DM.data.canvasData;s.nodes.forEach(t=>{switch(t.type){case"group":this.drawGroup(t,i);break;case"file":this.drawFileNode(t)}}),s.edges.forEach(t=>{this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,e){const i=e/this.zoomInOptimize.lastDrawnScale,n=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*e,s=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*e;this.canvas.style.transform=`translate(${n}px, ${s}px) scale(${i})`}isViewportInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;getCurrentViewport=(t,e,i)=>{const n=-t/i,s=-e/i,o=this.DM.data.container;return{left:n,top:s,right:n+o.clientWidth/i,bottom:s+o.clientHeight/i}};drawLabelBar=(t,e,i,n,s)=>{const o=30*s,a=6*s,r=8*s,l=16*s,c=6*s;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/s,1/s),this.ctx.font=`${l}px 'Inter', sans-serif`;const h=this.ctx.measureText(i).width+2*c;this.ctx.translate(0,-o-r),this.ctx.fillStyle=n,this.ctx.beginPath(),this.ctx.moveTo(a,0),this.ctx.lineTo(h-a,0),this.ctx.quadraticCurveTo(h,0,h,a),this.ctx.lineTo(h,o-a),this.ctx.quadraticCurveTo(h,o,h-a,o),this.ctx.lineTo(a,o),this.ctx.quadraticCurveTo(0,o,0,o-a),this.ctx.lineTo(0,a),this.ctx.quadraticCurveTo(0,0,a,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=f,this.ctx.fillText(i,c,.65*o),this.ctx.restore()};drawNodeBackground=t=>{const e=c.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=e.background,c.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=e.border,this.ctx.lineWidth=2,c.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,e)=>{this.drawNodeBackground(t),t.label&&this.drawLabelBar(t.x,t.y,t.label,c.getColor(t.color).active,e)};drawFileNode=t=>{this.ctx.fillStyle=f,this.ctx.font="16px sans-serif",this.ctx.fillText(t.file,t.x+5,t.y-10)};drawEdge=t=>{const{fromNode:e,toNode:i}=this.getEdgeNodes(t),n=c.getAnchorCoord,[s,o]=n(e,t.fromSide),[a,r]=n(i,t.toSide),{active:l}=c.getColor(t.color);let[h,d,p,m]=[0,0,0,0];if(t.controlPoints?[h,d,p,m]=t.controlPoints:([h,d,p,m]=this.getControlPoints(s,o,a,r,t.fromSide,t.toSide),t.controlPoints=[h,d,p,m]),this.drawCurvedPath(s,o,a,r,h,d,p,m,l),this.drawArrowhead(a,r,p,m,l),t.label){const e=.5,i=(1-e)**3*s+3*(1-e)**2*e*h+3*(1-e)*e*e*p+e**3*a,n=(1-e)**3*o+3*(1-e)**2*e*d+3*(1-e)*e*e*m+e**3*r;this.ctx.font="18px sans-serif";const l=8,u=this.ctx.measureText(t.label).width+2*l,g=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),c.drawRoundRect(this.ctx,i-u/2,n-g/2-2,u,g,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(t.label,i,n-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getEdgeNodes=t=>({fromNode:this.DM.data.nodeMap[t.fromNode],toNode:this.DM.data.nodeMap[t.toNode]});getControlPoints=(t,e,i,n,s,o)=>{const a=i-t,r=n-e,l=Math.min(Math.abs(a),Math.abs(r))+.3*Math.max(Math.abs(a),Math.abs(r)),c=(h=.5*l,d=60,p=300,Math.max(d,Math.min(p,h)));var h,d,p;let m=t,u=e,g=i,f=n;switch(s){case"top":u=e-c;break;case"bottom":u=e+c;break;case"left":m=t-c;break;case"right":m=t+c}switch(o){case"top":f=n-c;break;case"bottom":f=n+c;break;case"left":g=i-c;break;case"right":g=i+c}return[m,u,g,f]};drawCurvedPath=(t,e,i,n,s,o,a,r,l)=>{this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.bezierCurveTo(s,o,a,r,i,n),this.ctx.strokeStyle=l,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,e,i,n,s)=>{const o=t-i,a=e-n,r=Math.sqrt(o*o+a*a);if(0===r)return;const l=o/r,c=a/r,h=t-12*l-7*c,d=e-12*c+7*l,p=t-12*l+7*c,m=e-12*c-7*l;this.ctx.beginPath(),this.ctx.fillStyle=s,this.ctx.moveTo(t,e),this.ctx.lineTo(h,d),this.ctx.lineTo(p,m),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null),this.canvas.remove(),this._canvas=null}}class x{options;allModules;IO=null;container;constructor(e,i){this.container=new t,this.options=e;this.allModules=[p,m,u,g,v,...i||[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options)})}),this.options.lazyLoad?(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container)):this.load()}load=()=>{this.allModules.forEach(t=>{this.container.get(t)}),this.container.get(p).loadCanvas()};onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};dispose=()=>{this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.allModules.reverse(),this.allModules.forEach(t=>{const e=this.container.get(t);e.dispose&&e.dispose()}),this.container.unbindAll()}}const b='<svg viewBox="-5.28 -5.28 34.56 34.56" fill="none"><path d="M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15" stroke-width="2.4" stroke-linecap="round"/></svg>';class w extends l{_controlsPanel=null;_toggleCollapseBtn=null;_toggleFullscreenBtn=null;_zoomOutBtn=null;_zoomSlider=null;_zoomInBtn=null;_resetViewBtn=null;DM;collapsed;get controlsPanel(){if(null===this._controlsPanel)throw h;return this._controlsPanel}get toggleCollapseBtn(){if(null===this._toggleCollapseBtn)throw h;return this._toggleCollapseBtn}get toggleFullscreenBtn(){if(null===this._toggleFullscreenBtn)throw h;return this._toggleFullscreenBtn}get zoomOutBtn(){if(null===this._zoomOutBtn)throw h;return this._zoomOutBtn}get zoomSlider(){if(null===this._zoomSlider)throw h;return this._zoomSlider}get zoomInBtn(){if(null===this._zoomInBtn)throw h;return this._zoomInBtn}get resetViewBtn(){if(null===this._resetViewBtn)throw h;return this._resetViewBtn}constructor(...t){super(...t),this.collapsed=this.options.controlsCollapsed||!1,this.DM=this.container.get(p),this.DM.hooks.onToggleFullscreen.subscribe(this.updateFullscreenBtn),this.container.get(m).hooks.onRefresh.subscribe(this.updateSlider),this._controlsPanel=document.createElement("div"),this._controlsPanel.className="controls",this._controlsPanel.classList.toggle("collapsed",this.collapsed),c.applyStyles(this._controlsPanel,".collapse-button{border-radius:8px;transition:transform .2s}.collapse-button:hover{background:#444c}button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);text-align:center;background-color:#444;width:32px;padding:5px 0}button svg{width:100%;height:100%}.controls{position:absolute;top:10px;right:10px;display:flex;align-items:center;transition:transform .2s;border-radius:8px;gap:10px}.controls.collapsed{transform:translate(calc(100% - 32px))}.controls.collapsed .collapse-button{transform:rotate(180deg)}.controls .controls-content{display:flex;gap:1px;align-items:center;border-radius:8px;overflow:hidden;background:#333c}.controls button:hover{background:#555}.zoom-slider{width:100px;margin:0 10px}"),this._toggleCollapseBtn=document.createElement("button"),this._toggleCollapseBtn.className="collapse-button",this._toggleCollapseBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._controlsPanel.appendChild(this._toggleCollapseBtn);const e=document.createElement("div");e.className="controls-content",this._toggleFullscreenBtn=document.createElement("button"),this._toggleFullscreenBtn.innerHTML=b,e.appendChild(this._toggleFullscreenBtn),this._zoomOutBtn=document.createElement("button"),this._zoomOutBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomOutBtn),this._zoomSlider=document.createElement("input"),this._zoomSlider.type="range",this._zoomSlider.className="zoom-slider",this._zoomSlider.min="-30",this._zoomSlider.max="30",this._zoomSlider.value="0",e.appendChild(this._zoomSlider),this._zoomInBtn=document.createElement("button"),this._zoomInBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12m-6-6v12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomInBtn),this._resetViewBtn=document.createElement("button"),this._resetViewBtn.innerHTML='<svg viewBox="-6 -6 30 30" stroke-width=".08"><path d="m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z" /></svg>',e.appendChild(this._resetViewBtn),this._controlsPanel.appendChild(e),this.DM.data.container.appendChild(this._controlsPanel),this._toggleCollapseBtn.addEventListener("click",this.toggleCollapse),this._zoomInBtn.addEventListener("click",this.zoomIn),this._zoomOutBtn.addEventListener("click",this.zoomOut),this._zoomSlider.addEventListener("input",this.slide),this._resetViewBtn.addEventListener("click",this.DM.resetView),this._toggleFullscreenBtn.addEventListener("click",this.toggleFullscreen)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.controlsPanel.classList.toggle("collapsed",this.collapsed),this.collapsed||this.updateSlider()};zoomIn=()=>this.DM.zoom(1.1,this.DM.middleViewer());zoomOut=()=>this.DM.zoom(1/1.1,this.DM.middleViewer());slide=()=>this.DM.zoomToScale(1.1**Number(this.zoomSlider.value),this.DM.middleViewer());updateFullscreenBtn=t=>{this.toggleFullscreenBtn.innerHTML=t?'<svg viewBox="-40.32 -40.32 176.64 176.64"><path d="M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z"/></svg>':b};toggleFullscreen=()=>this.DM.shiftFullscreen("toggle");updateSlider=()=>{this.collapsed||(this.zoomSlider.value=String(this.scaleToSlider(this.DM.data.scale)))};scaleToSlider=t=>Math.log(t)/Math.log(1.1);dispose=()=>{this.toggleCollapseBtn.removeEventListener("click",this.toggleCollapse),this.zoomInBtn.removeEventListener("click",this.zoomIn),this.zoomOutBtn.removeEventListener("click",this.zoomOut),this.zoomSlider.removeEventListener("input",this.slide),this.resetViewBtn.removeEventListener("click",this.DM.resetView),this.toggleFullscreenBtn.removeEventListener("click",this.toggleFullscreen),this.controlsPanel.remove(),this._controlsPanel=null,this._toggleCollapseBtn=null,this._zoomInBtn=null,this._zoomOutBtn=null,this._zoomSlider=null,this._resetViewBtn=null,this._toggleFullscreenBtn=null}}class C extends l{_debugPanel=null;DM;get debugPanel(){if(!this._debugPanel)throw h;return this._debugPanel}constructor(...t){super(...t),this.DM=this.container.get(p),this.container.get(m).hooks.onRefresh.subscribe(this.update),this._debugPanel=document.createElement("div"),this._debugPanel.className="debug-panel";const e=this.DM.data.container;c.applyStyles(e,".debug-panel{position:absolute;bottom:12px;left:12px;background:#0006;border-radius:12px;padding:12px;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);color:#fff;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);pointer-events:none}"),e.appendChild(this._debugPanel)}update=()=>{const t=c.round,e=this.DM.data;this.debugPanel.innerHTML=`<p>Scale: ${t(e.scale,3)}</p><p>Offset: ${t(e.offsetX,1)}, ${t(e.offsetY,1)}</p>`};dispose=()=>{this.debugPanel.remove(),this._debugPanel=null}}class M extends l{_minimapCtx=null;_viewportRectangle=null;_minimap=null;_minimapContainer=null;_toggleMinimapBtn=null;minimapCache={scale:1,centerX:0,centerY:0};DM;collapsed;get minimap(){if(null===this._minimap)throw h;return this._minimap}get minimapCtx(){if(null===this._minimapCtx)throw h;return this._minimapCtx}get viewportRectangle(){if(null===this._viewportRectangle)throw h;return this._viewportRectangle}get minimapContainer(){if(null===this._minimapContainer)throw h;return this._minimapContainer}get toggleMinimapBtn(){if(null===this._toggleMinimapBtn)throw h;return this._toggleMinimapBtn}constructor(...t){super(...t),this.collapsed=this.options.minimapCollapsed||!1,this.container.get(m).hooks.onRefresh.subscribe(this.updateViewportRectangle),this.DM=this.container.get(p),this.DM.hooks.onCanvasFetched.subscribe(this.drawMinimap),this._minimapContainer=document.createElement("div"),this._minimapContainer.className="minimap-container",c.applyStyles(this._minimapContainer,".collapse-button{border-radius:8px;transition:transform .2s}.collapse-button:hover{background:#444c}button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);text-align:center;background-color:#444;width:32px;padding:5px 0}button svg{width:100%;height:100%}.minimap-container{position:absolute;bottom:10px;right:10px;display:flex;pointer-events:none;transition:transform .2s}.minimap-container.collapsed{transform:translate(calc(100% - 32px))}.toggle-minimap{margin:auto 10px 0 0;pointer-events:auto}.collapsed .toggle-minimap{transform:rotate(180deg)}.minimap{position:relative;width:200px;height:150px;overflow:hidden;border-radius:12px;background:#202020;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);transform-origin:0 0}.minimap .minimap-canvas{width:100%;height:100%}.minimap .viewport-rectangle{position:absolute;top:0;left:0;pointer-events:none;border:2px solid #fff;border-radius:6px;box-sizing:border-box;background:transparent}@container (max-width: 768px){.container .minimap{transform:scale(.6)}.container .toggle-minimap{transform:translateY(-60px)}.collapsed .container .toggle-minimap{transform:translateY(-60px) rotate(180deg)}.container .minimap-container{transform:translateY(60px) translate(80px)}.container .minimap-container.collapsed{transform:translateY(60px) translate(calc(100% - 32px))}}"),this._toggleMinimapBtn=document.createElement("button"),this._toggleMinimapBtn.className="toggle-minimap collapse-button",this._toggleMinimapBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._minimapContainer.appendChild(this._toggleMinimapBtn),this._minimap=document.createElement("div"),this._minimap.className="minimap";const e=document.createElement("canvas");e.className="minimap-canvas",e.width=200,e.height=150,this._minimap.appendChild(e),this._minimapCtx=e.getContext("2d"),this._viewportRectangle=document.createElement("div"),this._viewportRectangle.className="viewport-rectangle",this._minimap.appendChild(this._viewportRectangle),this._minimapContainer.appendChild(this._minimap),this.DM.data.container.appendChild(this._minimapContainer),this._minimapContainer.classList.toggle("collapsed",this.collapsed),this._toggleMinimapBtn.addEventListener("click",this.toggleCollapse),c.resizeCanvasForDPR(e,e.width,e.height)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.minimapContainer.classList.toggle("collapsed",this.collapsed),this.collapsed||this.updateViewportRectangle()};drawMinimap=()=>{const t=this.DM.data.nodeBounds;if(!t)return;const e=this.minimap.clientWidth,i=this.minimap.clientHeight,n=e/t.width,s=i/t.height;this.minimapCache.scale=.9*Math.min(n,s),this.minimapCache.centerX=e/2,this.minimapCache.centerY=i/2,this.minimapCtx.clearRect(0,0,e,i),this.minimapCtx.save(),this.minimapCtx.translate(this.minimapCache.centerX,this.minimapCache.centerY),this.minimapCtx.scale(this.minimapCache.scale,this.minimapCache.scale),this.minimapCtx.translate(-t.centerX,-t.centerY);const o=this.DM.data.canvasData;for(const a of o.edges)this.drawMinimapEdge(a);for(const a of o.nodes)this.drawMinimapNode(a);this.minimapCtx.restore()};drawMinimapNode=t=>{const e=c.getColor(t.color);this.minimapCtx.fillStyle=e.border,this.minimapCtx.globalAlpha=.3,c.drawRoundRect(this.minimapCtx,t.x,t.y,t.width,t.height,25),this.minimapCtx.fill(),this.minimapCtx.globalAlpha=1};drawMinimapEdge=t=>{const e=this.DM.data.nodeMap,i=e[t.fromNode],n=e[t.toNode];if(!i||!n)return;const[s,o]=c.getAnchorCoord(i,t.fromSide),[a,r]=c.getAnchorCoord(n,t.toSide);this.minimapCtx.beginPath(),this.minimapCtx.moveTo(s,o),this.minimapCtx.lineTo(a,r),this.minimapCtx.strokeStyle="#555",this.minimapCtx.lineWidth=10,this.minimapCtx.stroke()};updateViewportRectangle=()=>{if(this.collapsed)return;const t=this.DM.data.nodeBounds,e=this.DM.data.container,i=this.DM.data.scale;if(!t)return;const n=e.clientWidth/i,s=e.clientHeight/i,o=-this.DM.data.offsetX/i+e.clientWidth/(2*i),a=-this.DM.data.offsetY/i+e.clientHeight/(2*i),r=this.minimapCache.centerX+(o-n/2-t.centerX)*this.minimapCache.scale,l=this.minimapCache.centerY+(a-s/2-t.centerY)*this.minimapCache.scale,c=n*this.minimapCache.scale,h=s*this.minimapCache.scale;this.viewportRectangle.style.left=`${r}px`,this.viewportRectangle.style.top=`${l}px`,this.viewportRectangle.style.width=`${c}px`,this.viewportRectangle.style.height=`${h}px`};dispose=()=>{this.toggleMinimapBtn.removeEventListener("click",this.toggleCollapse),this.minimapCtx.clearRect(0,0,this.minimap.clientWidth,this.minimap.clientHeight),this.minimapContainer.remove(),this._minimapContainer=null,this._toggleMinimapBtn=null,this._viewportRectangle=null,this._minimap=null}}class y extends l{_preventionContainer=null;preventMt=!1;DM;preventMistouch={record:!1,lastX:0,lastY:0,initialX:0,initialY:0};get preventionContainer(){if(null===this._preventionContainer)throw h;return this._preventionContainer}constructor(...t){super(...t);const e=Object.assign({preventAtStart:!0,labelText:"Click on to unlock."},this.options.mistouchPreventer||{}),i=document.createElement("div");i.className="prevention-banner",i.textContent=e.labelText,this.DM=this.container.get(p),this._preventionContainer=document.createElement("div"),this._preventionContainer.className="prevention-container hidden",c.applyStyles(this._preventionContainer,".full,.prevention-container{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.prevention-container{display:flex;justify-content:center;align-items:center}.prevention-container{overflow:visible;transition:background .2s,opacity .2s,box-shadow .2s,border .2s,filter .2s,backdrop-filter .2s}.prevention-container.hidden{pointer-events:none;opacity:0}.prevention-container .prevention-banner{background:#0006;border-radius:12px;padding:12px;margin:12px;-webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);border:2px solid rgba(140,140,140,.75);color:#fff;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);text-align:center}"),this._preventionContainer.appendChild(i),this.DM.data.container.appendChild(this._preventionContainer),e.preventAtStart&&this.startPrevention(),window.addEventListener("pointerdown",this.onPointerDown),window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp)}onPointerDown=t=>{const e=this.DM.data.container.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=t.clientX,this.preventMistouch.initialY=t.clientY,this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY,this.preventMistouch.record=!0)};onPointerMove=t=>{this.preventMistouch.record&&(this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY)};onPointerUp=()=>{this.preventMistouch.record&&(this.preventMistouch.record=!1,Math.abs(this.preventMistouch.lastX-this.preventMistouch.initialX)+Math.abs(this.preventMistouch.lastY-this.preventMistouch.initialY)<5&&this.endPrevention())};startPrevention=()=>{this.preventionContainer.classList.remove("hidden"),this.DM.data.container.classList.add("numb"),this.preventMt=!0};endPrevention=()=>{this.preventMt=!1,this.preventionContainer.classList.add("hidden"),setTimeout(()=>this.DM.data.container.classList.remove("numb"),50)};dispose=()=>{window.removeEventListener("pointerdown",this.onPointerDown),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),this.preventionContainer.remove(),this._preventionContainer=null}}async function k(t,e){const i=t=>r(t,e),n=t=>function(t,e){switch(t.type){case"text":return e(t.text);case"file":return function(t,e){if(t.file.match(/\.md$/i))return async function(t,e){let i;try{const n=await fetch(t),s=await n.text(),o=s.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);i=e(o?o[2]:s)}catch{i="Failed to load content."}return i}(t.file,e);if(t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i))return`<img src="${t.file}" alt="${t.file.split("/").pop()}">`;if(t.file.match(/\.(mp3|wav)$/i))return`<audio src="${t.file}" controls></audio>`}(t,e);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow noreferrer">${t.url}</a>`;default:return""}}(t,i),s=Object.assign({nodes:[],edges:[]},await fetch(t).then(t=>t.json())).nodes,o=c.resolvePath(t);s.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=o+e.pop()}});let a="";return s.forEach(t=>{a+=n(t)}),a}const z={Controller:m,DataManager:p,InteractionHandler:g,Renderer:v,OverlayManager:u};export{l as BaseModule,w as Controls,C as DebugPanel,x as JSONCanvasViewer,M as Minimap,y as MistouchPreventer,c as canvasUtils,z as developerSuite,k as renderToString};
1
+ import{J as e}from"./index-u8PUIMyl.js";export{e as JSONCanvasViewer};
2
2
  //# sourceMappingURL=index.js.map