json-canvas-viewer 3.4.3 → 4.0.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 (50) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +51 -107
  3. package/dist/chimp.js +1 -1
  4. package/dist/index.d.ts +609 -0
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/package.json +15 -48
  8. package/dist/bridges.js +0 -2
  9. package/dist/bridges.js.map +0 -1
  10. package/dist/dev.js +0 -2
  11. package/dist/dev.js.map +0 -1
  12. package/dist/index-BPBGNZi4.js +0 -2
  13. package/dist/index-BPBGNZi4.js.map +0 -1
  14. package/dist/interactionHandler-CrVH9u7P.js +0 -2
  15. package/dist/interactionHandler-CrVH9u7P.js.map +0 -1
  16. package/dist/modules.js +0 -2
  17. package/dist/modules.js.map +0 -1
  18. package/dist/react.js +0 -2
  19. package/dist/react.js.map +0 -1
  20. package/dist/renderToString-Dp8A-Rka.js +0 -2
  21. package/dist/renderToString-Dp8A-Rka.js.map +0 -1
  22. package/dist/renderer-BGA72dN1.js +0 -2
  23. package/dist/renderer-BGA72dN1.js.map +0 -1
  24. package/dist/types/bridges/reactComponent.d.ts +0 -12
  25. package/dist/types/bridges/renderToString.d.ts +0 -6
  26. package/dist/types/bridges/vitePlugin.d.ts +0 -8
  27. package/dist/types/bridges/vueComponent.vue.d.ts +0 -28
  28. package/dist/types/bridges/webpackPlugin.d.ts +0 -7
  29. package/dist/types/bridges.d.ts +0 -3
  30. package/dist/types/chimp.d.ts +0 -7
  31. package/dist/types/core/baseModule.d.ts +0 -19
  32. package/dist/types/core/controller.d.ts +0 -35
  33. package/dist/types/core/dataManager.d.ts +0 -59
  34. package/dist/types/core/declarations.d.ts +0 -105
  35. package/dist/types/core/index.d.ts +0 -25
  36. package/dist/types/core/interactionHandler.d.ts +0 -39
  37. package/dist/types/core/overlayManager.d.ts +0 -44
  38. package/dist/types/core/renderer.d.ts +0 -32
  39. package/dist/types/core/styleManager.d.ts +0 -49
  40. package/dist/types/core/utilities.d.ts +0 -25
  41. package/dist/types/dev.d.ts +0 -9
  42. package/dist/types/index.d.ts +0 -2
  43. package/dist/types/modules/controls/index.d.ts +0 -38
  44. package/dist/types/modules/debugPanel/index.d.ts +0 -9
  45. package/dist/types/modules/minimap/index.d.ts +0 -32
  46. package/dist/types/modules/mistouchPreventer/index.d.ts +0 -25
  47. package/dist/types/modules.d.ts +0 -4
  48. package/dist/vue.js +0 -2
  49. package/dist/vue.js.map +0 -1
  50. package/dist/webpackLoader.js +0 -33
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{J as e}from"./index-BPBGNZi4.js";export{e as JSONCanvasViewer};
1
+ import{toHslString as t,rgbToHsl as e,parseRgb as i,parseHex as n,parseHsl as s}from"@ahmedsemih/color-fns";import{dragPreset as o,zoomPreset as a,panPreset as r,Pointeract as l,Click as h,Drag as c,WheelPanZoom as d,PreventDefault as p,MultitouchPanZoom as m,Lubricator as u}from"pointeract";import{Container as v}from"@needle-di/core";import C from"dompurify";import{marked as g}from"marked";class f{constructor(t,e,i,n,s,o){this.container=t,this.augment=o,this.options=e,this.onStart=i.subscribe,this.onDispose=n.subscribe,this.onRestart=s.subscribe}onStart;onRestart;onDispose;options}const w={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{x:i,y:t.y};case"bottom":return{x:i,y:t.y+t.height};case"left":return{x:t.x,y:n};case"right":return{x:t.x+t.width,y:n};default:return{x:i,y:n}}},makeHook:function(t=!1,e=!1){const i=e?async(...e)=>{if(t){const t=Array.from(i.subs).reverse();for(const i of t)await i(...e)}else for(const t of i.subs)await t(...e)}:(...e)=>{if(t){const t=Array.from(i.subs).reverse();for(const i of t)i(...e)}else for(const t of i.subs)t(...e)};return i.subs=/* @__PURE__ */new Set,i.subscribe=t=>{i.subs.add(t)},i.unsubscribe=t=>{i.subs.delete(t)},i}},V=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");class x extends f{onToggleFullscreen=w.makeHook();data={canvasData:{nodes:[],edges:[]},nodeMap:{},edgeMap:{},canvasBaseDir:"./",nodeBounds:{maxX:0,maxY:0,minX:0,minY:0,width:0,height:0,centerX:0,centerY:0},offsetX:0,offsetY:0,scale:1,container:document.createElement("div")};constructor(...t){super(...t);const e=this.options.container;for(;e.firstElementChild;)e.firstElementChild.remove();e.innerHTML="";const i=this.options.shadowed?e.attachShadow({mode:"open"}):e;w.applyStyles(i,".JSON-Canvas-Viewer{--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:var(--text);fill:var(--text);stroke:var(--text);background-color:var(--background);position:relative;width:100%;height:100%;overflow:hidden}.JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-full,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{top:0;left:0;width:100%;height:100%;position:absolute}.JSON-Canvas-Viewer .JCV-flex-center,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{display:flex;justify-content:center;align-items:center}.JSON-Canvas-Viewer .JCV-border-shadow-bg{background:var(--background-secondary);border:1px solid var(--border)!important;box-shadow:var(--shadow)}.JSON-Canvas-Viewer .JCV-button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);background-color:var(--background-secondary);text-align:center;width:32px;padding:5px 0}.JSON-Canvas-Viewer .JCV-button svg{width:100%;height:100%}.JSON-Canvas-Viewer .JCV-button:hover{background-color:var(--border)}.JSON-Canvas-Viewer .JCV-button.JCV-collapse-button{border-radius:8px;transition:transform .2s,background-color .2s}.JSON-Canvas-Viewer .JCV-collapsed .JCV-collapse-button{transform:rotate(180deg)}.JSON-Canvas-Viewer .JCV-main-canvas{width:100%;height:100%;transform-origin:top left}.JSON-Canvas-Viewer .JCV-overlays{position:absolute;transform-origin:top left;will-change:transform}.JSON-Canvas-Viewer .JCV-overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto;background-color:var(--overlay-card);transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;color:var(--overlay-border);top:0;left:0;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{overflow:hidden}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{position:absolute;padding:0 7px}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content.rtl{direction:rtl;text-align:right}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active{-webkit-user-select:auto;user-select:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-overlay-border{border:4px solid var(--overlay-active)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video{border:none;background:transparent}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer{background:transparent;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-click-layer{pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-img{width:100%;height:100%;object-fit:cover;pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-img{pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-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){.JSON-Canvas-Viewer .JCV-overlay-container .JCV-parsed-content-wrapper{padding:10px}}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-parsed-content-wrapper{overflow:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar{width:4px}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-track{background-color:transparent}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}.JSON-Canvas-Viewer .JCV-markdown-content p{font-size:16px;line-height:21px}.JSON-Canvas-Viewer .JCV-markdown-content img{width:100%;border-radius:8px}.JSON-Canvas-Viewer .JCV-markdown-content h1{font-size:25px}.JSON-Canvas-Viewer .JCV-markdown-content h2{font-size:23px}.JSON-Canvas-Viewer .JCV-markdown-content h3{font-size:22px}.JSON-Canvas-Viewer .JCV-markdown-content h4{font-size:20px}.JSON-Canvas-Viewer .JCV-markdown-content h5{font-size:19px}.JSON-Canvas-Viewer .JCV-markdown-content h6{font-size:17px}.JSON-Canvas-Viewer .JCV-markdown-content p,.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2,.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4,.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6,.JSON-Canvas-Viewer .JCV-markdown-content ol,.JSON-Canvas-Viewer .JCV-markdown-content ul{margin:0}.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2{font-weight:800}.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4{font-weight:700}.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6{font-weight:600}.JSON-Canvas-Viewer .JCV-markdown-content code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre .JSON-Canvas-Viewer .JCV-markdown-content code{display:block;box-sizing:border-box;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content pre:has(code),.JSON-Canvas-Viewer .JCV-markdown-content table{margin:6px 0}.JSON-Canvas-Viewer .JCV-markdown-content strong{color:#fe8e7c}.JSON-Canvas-Viewer .JCV-markdown-content em{color:#5affb2}.JSON-Canvas-Viewer .JCV-markdown-content a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}.JSON-Canvas-Viewer .JCV-markdown-content a:hover{color:#86d3fd}.JSON-Canvas-Viewer .JCV-markdown-content hr{height:1px;width:100%;background-color:#fff3;border:none}.JSON-Canvas-Viewer .JCV-markdown-content li{margin:5px 0}.JSON-Canvas-Viewer .JCV-markdown-content ul{padding-left:16px}.JSON-Canvas-Viewer .JCV-markdown-content ol{padding-left:15px;padding-right:7.5px}.JSON-Canvas-Viewer .JCV-markdown-content table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content table th,.JSON-Canvas-Viewer .JCV-markdown-content table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}.JSON-Canvas-Viewer .JCV-markdown-content table th{background:#ffffff1f;font-weight:700}"+this.options.extraCSS),this.data.container.classList.add("JSON-Canvas-Viewer"),i.appendChild(this.data.container),this.augment({resetView:this.resetView,toggleFullscreen:this.toggleFullscreen,onToggleFullscreen:this.onToggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{const t=Object.assign({nodes:[],edges:[]},this.options.canvas);Object.assign(this.data,{canvasData:t,nodeMap:{},edgeMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(t),offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(t=>{const e={ref:t,box:this.getNodeBox(t)};if(this.data.nodeMap[t.id]=e,"file"===t.type){const i=t.file.split("/").pop()??"";if(e.fileName=i,!t.file.startsWith("http://")&&!t.file.startsWith("https://")){const e=this.options.attachments?.[i];e?t.file=e:this.options.noAttachmentRelocation||(t.file=this.data.canvasBaseDir+i)}}}),this.data.canvasData.edges.forEach(t=>{this.data.edgeMap[t.id]={ref:t,box:this.getEdgeBox(t)}}),this.resetView()};processBaseDir=t=>{if(!t)return"./";const e=t?.slice(-1);return"/"===e?t:`${t}/`};getNodeBox=t=>({left:t.x,top:"file"===t.type||"group"===t.type?t.y-40:t.y,right:t.width+t.x,bottom:t.y+t.height});getEdgeBox=t=>{const e=this.data.nodeMap,i=e[t.fromNode].ref,n=e[t.toNode].ref,s=w.getAnchorCoord(i,t.fromSide),o=w.getAnchorCoord(n,t.toSide),a=Math.min(s.x,o.x),r=Math.min(s.y,o.y),l=Math.max(s.x,o.x),h=Math.max(s.y,o.y),c=l-a,d=h-r,p=Math.min(c,d),m=0===p?1:p,u=Math.max(c,d),v=10*Math.log2(u/m);return{left:a-v,top:r-v,right:l+v,bottom:h+v}};calculateNodeBounds(t){let e=1/0,i=1/0,n=-1/0,s=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),i=Math.min(i,t.y),n=Math.max(n,t.x+t.width),s=Math.max(s,t.y+t.height)});const o=n-e,a=s-i;return{minX:e,minY:i,maxX:n,maxY:s,width:o,height:a,centerX:e+o/2,centerY:i+a/2}}toggleFullscreen=async t=>{document.fullscreenElement||t&&"enter"!==t?!document.fullscreenElement||t&&"exit"!==t||(await document.exitFullscreen(),this.onToggleFullscreen("exit")):(await this.data.container.requestFullscreen(),this.onToggleFullscreen("enter"))};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,h={scale:l,offsetX:s/2-t.centerX*l,offsetY:o/2-t.centerY*l};this.data.offsetX=h.offsetX,this.data.offsetY=h.offsetY,this.data.scale=h.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 b extends f{theme="light";onChangeTheme=w.makeHook();definedColors={light:{0:{hue:0,saturation:0,lightness:72},1:{hue:358,saturation:81,lightness:55},2:{hue:19,saturation:87,lightness:58},3:{hue:41,saturation:79,lightness:52},4:{hue:150,saturation:100,lightness:37},5:{hue:221,saturation:100,lightness:59},6:{hue:257,saturation:81,lightness:62}},dark:{0:{hue:0,saturation:0,lightness:40},1:{hue:358,saturation:100,lightness:65},2:{hue:23,saturation:86,lightness:63},3:{hue:39,saturation:91,lightness:70},4:{hue:153,saturation:80,lightness:45},5:{hue:217,saturation:100,lightness:62},6:{hue:259,saturation:100,lightness:75}}};namedColors={light:{dots:"hsla(0, 0%, 72%, 0.4)",text:"rgb(30, 30, 30)",background:"rgb(250, 250, 250)","background-secondary":"rgb(255, 255, 255)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.1)",border:"hsla(0, 0%, 82%, 0.7)"},dark:{dots:"hsla(0, 0%, 40%, 0.3)",text:"rgb(242, 242, 242)",background:"rgb(30, 30, 30)","background-secondary":"rgb(37, 37, 40)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.2)",border:"hsla(0, 0%, 30%, 0.7)"}};colorCache={dark:{},light:{}};constructor(...t){super(...t);const e=this.options.colors;if(e){["light","dark"].forEach(t=>{if(!(t in e))return;const i=e[t];i&&Object.entries(i).forEach(([e,i])=>{if(!i)return;const n=this.namedColors[t],s=this.definedColors[t];if(e in n)n[e]=i;else if(e in s){const t=this.parseColor(i);if(!t)return void console.warn(`[JSON Canvas Viewer] Color ${i} unsupported.`);s[e]=t}})})}this.changeTheme(this.options.theme??"light"),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=e=>{const{hue:i,saturation:n,lightness:s}=e;let o;return o="dark"===this.theme?{active:e,card:{hue:i,saturation:n/3,lightness:s/3},border:{...e,alpha:.7},background:{...e,alpha:.1},text:e.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"}:{active:e,card:0===i?{hue:i,saturation:n,lightness:100}:{hue:i,saturation:.4*n,lightness:90},border:{...e,alpha:.7},background:{...e,alpha:.1},text:e.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"},{active:t(o.active),card:t(o.card),border:t(o.border),background:t(o.background),text:o.text}};parseColor=t=>t.startsWith("rgb")?e(i(t)):t.startsWith("#")?e(n(t)):t.startsWith("hsl")?s(t):void 0;getColor=(t="0")=>{const i=this.theme;let s;return this.colorCache[i][t]?this.colorCache[i][t]:(s=t in this.definedColors[i]?this.hslProcessor(this.definedColors[i][t]):this.hslProcessor(e(n(t))),this.colorCache[i][t]=s,s)};getNamedColor=t=>this.namedColors[this.theme][t];changeTheme=t=>{this.theme=t||("dark"===this.theme?"light":"dark");const e=this.container.get(x).data.container;Object.entries(this.namedColors[this.theme]).forEach(([t,i])=>{e.style.setProperty(`--${t}`,i)}),this.onChangeTheme(this.theme)}}class J extends f{animationId=null;resizeAnimationId=null;DM;SM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};onResize=w.makeHook();onRefresh=w.makeHook();constructor(...t){super(...t),this.DM=this.container.get(x),this.SM=this.container.get(b),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({refresh:this.refresh,onRefresh:this.onRefresh,onResize:this.onResize}),this.onStart(this.start),this.onRestart(this.refresh),this.onDispose(this.dispose)}start=()=>{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,lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY}},this.onRefresh()};onResizeCallback=()=>{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.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}const M={markdown:/\.(md|mdx|markdown|txt)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},y=["markdown","image","audio","video"];class S extends f{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;aborted=!1;eventListeners={};DM;SM;parse;componentDict={text:(t,e)=>{t.classList.add("JCV-markdown-content");const i=document.createElement("div");i.innerHTML=e,i.classList.add("JCV-parsed-content-wrapper"),t.appendChild(i)},markdown:async(t,e)=>{t.classList.add("JCV-markdown-content");const i=document.createElement("div");let n;i.textContent="Loading...",i.classList.add("JCV-parsed-content-wrapper"),t.appendChild(i);try{const t=await fetch(e),i=await t.text(),s=i.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);n=s?await this.parse(s[2]):await this.parse(i)}catch(s){console.error("[JSON Canvas Viewer] Failed to load markdown:",s),n="Failed to load content."}i.innerHTML=n},link:(t,e)=>{const i=document.createElement("iframe");i.src=e,i.sandbox="allow-scripts allow-same-origin",i.className="JCV-link-iframe",i.loading="lazy",t.appendChild(i)},audio:(t,e)=>{const i=document.createElement("audio");i.className="JCV-audio",i.src=e,i.controls=!0,t.appendChild(i)},image:(t,e)=>{const i=document.createElement("img");i.className="JCV-img",i.src=e,i.loading="lazy",t.appendChild(i)},video:(t,e)=>{const i=document.createElement("video");i.className="JCV-video",i.src=e,i.controls=!0,t.appendChild(i)}};get overlaysLayer(){if(!this._overlaysLayer)throw V;return this._overlaysLayer}onInteractionStart=w.makeHook();onInteractionEnd=w.makeHook();onNodeActive=w.makeHook();onNodeLosesActive=w.makeHook();constructor(...t){super(...t),this.parse=this.options.parser||(t=>t),this.DM=this.container.get(x),this.SM=this.container.get(b);this.container.get(J).onRefresh.subscribe(this.updateOverlays),this.SM.onChangeTheme.subscribe(this.themeChanged),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="JCV-overlays",this._overlaysLayer.id="overlays",this.DM.data.container.appendChild(this.overlaysLayer);const e=this.options.nodeComponents;e&&Object.assign(this.componentDict,e),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(k).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{const t=async t=>{switch(t.type){case"text":this.createOverlay(t,await this.parse(t.text),"text");break;case"file":for(const e of y)if(t.file.match(M[e])){this.createOverlay(t,t.file,e);break}break;case"link":this.createOverlay(t,t.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(async e=>{await t(e.ref)})};themeChanged=()=>{Object.values(this.overlays).forEach(t=>{const e=this.DM.data.nodeMap[t.id].ref,i=this.SM.getColor(e.color);this.setOverlayColor(t,i)})};select=t=>{const e=this.selectedId,i=e?this.overlays[e]:null,n=t?this.overlays[t]:null;if(i&&e){i.classList.remove("JCV-active");const t=this.DM.data.nodeMap[e];this.onNodeLosesActive(t.ref),t.onLoseActive?.()}if(n&&t){n.classList.add("JCV-active"),this.onInteractionStart();const e=this.DM.data.nodeMap[t];this.onNodeActive(e.ref),e.onActive?.()}else this.onInteractionEnd();this.selectedId=t};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};createOverlay=(...t)=>{if(this.aborted)return;const e=t[0];let i=this.overlays[e.id];if(!i){if(i=this.constructOverlay(...t),this.aborted)return;this.overlaysLayer.appendChild(i),this.overlays[e.id]=i,i.style.left=`${e.x}px`,i.style.top=`${e.y}px`,i.style.width=`${e.width}px`,i.style.height=`${e.height}px`}};constructOverlay=(...t)=>{const e=t[0],i=document.createElement("div");i.classList.add("JCV-overlay-container"),i.id=e.id,this.setOverlayColor(i,this.SM.getColor(e.color));const n=document.createElement("div");n.classList.add("JCV-content"),i.appendChild(n);const s=document.createElement("div");s.className="JCV-click-layer",i.appendChild(s);const o=document.createElement("div");o.className="JCV-overlay-border",i.appendChild(o);const a=this.DM.data.nodeMap[e.id];a.onActive=w.makeHook(),a.onLoseActive=w.makeHook(),a.onBeforeUnmount=w.makeHook(),this.componentDict[t[2]](n,t[1],t[0],a.onBeforeUnmount,a.onActive,a.onLoseActive);const r=()=>{e.id===this.selectedId&&this.onInteractionStart()},l=()=>{e.id===this.selectedId&&this.onInteractionEnd()};return i.addEventListener("pointerenter",r),i.addEventListener("pointerleave",l),i.addEventListener("touchstart",r),i.addEventListener("touchend",l),this.eventListeners[e.id]=[r,l],i};setOverlayColor=(t,e)=>{Object.entries(e).forEach(([e,i])=>{t.style.setProperty(`--overlay-${e}`,i)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([t,e])=>{if(this.DM.data.nodeMap[t].onBeforeUnmount?.(),this.eventListeners[t]){const i=this.eventListeners[t][0],n=this.eventListeners[t][1];if(!i||!n)throw V;e.removeEventListener("pointerenter",i),e.removeEventListener("pointerleave",n),e.removeEventListener("touchstart",i),e.removeEventListener("touchend",n),this.eventListeners[t][0]=null,this.eventListeners[t][1]=null}e.remove(),delete this.overlays[t]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=null}}class k extends f{pointeract;DM;onClick=w.makeHook();constructor(...t){super(...t),this.DM=this.container.get(x);const e=Object.assign(this.options.pointeract??{},{coordinateOutput:"relative",element:this.DM.data.container,lubricator:{pan:r,zoom:a,drag:o}});this.pointeract=new l(e,[h,c,d,p,m,u]);const i=this.container.get(S);i.onInteractionStart.subscribe(this.stopInteract),i.onInteractionEnd.subscribe(this.startInteract),this.augment({pan:this.pan,panToCoords:this.panToCoords,zoom:this.zoom,zoomToScale:this.zoomToScale}),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.pointeract.on("pan",this.onPan).on("drag",this.onPan).on("zoom",this.onZoom).on("trueClick",this.onTrueClick).start()};startInteract=()=>{this.pointeract.start()};stopInteract=()=>{this.pointeract.stop()};onPan=t=>{this.truePan({x:t.deltaX,y:t.deltaY})};onZoom=t=>{this.trueZoom(t.factor,t)};trueZoom=(t,e)=>{const i=Math.max(Math.min(this.DM.data.scale*t,20),.05);if(i===this.DM.data.scale)return;const n=i/this.DM.data.scale,s=this.C2C(e);this.DM.data.offsetX=e.x-s.x*n,this.DM.data.offsetY=e.y-s.y*n,this.DM.data.scale=i};truePan=({x:t,y:e})=>{this.DM.data.offsetX=this.DM.data.offsetX+t,this.DM.data.offsetY=this.DM.data.offsetY+e};zoom=(t,e)=>{this.pointeract.dispatch("zoom",{factor:t,...e})};pan=({x:t,y:e})=>{this.pointeract.dispatch("pan",{deltaX:t,deltaY:e})};zoomToScale=(t,e)=>{const i=t/this.DM.data.scale;this.pointeract.dispatch("zoom",{factor:i,...e})};panToCoords=({x:t,y:e})=>{this.pointeract.dispatch("pan",{deltaX:t-this.DM.data.offsetX,deltaY:e-this.DM.data.offsetY})};C2C=({x:t,y:e})=>({x:t-this.DM.data.offsetX,y:e-this.DM.data.offsetY});onTrueClick=t=>{const e=t.target;if(this.isUIControl(e))return;const i=this.findNodeId(e);this.onClick(i)};isUIControl=t=>!!t&&(t.closest(".controls")||t.closest("button")||t.closest("input"));findNodeId=t=>{if(!t)return null;let e=t;for(;(!e.id||""===e.id)&&e.parentElement;)e=e.parentElement;return"overlays"!==e.id&&e.id&&""!==e.id?e.id:null};dispose=()=>this.pointeract.dispose()}class O extends f{_canvas;ctx;DM;SM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(!this._canvas)throw V;return this._canvas}constructor(...t){super(...t);const e=this.container.get(J);this.SM=this.container.get(b),e.onRefresh.subscribe(this.redraw),e.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(x),this._canvas=document.createElement("canvas"),this._canvas.className="JCV-main-canvas",this.ctx=this._canvas.getContext("2d"),this.DM.data.container.appendChild(this._canvas),this.onDispose(this.dispose)}optimizeDPR=()=>{const t=this.DM.data.container;w.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{const t=this.DM.data.offsetX,e=this.DM.data.offsetY,i=this.DM.data.scale,n=this.getCurrentViewport(t,e,i);if(!this.options.zoomInOptimization)return void this.trueRedraw(t,e,i,n);this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const s=Date.now();if(this.isInside(n,this.zoomInOptimize.lastDrawnViewport)&&i!==this.zoomInOptimize.lastDrawnScale){if(s-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(t,e,i,n),this.zoomInOptimize.lastCallTime=s,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(n,i)}this.zoomInOptimize.lastCallTime=s,this.trueRedraw(t,e,i,n)};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.drawGridDots(i,t,e),this.ctx.translate(t,e),this.ctx.scale(i,i),Object.values(this.DM.data.nodeMap).forEach(t=>{if(this.isOutside(t.box,n))return;const e=t.ref;"file"===e.type?this.drawFile(t):"group"===e.type&&this.drawGroup(e,i)}),Object.values(this.DM.data.edgeMap).forEach(t=>{this.isOutside(t.box,n)||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})`}isInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;isOutside=(t,e)=>t.right<e.left||t.bottom<e.top||t.left>e.right||t.top>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,o)=>{const a=30*o,r=6*o,l=8*o,h=16*o,c=6*o;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/o,1/o),this.ctx.font=`${h}px 'Inter', sans-serif`;const d=this.ctx.measureText(i).width+2*c;this.ctx.translate(0,-a-l),this.ctx.fillStyle=n,this.ctx.beginPath(),this.ctx.moveTo(r,0),this.ctx.lineTo(d-r,0),this.ctx.quadraticCurveTo(d,0,d,r),this.ctx.lineTo(d,a-r),this.ctx.quadraticCurveTo(d,a,d-r,a),this.ctx.lineTo(r,a),this.ctx.quadraticCurveTo(0,a,0,a-r),this.ctx.lineTo(0,r),this.ctx.quadraticCurveTo(0,0,r,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=s,this.ctx.fillText(i,c,.65*a),this.ctx.restore()};drawNodeBackground=t=>{const e=this.SM.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=e.background,w.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,w.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,e)=>{if(this.drawNodeBackground(t),t.label){const i=this.SM.getColor(t.color);this.drawLabelBar(t.x,t.y,t.label,i.active,i.text,e)}};drawFile=t=>{this.ctx.fillStyle=this.SM.getColor().text;const e=t.ref;this.ctx.font="16px sans-serif",this.ctx.fillText(t.fileName??"",e.x+5,e.y-10)};drawEdge=t=>{const e=t.ref,i=this.DM.data.nodeMap[e.fromNode].ref,n=this.DM.data.nodeMap[e.toNode].ref,s=w.getAnchorCoord,{x:o,y:a}=s(i,e.fromSide),{x:r,y:l}=s(n,e.toSide),h=this.SM.getColor(e.color);let[c,d,p,m]=[0,0,0,0];if(t.controlPoints?[c,d,p,m]=t.controlPoints:([c,d,p,m]=this.getControlPoints(o,a,r,l,e.fromSide,e.toSide),t.controlPoints=[c,d,p,m]),this.drawCurvedPath(o,a,r,l,c,d,p,m,h.active),this.drawArrowhead(r,l,p,m,h.active),e.label){const t=.5,i=(1-t)**3*o+3*(1-t)**2*t*c+3*(1-t)*t*t*p+t**3*r,n=(1-t)**3*a+3*(1-t)**2*t*d+3*(1-t)*t*t*m+t**3*l;this.ctx.font="18px sans-serif";const s=8,u=this.ctx.measureText(e.label).width+2*s,v=20;this.ctx.fillStyle=h.active,this.ctx.beginPath(),w.drawRoundRect(this.ctx,i-u/2,n-v/2-2,u,v,4),this.ctx.fill(),this.ctx.fillStyle=h.text,this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(e.label,i,n-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};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)),h=(c=.5*l,d=60,p=300,Math.max(d,Math.min(p,c)));var c,d,p;let m=t,u=e,v=i,C=n;switch(s){case"top":u=e-h;break;case"bottom":u=e+h;break;case"left":m=t-h;break;case"right":m=t+h}switch(o){case"top":C=n-h;break;case"bottom":C=n+h;break;case"left":v=i-h;break;case"right":v=i+h}return[m,u,v,C]};drawGridDots=(t,e,i)=>{const n=10*2**-Math.floor(Math.log2(t))*t,s=this.canvas.width,o=this.canvas.height,a=e%n,r=i%n;this.ctx.fillStyle=this.SM.getNamedColor("dots");for(let l=a;l<=s;l+=n)for(let t=r;t<=o;t+=n)this.ctx.beginPath(),this.ctx.arc(l,t,1,0,2*Math.PI),this.ctx.fill()};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,h=a/r,c=t-12*l-4*h,d=e-12*h+4*l,p=t-12*l+4*h,m=e-12*h-4*l;this.ctx.beginPath(),this.ctx.fillStyle=s,this.ctx.moveTo(t,e),this.ctx.lineTo(c,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 N=[x,b,J,S,k,O];class z{allModules;IO=null;started=!1;disposed=!1;options;container;onDispose=w.makeHook(!0);onStart=w.makeHook();onRestart=w.makeHook();constructor(t,e){this.container=new v,this.options=t;this.allModules=[...N,...e??[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})}),this.allModules.forEach(t=>{this.container.get(t)});const i=this.options.loading??"normal";"normal"===i?this.load():"lazy"===i&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};augment=t=>{const e=Object.getOwnPropertyDescriptors(t);Object.defineProperties(this,e)};load=t=>{this.disposed||(t&&Object.assign(this.options,t),this.started?this.onRestart():(this.onStart(),this.started=!0))};dispose=()=>{if(!this.started||this.disposed)return;this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.onDispose(),this.container.unbindAll(),this.disposed=!0}}async function _(t){const e=async e=>await async function(t,e){switch(t.type){case"text":return await e(t.text);case"file":return await async function(t,e){if(t.file.match(/\.md$/i))return await 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=o?await e(o[2]):await e(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>`;return""}(t,e);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow">${t.url}</a>`;default:return""}}(e,t.parser??(t=>t)),i=t.canvas.nodes??[],n=t.attachmentDir??"./";i.forEach(e=>{if("file"===e.type&&!e.file.startsWith("http")){const i=e.file.split("/").pop()??"";t.attachments?.[i]?e.file=t.attachments[i]:e.file=n+i}});const s=[];return await Promise.all(i.map(async t=>s.push(await e(t)))),s.join("")}const D='<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 B extends f{_controlsPanel=null;_toggleCollapseBtn=null;_toggleFullscreenBtn=null;_zoomOutBtn=null;_zoomSlider=null;_zoomInBtn=null;_resetViewBtn=null;DM;IH;collapsed;get controlsPanel(){if(null===this._controlsPanel)throw V;return this._controlsPanel}get toggleCollapseBtn(){if(null===this._toggleCollapseBtn)throw V;return this._toggleCollapseBtn}get toggleFullscreenBtn(){if(null===this._toggleFullscreenBtn)throw V;return this._toggleFullscreenBtn}get zoomOutBtn(){if(null===this._zoomOutBtn)throw V;return this._zoomOutBtn}get zoomSlider(){if(null===this._zoomSlider)throw V;return this._zoomSlider}get zoomInBtn(){if(null===this._zoomInBtn)throw V;return this._zoomInBtn}get resetViewBtn(){if(null===this._resetViewBtn)throw V;return this._resetViewBtn}constructor(...t){super(...t),this.collapsed=this.options.controlsCollapsed??!1,this.DM=this.container.get(x),this.IH=this.container.get(k),this.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn),this.container.get(J).onRefresh.subscribe(this.updateSlider),this._controlsPanel=document.createElement("div"),this._controlsPanel.className="JCV-controls",this._controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),w.applyStyles(this._controlsPanel,".JSON-Canvas-Viewer>.JCV-controls{position:absolute;top:10px;right:10px;display:flex;align-items:center;transition:transform .2s;border-radius:8px;gap:10px}.JSON-Canvas-Viewer>.JCV-controls.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-controls .JCV-controls-content{display:flex;gap:1px;align-items:center;border-radius:8px;overflow:hidden;background:var(--border);box-shadow:var(--shadow);outline:1px solid var(--border)}.JSON-Canvas-Viewer>.JCV-controls .JCV-zoom-slider{width:100px;margin:0 10px}"),this._toggleCollapseBtn=document.createElement("button"),this._toggleCollapseBtn.className="JCV-button JCV-collapse-button JCV-border-shadow-bg",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="JCV-controls-content",this._toggleFullscreenBtn=document.createElement("button"),this._toggleFullscreenBtn.className="JCV-button",this._toggleFullscreenBtn.innerHTML=D,e.appendChild(this._toggleFullscreenBtn),this._zoomOutBtn=document.createElement("button"),this.zoomOutBtn.className="JCV-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="JCV-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.className="JCV-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.className="JCV-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),this.augment({toggleControlsCollapse:this.toggleCollapse}),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateSlider()};zoomIn=()=>this.IH.zoom(1.3,this.DM.middleViewer());zoomOut=()=>this.IH.zoom(1/1.3,this.DM.middleViewer());slide=()=>this.IH.trueZoom(1.1**Number(this.zoomSlider.value)/this.DM.data.scale,this.DM.middleViewer());updateFullscreenBtn=t=>{this.toggleFullscreenBtn.innerHTML="enter"===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>':D};toggleFullscreen=()=>this.DM.toggleFullscreen();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 E extends f{_debugPanel=null;DM;get debugPanel(){if(!this._debugPanel)throw V;return this._debugPanel}constructor(...t){super(...t),this.DM=this.container.get(x),this.container.get(J).onRefresh.subscribe(this.update),this._debugPanel=document.createElement("div"),this._debugPanel.className="JCV-debug-panel JCV-border-shadow-bg";const e=this.DM.data.container;w.applyStyles(e,".JSON-Canvas-Viewer>.JCV-debug-panel{position:absolute;bottom:12px;left:12px;border-radius:12px;padding:12px;color:var(--text);font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);pointer-events:none}"),e.appendChild(this._debugPanel),this.onDispose(this.dispose)}update=()=>{const t=w.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 L extends f{_minimapCtx=null;_viewportRectangle=null;_minimap=null;_minimapContainer=null;_toggleMinimapBtn=null;minimapCache={scale:1,centerX:0,centerY:0};DM;SM;collapsed;get minimap(){if(null===this._minimap)throw V;return this._minimap}get minimapCtx(){if(null===this._minimapCtx)throw V;return this._minimapCtx}get viewportRectangle(){if(null===this._viewportRectangle)throw V;return this._viewportRectangle}get minimapContainer(){if(null===this._minimapContainer)throw V;return this._minimapContainer}get toggleMinimapBtn(){if(null===this._toggleMinimapBtn)throw V;return this._toggleMinimapBtn}constructor(...t){super(...t),this.collapsed=this.options.minimapCollapsed??!1,this.container.get(J).onRefresh.subscribe(this.updateViewportRectangle),this.DM=this.container.get(x),this.SM=this.container.get(b),this._minimapContainer=document.createElement("div"),this._minimapContainer.className="JCV-minimap-container",w.applyStyles(this._minimapContainer,".JSON-Canvas-Viewer>.JCV-minimap-container{position:absolute;bottom:10px;right:10px;display:flex;pointer-events:none;transition:transform .2s}.JSON-Canvas-Viewer>.JCV-minimap-container.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-toggle-minimap{margin:auto 10px 0 0;pointer-events:auto}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap{position:relative;pointer-events:none;width:200px;height:150px;overflow:hidden;border-radius:12px;transform-origin:0 0}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-minimap-canvas{width:100%;height:100%}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-viewport-rectangle{position:absolute;top:0;left:0;pointer-events:none;border-radius:6px;box-sizing:border-box;border:2px dashed var(--text)}@container (max-width: 768px){.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap{transform:scale(.6)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px)}.collapsed .JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px) rotate(180deg)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container{transform:translateY(60px) translate(80px)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container.JCV-collapsed{transform:translateY(60px) translate(calc(100% - 32px))}}"),this._toggleMinimapBtn=document.createElement("button"),this._toggleMinimapBtn.className="JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg",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="JCV-minimap JCV-border-shadow-bg";const e=document.createElement("canvas");e.className="JCV-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="JCV-viewport-rectangle",this._minimap.appendChild(this._viewportRectangle),this._minimapContainer.appendChild(this._minimap),this.DM.data.container.appendChild(this._minimapContainer),this._minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this._toggleMinimapBtn.addEventListener("click",this.toggleCollapse),w.resizeCanvasForDPR(e,e.width,e.height),this.augment({toggleMinimapCollapse:this.toggleCollapse}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateViewportRectangle()};start=()=>{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=this.SM.getColor(t.color);this.minimapCtx.fillStyle=e.border,w.drawRoundRect(this.minimapCtx,t.x,t.y,t.width,t.height,25),this.minimapCtx.fill()};drawMinimapEdge=t=>{const e=this.DM.data.nodeMap,i=e[t.fromNode].ref,n=e[t.toNode].ref;if(!i||!n)return;const{x:s,y:o}=w.getAnchorCoord(i,t.fromSide),{x:a,y:r}=w.getAnchorCoord(n,t.toSide);this.minimapCtx.beginPath(),this.minimapCtx.moveTo(s,o),this.minimapCtx.lineTo(a,r),this.minimapCtx.strokeStyle=this.SM.getColor(t.color).active,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,h=n*this.minimapCache.scale,c=s*this.minimapCache.scale;this.viewportRectangle.style.left=`${r}px`,this.viewportRectangle.style.top=`${l}px`,this.viewportRectangle.style.width=`${h}px`,this.viewportRectangle.style.height=`${c}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 T extends f{_preventionContainer=null;preventMt=!1;DM;preventMistouch={record:!1,lastX:0,lastY:0,initialX:0,initialY:0};get preventionContainer(){if(null===this._preventionContainer)throw V;return this._preventionContainer}constructor(...t){super(...t);const e=document.createElement("div");e.className="JCV-prevention-banner JCV-border-shadow-bg",e.textContent=this.options.mistouchPreventerBannerText??"Click on to unlock.",this.DM=this.container.get(x),this._preventionContainer=document.createElement("div"),this._preventionContainer.className="JCV-prevention-container JCV-hidden JCV-full JCV-flex-center",w.applyStyles(this._preventionContainer,".JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-prevention-container{overflow:visible;transition:background .2s,opacity .2s,box-shadow .2s,border .2s,filter .2s,backdrop-filter .2s}.JSON-Canvas-Viewer .JCV-prevention-container.JCV-hidden{pointer-events:none;opacity:0}.JSON-Canvas-Viewer .JCV-prevention-container .JCV-prevention-banner{border-radius:12px;padding:12px;margin:12px;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);text-align:center}"),this._preventionContainer.appendChild(e),this.DM.data.container.appendChild(this._preventionContainer),this.options.preventMistouchAtStart&&this.startPrevention(),window.addEventListener("pointerdown",this.onPointerDown),window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp),this.augment({startMistouchPrevention:this.startPrevention,endMistouchPrevention:this.endPrevention}),this.onDispose(this.dispose)}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("JCV-hidden"),this.DM.data.container.classList.add("JCV-numb"),this.preventMt=!0};endPrevention=()=>{this.preventMt=!1,this.preventionContainer.classList.add("JCV-hidden"),setTimeout(()=>this.DM.data.container.classList.remove("JCV-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 I(t){return C.sanitize(await g(t))}async function P(t){return await fetch(t).then(t=>t.json())}export{f as BaseModule,J as Controller,B as Controls,x as DataManager,E as DebugPanel,k as InteractionHandler,z as JSONCanvasViewer,L as Minimap,T as MistouchPreventer,S as OverlayManager,O as Renderer,b as StyleManager,w as canvasUtils,P as fetchCanvas,I as parser,_ as renderToString};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sources":["../src/kernel/BaseModule.ts","../src/kernel/utilities.ts","../src/kernel/DataManager.ts","../src/kernel/StyleManager.ts","../src/kernel/Controller.ts","../src/kernel/OverlayManager.ts","../src/kernel/InteractionHandler.ts","../src/kernel/Renderer.ts","../src/kernel/index.ts","../src/renderToString.ts","../src/modules/Controls/index.ts","../src/modules/DebugPanel/index.ts","../src/modules/Minimap/index.ts","../src/modules/MistouchPreventer/index.ts","../src/chimp.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { General, GeneralObject, ModuleInput as MI, Orchestratable } from '$/types';\nimport type utilities from '$/utilities';\nimport type { Container } from '@needle-di/core';\n\ntype Hook = ReturnType<typeof utilities.makeHook>;\n\nexport type GeneralModuleCtor = typeof BaseModule<General, General>;\nexport type GeneralModule = BaseModule<General, General>;\n\nexport type ModuleInputCtor = Array<GeneralModuleCtor>;\nexport type ModuleInput = MI<GeneralModuleCtor>;\nexport type Options<M extends ModuleInput> = Orchestratable<M, 'options'>;\nexport type Augmentation<M extends ModuleInput> = Orchestratable<M, '_Augmentation'>;\n\nexport type BaseArgs = ConstructorParameters<GeneralModuleCtor>;\n\nexport class BaseModule<O extends BaseOptions = BaseOptions, A extends GeneralObject = {}> {\n\t// https://github.com/timocov/dts-bundle-generator/issues/360\n\tdeclare private static readonly _BaseModuleBrand: unique symbol; // Nominal marker\n\tdeclare _Augmentation: A;\n\tonStart: Hook['subscribe'];\n\tonRestart: Hook['subscribe'];\n\tonDispose: Hook['subscribe'];\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tonStart: Hook,\n\t\tonDispose: Hook,\n\t\tonRestart: Hook,\n\t\tprotected augment: (aug: A) => void,\n\t) {\n\t\tthis.options = options as O;\n\t\tthis.onStart = onStart.subscribe;\n\t\tthis.onDispose = onDispose.subscribe;\n\t\tthis.onRestart = onRestart.subscribe;\n\t}\n\toptions: O;\n}\n","import type { GeneralArray } from '$/types';\nimport type { JSONCanvasNode } from '@repo/shared';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\n\t\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\",\n);\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 { x: midX, y: node.y };\n\t\tcase 'bottom':\n\t\t\treturn { x: midX, y: node.y + node.height };\n\t\tcase 'left':\n\t\t\treturn { x: node.x, y: midY };\n\t\tcase 'right':\n\t\t\treturn { x: node.x + node.width, y: midY };\n\t\tdefault:\n\t\t\treturn { x: midX, y: midY };\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\ntype MatchingFunc<Args extends GeneralArray> = (...args: Args) => void | Promise<void>;\nexport type Hook<Args extends GeneralArray = [], Async extends boolean = false> = {\n\t(...args: Args): Async extends true ? Promise<void> : void;\n\tsubs: Set<MatchingFunc<Args>>;\n\tsubscribe(callback: MatchingFunc<Args>): void;\n\tunsubscribe(callback: MatchingFunc<Args>): void;\n};\n\n/**\n * A quick function to create a hook that can be subscribed to and unsubscribed from.\n * Pass your arguments as the type parameter\n *\n * @param reverse - Whether the hook should reverse the execution order or not\n * @param async - Whether the hook is async or not\n * @example const hook = makeHook(true);\n */\nexport function makeHook<Args extends GeneralArray = [], Async extends boolean = false>(\n\treverse: boolean = false,\n\tasync: Async = false as Async,\n) {\n\tconst result = (\n\t\tasync\n\t\t\t? async (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) await callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) await callback(...args);\n\t\t\t\t}\n\t\t\t: (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) void callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) void callback(...args);\n\t\t\t\t}\n\t) as Hook<Args, Async>;\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import type { BaseOptions } from '$';\nimport type { Box, NodeBounds } from '$/types';\nimport type { JSONCanvas, JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport style from '$/styles.scss?inline';\nimport utilities, { type Hook } from '$/utilities';\n\nconst INITIAL_VIEWPORT_PADDING = 100;\nconst NODE_LABEL_MARGIN = 40;\nconst EDGE_BOX_HEURISTICS_BASE_MARGIN = 10;\n\ninterface Options extends BaseOptions {\n\tshadowed?: boolean;\n\tcanvas?: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n\tattachments?: Record<string, string>;\n\tnoAttachmentRelocation?: boolean;\n}\n\ninterface Augmentation {\n\tresetView: DataManager['resetView'];\n\ttoggleFullscreen: DataManager['toggleFullscreen'];\n\tonToggleFullscreen: DataManager['onToggleFullscreen'];\n}\n\nexport interface NodeItem {\n\tref: JSONCanvasNode;\n\tbox: Box;\n\tfileName?: string;\n\tonBeforeUnmount?: Hook;\n\tonActive?: Hook;\n\tonLoseActive?: Hook;\n}\n\nexport interface EdgeItem {\n\tref: JSONCanvasEdge;\n\tbox: Box;\n\tcontrolPoints?: Array<number>;\n}\n\ntype NodeMap = Record<string, NodeItem>;\ntype EdgeMap = Record<string, EdgeItem>;\n\nexport default class DataManager extends BaseModule<Options, Augmentation> {\n\tonToggleFullscreen = utilities.makeHook<['enter' | 'exit']>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: NodeMap;\n\t\tedgeMap: EdgeMap;\n\t\tcanvasBaseDir: string;\n\t\tnodeBounds: NodeBounds;\n\t\toffsetX: number;\n\t\toffsetY: number;\n\t\tscale: number;\n\t\tcontainer: HTMLDivElement;\n\t} = {\n\t\tcanvasData: {\n\t\t\tnodes: [],\n\t\t\tedges: [],\n\t\t},\n\t\tnodeMap: {},\n\t\tedgeMap: {},\n\t\tcanvasBaseDir: './',\n\t\tnodeBounds: {\n\t\t\tmaxX: 0,\n\t\t\tmaxY: 0,\n\t\t\tminX: 0,\n\t\t\tminY: 0,\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\tcenterX: 0,\n\t\t\tcenterY: 0,\n\t\t},\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\n\t\tcontainer: document.createElement('div'),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst viewerContainer = this.options.container;\n\t\twhile (viewerContainer.firstElementChild) viewerContainer.firstElementChild.remove();\n\t\tviewerContainer.innerHTML = '';\n\n\t\tconst realContainer = this.options.shadowed\n\t\t\t? viewerContainer.attachShadow({ mode: 'open' })\n\t\t\t: viewerContainer;\n\n\t\tutilities.applyStyles(realContainer, style + this.options.extraCSS);\n\n\t\tthis.data.container.classList.add('JSON-Canvas-Viewer');\n\t\trealContainer.appendChild(this.data.container);\n\n\t\tthis.augment({\n\t\t\tresetView: this.resetView,\n\t\t\ttoggleFullscreen: this.toggleFullscreen,\n\t\t\tonToggleFullscreen: this.onToggleFullscreen,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tconst canvasData = Object.assign(\n\t\t\t{\n\t\t\t\tnodes: [],\n\t\t\t\tedges: [],\n\t\t\t},\n\t\t\tthis.options.canvas,\n\t\t);\n\n\t\tObject.assign(this.data, {\n\t\t\tcanvasData: canvasData,\n\t\t\tnodeMap: {},\n\t\t\tedgeMap: {},\n\t\t\tcanvasBaseDir: this.processBaseDir(this.options.attachmentDir),\n\t\t\tnodeBounds: this.calculateNodeBounds(canvasData),\n\t\t\toffsetX: 0,\n\t\t\toffsetY: 0,\n\t\t\tscale: 1,\n\t\t});\n\n\t\tthis.data.canvasData.nodes.forEach((node) => {\n\t\t\tconst item: NodeItem = {\n\t\t\t\tref: node,\n\t\t\t\tbox: this.getNodeBox(node),\n\t\t\t};\n\t\t\tthis.data.nodeMap[node.id] = item;\n\n\t\t\t// re-process attachments\n\t\t\tif (node.type === 'file') {\n\t\t\t\tconst path = node.file.split('/');\n\t\t\t\tconst fileName = path.pop() ?? '';\n\t\t\t\titem.fileName = fileName;\n\t\t\t\tif (!node.file.startsWith('http://') && !node.file.startsWith('https://')) {\n\t\t\t\t\tconst userDefinedAttachment = this.options.attachments?.[fileName];\n\t\t\t\t\tif (userDefinedAttachment) node.file = userDefinedAttachment;\n\t\t\t\t\telse if (!this.options.noAttachmentRelocation)\n\t\t\t\t\t\tnode.file = this.data.canvasBaseDir + fileName;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.data.canvasData.edges.forEach((edge) => {\n\t\t\tthis.data.edgeMap[edge.id] = {\n\t\t\t\tref: edge,\n\t\t\t\tbox: this.getEdgeBox(edge),\n\t\t\t};\n\t\t});\n\t\tthis.resetView();\n\t};\n\n\tprivate processBaseDir = (baseDir: string | undefined) => {\n\t\tif (!baseDir) return './';\n\t\tconst lastChar = baseDir?.slice(-1);\n\t\tif (lastChar === '/') return baseDir;\n\t\treturn `${baseDir}/`;\n\t};\n\n\tprivate getNodeBox = (node: JSONCanvasNode) => {\n\t\treturn {\n\t\t\tleft: node.x,\n\t\t\ttop:\n\t\t\t\tnode.type === 'file' || node.type === 'group' ? node.y - NODE_LABEL_MARGIN : node.y,\n\t\t\tright: node.width + node.x,\n\t\t\tbottom: node.y + node.height,\n\t\t};\n\t};\n\n\tprivate getEdgeBox = (edge: JSONCanvasEdge) => {\n\t\tconst nodes = this.data.nodeMap;\n\t\tconst from = nodes[edge.fromNode].ref;\n\t\tconst to = nodes[edge.toNode].ref;\n\t\tconst fromAnchor = utilities.getAnchorCoord(from, edge.fromSide);\n\t\tconst toAnchor = utilities.getAnchorCoord(to, edge.toSide);\n\t\tconst strictBox = {\n\t\t\tleft: Math.min(fromAnchor.x, toAnchor.x),\n\t\t\ttop: Math.min(fromAnchor.y, toAnchor.y),\n\t\t\tright: Math.max(fromAnchor.x, toAnchor.x),\n\t\t\tbottom: Math.max(fromAnchor.y, toAnchor.y),\n\t\t};\n\t\t// edge size heuristics\n\t\tconst width = strictBox.right - strictBox.left;\n\t\tconst height = strictBox.bottom - strictBox.top;\n\t\tconst _min = Math.min(width, height);\n\t\tconst min = _min === 0 ? 1 : _min;\n\t\tconst max = Math.max(width, height);\n\t\tconst edgeFactor = Math.log2(max / min);\n\t\tconst margin = edgeFactor * EDGE_BOX_HEURISTICS_BASE_MARGIN;\n\t\treturn {\n\t\t\tleft: strictBox.left - margin,\n\t\t\ttop: strictBox.top - margin,\n\t\t\tright: strictBox.right + margin,\n\t\t\tbottom: strictBox.bottom + margin,\n\t\t};\n\t};\n\n\tprivate calculateNodeBounds(canvasData: Required<JSONCanvas>) {\n\t\tlet minX = Infinity,\n\t\t\tminY = Infinity,\n\t\t\tmaxX = -Infinity,\n\t\t\tmaxY = -Infinity;\n\t\tcanvasData.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\ttoggleFullscreen = async (option?: 'enter' | 'exit') => {\n\t\tif (!document.fullscreenElement && (!option || option === 'enter')) {\n\t\t\tawait this.data.container.requestFullscreen();\n\t\t\tthis.onToggleFullscreen('enter');\n\t\t} else if (document.fullscreenElement && (!option || option === 'exit')) {\n\t\t\tawait document.exitFullscreen();\n\t\t\tthis.onToggleFullscreen('exit');\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\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\tprivate dispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n","import type { BaseOptions } from '$';\nimport { BaseModule, type BaseArgs } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities from '$/utilities';\nimport {\n\tparseHex,\n\ttoHslString,\n\ttype HslColor,\n\trgbToHsl,\n\tparseHsl,\n\tparseRgb,\n} from '@ahmedsemih/color-fns';\n\nexport type Color = {\n\tborder: string;\n\tbackground: string;\n\tactive: string;\n\ttext: string;\n\tcard: string;\n};\n\ntype ColorOptions = {\n\t[K in keyof (StyleManager['definedColors']['light'] &\n\t\tStyleManager['namedColors']['light'])]?: string;\n};\n\ninterface Options extends BaseOptions {\n\ttheme?: 'dark' | 'light';\n\tcolors?: {\n\t\tlight?: ColorOptions;\n\t\tdark?: ColorOptions;\n\t};\n}\n\ninterface Augmentation {\n\tchangeTheme: StyleManager['changeTheme'];\n\tonChangeTheme: StyleManager['onChangeTheme'];\n}\n\nexport default class StyleManager extends BaseModule<Options, Augmentation> {\n\ttheme: 'dark' | 'light' = 'light';\n\tonChangeTheme = utilities.makeHook<['light' | 'dark']>();\n\tdefinedColors = {\n\t\tlight: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 72 },\n\t\t\t'1': { hue: 358, saturation: 81, lightness: 55 },\n\t\t\t'2': { hue: 19, saturation: 87, lightness: 58 },\n\t\t\t'3': { hue: 41, saturation: 79, lightness: 52 },\n\t\t\t'4': { hue: 150, saturation: 100, lightness: 37 },\n\t\t\t'5': { hue: 221, saturation: 100, lightness: 59 },\n\t\t\t'6': { hue: 257, saturation: 81, lightness: 62 },\n\t\t},\n\t\tdark: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 40 },\n\t\t\t'1': { hue: 358, saturation: 100, lightness: 65 },\n\t\t\t'2': { hue: 23, saturation: 86, lightness: 63 },\n\t\t\t'3': { hue: 39, saturation: 91, lightness: 70 },\n\t\t\t'4': { hue: 153, saturation: 80, lightness: 45 },\n\t\t\t'5': { hue: 217, saturation: 100, lightness: 62 },\n\t\t\t'6': { hue: 259, saturation: 100, lightness: 75 },\n\t\t},\n\t};\n\n\tnamedColors = {\n\t\tlight: {\n\t\t\tdots: 'hsla(0, 0%, 72%, 0.4)',\n\t\t\ttext: 'rgb(30, 30, 30)',\n\t\t\tbackground: 'rgb(250, 250, 250)',\n\t\t\t'background-secondary': 'rgb(255, 255, 255)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.1)',\n\t\t\tborder: 'hsla(0, 0%, 82%, 0.7)',\n\t\t},\n\t\tdark: {\n\t\t\tdots: 'hsla(0, 0%, 40%, 0.3)',\n\t\t\ttext: 'rgb(242, 242, 242)',\n\t\t\tbackground: 'rgb(30, 30, 30)',\n\t\t\t'background-secondary': 'rgb(37, 37, 40)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.2)',\n\t\t\tborder: 'hsla(0, 0%, 30%, 0.7)',\n\t\t},\n\t};\n\n\tprivate colorCache: {\n\t\tdark: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t\tlight: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t} = {\n\t\tdark: {},\n\t\tlight: {},\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\n\t\t// user-defined color merging\n\t\tconst colors = this.options.colors;\n\t\tif (colors) {\n\t\t\tconst themes = ['light', 'dark'] as const;\n\t\t\tthemes.forEach((theme) => {\n\t\t\t\tif (!(theme in colors)) return;\n\t\t\t\tconst colorObject = colors[theme];\n\t\t\t\tif (!colorObject) return;\n\t\t\t\tObject.entries(colorObject).forEach(([key, value]) => {\n\t\t\t\t\tif (!value) return;\n\t\t\t\t\tconst namedColorsDict = this.namedColors[theme];\n\t\t\t\t\tconst definedColorsDict = this.definedColors[theme];\n\t\t\t\t\tif (key in namedColorsDict)\n\t\t\t\t\t\tnamedColorsDict[key as keyof typeof namedColorsDict] = value;\n\t\t\t\t\telse if (key in definedColorsDict) {\n\t\t\t\t\t\tconst color = this.parseColor(value);\n\t\t\t\t\t\tif (!color) {\n\t\t\t\t\t\t\tconsole.warn(`[JSON Canvas Viewer] Color ${value} unsupported.`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefinedColorsDict[key as keyof typeof definedColorsDict] = color;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tthis.changeTheme(this.options.theme ?? 'light');\n\t\tthis.augment({\n\t\t\tchangeTheme: this.changeTheme,\n\t\t\tonChangeTheme: this.onChangeTheme,\n\t\t});\n\t}\n\n\tprivate hslProcessor = (color: HslColor) => {\n\t\tconst { hue, saturation, lightness } = color;\n\t\tlet result;\n\t\tif (this.theme === 'dark') {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard: { hue, saturation: saturation / 3, lightness: lightness / 3 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t} else {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard:\n\t\t\t\t\thue === 0\n\t\t\t\t\t\t? { hue, saturation, lightness: 100 }\n\t\t\t\t\t\t: { hue, saturation: saturation * 0.4, lightness: 90 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tactive: toHslString(result.active),\n\t\t\tcard: toHslString(result.card),\n\t\t\tborder: toHslString(result.border),\n\t\t\tbackground: toHslString(result.background),\n\t\t\ttext: result.text,\n\t\t};\n\t};\n\n\tprivate parseColor = (color: string) => {\n\t\tif (color.startsWith('rgb')) return rgbToHsl(parseRgb(color));\n\t\tif (color.startsWith('#')) return rgbToHsl(parseHex(color));\n\t\tif (color.startsWith('hsl')) return parseHsl(color);\n\t};\n\n\tgetColor = (colorIndex: string = '0') => {\n\t\tconst theme = this.theme;\n\t\tlet color: Color;\n\t\tif (this.colorCache[theme][colorIndex]) return this.colorCache[theme][colorIndex];\n\t\telse if (colorIndex in this.definedColors[theme])\n\t\t\tcolor = this.hslProcessor(\n\t\t\t\tthis.definedColors[theme][colorIndex as keyof typeof this.definedColors.dark],\n\t\t\t);\n\t\telse color = this.hslProcessor(rgbToHsl(parseHex(colorIndex)));\n\t\tthis.colorCache[theme][colorIndex] = color;\n\t\treturn color;\n\t};\n\n\tgetNamedColor = (name: keyof typeof this.namedColors.light) =>\n\t\tthis.namedColors[this.theme][name];\n\n\tchangeTheme = (theme?: 'dark' | 'light') => {\n\t\tthis.theme = theme ? theme : this.theme === 'dark' ? 'light' : 'dark';\n\t\tconst container = this.container.get(DataManager).data.container;\n\t\tObject.entries(this.namedColors[this.theme]).forEach(([key, value]) => {\n\t\t\tcontainer.style.setProperty(`--${key}`, value);\n\t\t});\n\t\tthis.onChangeTheme(this.theme);\n\t};\n}\n","import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\n\ninterface Augmentation {\n\trefresh: Controller['refresh'];\n\tonRefresh: Controller['onRefresh'];\n\tonResize: Controller['onResize'];\n}\n\nexport default class Controller extends BaseModule<BaseOptions, Augmentation> {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame: {\n\t\tlastScale: number;\n\t\tlastOffsets: { x: number; y: number };\n\t} = {\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\tonResize = utilities.makeHook<[number, number]>();\n\tonRefresh = utilities.makeHook();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResizeCallback);\n\t\tthis.SM.onChangeTheme.subscribe(this.refresh);\n\t\tthis.augment({\n\t\t\trefresh: this.refresh,\n\t\t\tonRefresh: this.onRefresh,\n\t\t\tonResize: this.onResize,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.refresh);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\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\trefresh = () => {\n\t\tthis.perFrame = {\n\t\t\tlastScale: this.DM.data.scale,\n\t\t\tlastOffsets: { x: this.DM.data.offsetX, y: this.DM.data.offsetY },\n\t\t};\n\t\tthis.onRefresh();\n\t};\n\n\tprivate onResizeCallback = () => {\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.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\tprivate dispose = () => {\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 type { BaseOptions } from '$';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager, { type Color } from '$/StyleManager';\nimport utilities, { destroyError, type Hook } from '$/utilities';\n\ninterface Options extends BaseOptions {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n}\n\ninterface Augmentation {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n}\n\n// TODO: add more formats\nconst fileRegex = {\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (\n\tcontainer: HTMLDivElement,\n\tcontent: string,\n\tnode: N,\n\tonBeforeUnmount: Hook,\n\tonActive: Hook,\n\tonLoseActive: Hook,\n) => void | Promise<void>;\n\ntype CreateOverlayArgs =\n\t| [ComponentNodeMap['text'], string, 'text']\n\t| [ComponentNodeMap['markdown'], string, 'markdown']\n\t| [ComponentNodeMap['image'], string, 'image']\n\t| [ComponentNodeMap['audio'], string, 'audio']\n\t| [ComponentNodeMap['video'], string, 'video']\n\t| [ComponentNodeMap['link'], string, 'link'];\n\ntype ComponentNodeMap = {\n\ttext: JSONCanvasTextNode;\n\tmarkdown: JSONCanvasFileNode;\n\timage: JSONCanvasFileNode;\n\taudio: JSONCanvasFileNode;\n\tvideo: JSONCanvasFileNode;\n\tlink: JSONCanvasLinkNode;\n};\n\ntype ComponentDict = {\n\t[K in keyof ComponentNodeMap]: NodeComponentHook<ComponentNodeMap[K]>;\n};\n\nconst supportedTypes = ['markdown', 'image', 'audio', 'video'] as const;\n\nexport default class OverlayManager extends BaseModule<Options, Augmentation> {\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 aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate parse: Parser;\n\tprivate componentDict: ComponentDict = {\n\t\ttext: (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.innerHTML = content;\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t},\n\t\tmarkdown: async (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.textContent = 'Loading...';\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t\tlet parsedContent: string;\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(content);\n\t\t\t\tconst result = await response.text();\n\t\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\t\tif (frontmatterMatch) parsedContent = await this.parse(frontmatterMatch[2]);\n\t\t\t\telse parsedContent = await this.parse(result);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', err);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\n\t\tlink: (container, content) => {\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.src = content;\n\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\tiframe.className = 'JCV-link-iframe';\n\t\t\tiframe.loading = 'lazy';\n\t\t\tcontainer.appendChild(iframe);\n\t\t},\n\t\taudio: (container, content) => {\n\t\t\tconst audio = document.createElement('audio');\n\t\t\taudio.className = 'JCV-audio';\n\t\t\taudio.src = content;\n\t\t\taudio.controls = true;\n\t\t\tcontainer.appendChild(audio);\n\t\t},\n\t\timage: (container, content) => {\n\t\t\tconst img = document.createElement('img');\n\t\t\timg.className = 'JCV-img';\n\t\t\timg.src = content;\n\t\t\timg.loading = 'lazy';\n\t\t\tcontainer.appendChild(img);\n\t\t},\n\t\tvideo: (container, content) => {\n\t\t\tconst video = document.createElement('video');\n\t\t\tvideo.className = 'JCV-video';\n\t\t\tvideo.src = content;\n\t\t\tvideo.controls = true;\n\t\t\tcontainer.appendChild(video);\n\t\t},\n\t};\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\tonInteractionStart = utilities.makeHook();\n\tonInteractionEnd = utilities.makeHook();\n\tonNodeActive = utilities.makeHook<[JSONCanvasNode]>();\n\tonNodeLosesActive = utilities.makeHook<[JSONCanvasNode]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.parser || ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.onRefresh.subscribe(this.updateOverlays);\n\t\tthis.SM.onChangeTheme.subscribe(this.themeChanged);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'JCV-overlays';\n\t\tthis._overlaysLayer.id = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tconst components = this.options.nodeComponents;\n\t\tif (components) Object.assign(this.componentDict, components);\n\n\t\tthis.augment({\n\t\t\tonNodeActive: this.onNodeActive,\n\t\t\tonNodeLosesActive: this.onNodeLosesActive,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.restart);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate renderOverlays = () => {\n\t\tconst overlayMatcher = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.createOverlay(node, await this.parse(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\tfor (const type of supportedTypes) {\n\t\t\t\t\t\tif (!node.file.match(fileRegex[type])) continue;\n\t\t\t\t\t\tthis.createOverlay(node, node.file, type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.createOverlay(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(async (node) => {\n\t\t\tawait overlayMatcher(node.ref);\n\t\t});\n\t};\n\n\tprivate themeChanged = () => {\n\t\tObject.values(this.overlays).forEach((overlay) => {\n\t\t\tconst node = this.DM.data.nodeMap[overlay.id].ref;\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.setOverlayColor(overlay, color);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = !previousId ? null : this.overlays[previousId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous && previousId) {\n\t\t\tprevious.classList.remove('JCV-active');\n\t\t\tconst nodeItem = this.DM.data.nodeMap[previousId];\n\t\t\tthis.onNodeLosesActive(nodeItem.ref);\n\t\t\tnodeItem.onLoseActive?.();\n\t\t}\n\t\tif (current && id) {\n\t\t\tcurrent.classList.add('JCV-active');\n\t\t\tthis.onInteractionStart();\n\t\t\tconst nodeItem = this.DM.data.nodeMap[id];\n\t\t\tthis.onNodeActive(nodeItem.ref);\n\t\t\tnodeItem.onActive?.();\n\t\t} else this.onInteractionEnd();\n\t\tthis.selectedId = id;\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 createOverlay = (...args: CreateOverlayArgs) => {\n\t\tif (this.aborted) return;\n\t\tconst node = args[0];\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = this.constructOverlay(...args);\n\t\t\tif (this.aborted) return;\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}\n\t};\n\n\tprivate constructOverlay = (...args: CreateOverlayArgs) => {\n\t\tconst node = args[0];\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('JCV-overlay-container');\n\t\toverlay.id = node.id;\n\t\tthis.setOverlayColor(overlay, this.SM.getColor(node.color));\n\t\tconst contentWrapper = document.createElement('div');\n\t\tcontentWrapper.classList.add('JCV-content');\n\t\toverlay.appendChild(contentWrapper);\n\t\tconst clickLayer = document.createElement('div');\n\t\tclickLayer.className = 'JCV-click-layer';\n\t\toverlay.appendChild(clickLayer);\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'JCV-overlay-border';\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst nodeItem = this.DM.data.nodeMap[node.id];\n\n\t\tnodeItem.onActive = utilities.makeHook();\n\t\tnodeItem.onLoseActive = utilities.makeHook();\n\t\tnodeItem.onBeforeUnmount = utilities.makeHook();\n\n\t\tvoid this.componentDict[args[2]](\n\t\t\tcontentWrapper,\n\t\t\targs[1],\n\t\t\targs[0] as never,\n\t\t\tnodeItem.onBeforeUnmount,\n\t\t\tnodeItem.onActive,\n\t\t\tnodeItem.onLoseActive,\n\t\t);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.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\tprivate setOverlayColor = (overlay: HTMLDivElement, color: Color) => {\n\t\tObject.entries(color).forEach(([key, value]) => {\n\t\t\toverlay.style.setProperty(`--overlay-${key}`, value);\n\t\t});\n\t};\n\n\tprivate clearOverlays = () => {\n\t\tObject.entries(this.overlays).forEach(([id, overlay]) => {\n\t\t\tthis.DM.data.nodeMap[id].onBeforeUnmount?.();\n\t\t\tif (this.eventListeners[id]) {\n\t\t\t\tconst onStart = this.eventListeners[id][0];\n\t\t\t\tconst onEnd = this.eventListeners[id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\toverlay.removeEventListener('pointerenter', onStart);\n\t\t\t\toverlay.removeEventListener('pointerleave', onEnd);\n\t\t\t\toverlay.removeEventListener('touchstart', onStart);\n\t\t\t\toverlay.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[id][0] = null;\n\t\t\t\tthis.eventListeners[id][1] = null;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import type { BaseOptions } from '$';\nimport type { Coordinates } from '$/types';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport OverlayManager from '$/OverlayManager';\nimport utilities from '$/utilities';\nimport {\n\tClick,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype Events,\n\tWheelPanZoom,\n\tLubricator,\n\tpanPreset as pan,\n\tzoomPreset as zoom,\n\tdragPreset as drag,\n\ttype PointeractInterface,\n} from 'pointeract';\n\ntype LoadedModules = [Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom, Lubricator];\n\ntype LoadedEvents = Events<LoadedModules>;\n\ninterface Options extends BaseOptions {\n\tpointeract?: PointeractOptions<LoadedModules>;\n}\n\ninterface Augmentation {\n\tpan: InteractionHandler['pan'];\n\tpanToCoords: InteractionHandler['panToCoords'];\n\tzoom: InteractionHandler['zoom'];\n\tzoomToScale: InteractionHandler['zoomToScale'];\n}\n\nexport default class InteractionHandler extends BaseModule<Options, Augmentation> {\n\tpointeract: PointeractInterface<LoadedModules>;\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\telement: this.DM.data.container,\n\t\t\tlubricator: { pan, zoom, drag },\n\t\t} satisfies PointeractOptions<LoadedModules>);\n\t\tthis.pointeract = new Pointeract(options, [\n\t\t\tClick,\n\t\t\tDrag,\n\t\t\tWheelPanZoom,\n\t\t\tPreventDefault,\n\t\t\tMultitouchPanZoom,\n\t\t\tLubricator,\n\t\t]);\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.onInteractionStart.subscribe(this.stopInteract);\n\t\tOM.onInteractionEnd.subscribe(this.startInteract);\n\n\t\tthis.augment({\n\t\t\tpan: this.pan,\n\t\t\tpanToCoords: this.panToCoords,\n\t\t\tzoom: this.zoom,\n\t\t\tzoomToScale: this.zoomToScale,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.pointeract\n\t\t\t.on('pan', this.onPan)\n\t\t\t.on('drag', this.onPan)\n\t\t\t.on('zoom', this.onZoom)\n\t\t\t.on('trueClick', this.onTrueClick)\n\t\t\t.start();\n\t};\n\n\tprivate startInteract = () => {\n\t\tthis.pointeract.start();\n\t};\n\tprivate stopInteract = () => {\n\t\tthis.pointeract.stop();\n\t};\n\n\tprivate onPan = (event: LoadedEvents['pan']) => {\n\t\tthis.truePan({\n\t\t\tx: event.deltaX,\n\t\t\ty: event.deltaY,\n\t\t});\n\t};\n\tprivate onZoom = (event: LoadedEvents['zoom']) => {\n\t\tthis.trueZoom(event.factor, event);\n\t};\n\n\ttrueZoom = (_factor: number, origin: Coordinates) => {\n\t\tconst newScale = Math.max(Math.min(this.DM.data.scale * _factor, 20), 0.05);\n\t\tconst scale = this.DM.data.scale;\n\t\tif (newScale === scale) return;\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.DM.data.offsetX = origin.x - canvasCoords.x * factor;\n\t\tthis.DM.data.offsetY = origin.y - canvasCoords.y * factor;\n\t\tthis.DM.data.scale = newScale;\n\t};\n\ttruePan = ({ x, y }: Coordinates) => {\n\t\tthis.DM.data.offsetX = this.DM.data.offsetX + x;\n\t\tthis.DM.data.offsetY = this.DM.data.offsetY + y;\n\t};\n\n\tzoom = (_factor: number, origin: Coordinates) => {\n\t\tthis.pointeract.dispatch('zoom', { factor: _factor, ...origin });\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', { deltaX: x, deltaY: y });\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tthis.pointeract.dispatch('zoom', { factor, ...origin });\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', {\n\t\t\tdeltaX: x - this.DM.data.offsetX,\n\t\t\tdeltaY: y - this.DM.data.offsetY,\n\t\t});\n\t};\n\n\t// Container Coords to Canvas Coords relative to the top-left corner of the scaled canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.DM.data.offsetX,\n\t\ty: containerY - this.DM.data.offsetY,\n\t});\n\n\tprivate onTrueClick = (e: LoadedEvents['trueClick']) => {\n\t\tconst element = e.target as HTMLElement | null;\n\t\tif (this.isUIControl(element)) return;\n\t\tconst node = this.findNodeId(element);\n\t\tthis.onClick(node);\n\t};\n\n\tprivate isUIControl = (target: HTMLElement | null) => {\n\t\tif (!target) return false;\n\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t};\n\n\tprivate findNodeId = (element: HTMLElement | null) => {\n\t\tif (!element) return null;\n\t\tlet ele = element;\n\t\twhile (!ele.id || ele.id === '') {\n\t\t\tif (!ele.parentElement) break;\n\t\t\tele = ele.parentElement;\n\t\t}\n\t\tif (ele.id === 'overlays' || !ele.id || ele.id === '') return null;\n\t\treturn ele.id;\n\t};\n\n\tprivate dispose = () => this.pointeract.dispose();\n}\n","import type { BaseOptions } from '$';\nimport type { Box } from '$/types';\nimport type { JSONCanvasGroupNode, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager, { type EdgeItem, type NodeItem } from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 4;\nconst NODE_RADIUS = 12;\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\nconst NODE_BORDER_WIDTH = 2;\nconst DOT_RADIUS = 1; // Dot radius in CSS pixels\nconst DOT_BASE_GAP = 10; // Base gap between dots in CSS pixels\n\nconst NODE_BORDER_HALF_WIDTH = NODE_BORDER_WIDTH / 2;\n\ninterface Options extends BaseOptions {\n\tzoomInOptimization?: boolean;\n}\n\nexport default class Renderer extends BaseModule<Options> {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: Box;\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) 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\tthis.SM = this.container.get(StyleManager);\n\t\tcontroller.onRefresh.subscribe(this.redraw);\n\t\tcontroller.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'JCV-main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t\tthis.onDispose(this.dispose);\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\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 (!this.options.zoomInOptimization) {\n\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\treturn;\n\t\t}\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\tif (\n\t\t\tthis.isInside(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: Box) {\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.drawGridDots(scale, offsetX, offsetY);\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tObject.values(this.DM.data.nodeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tconst node = item.ref;\n\t\t\tif (node.type === 'file') this.drawFile(item);\n\t\t\telse if (node.type === 'group') this.drawGroup(node, scale);\n\t\t});\n\t\tObject.values(this.DM.data.edgeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tthis.drawEdge(item);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: Box, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX =\n\t\t\t(this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY =\n\t\t\t(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 isInside = (inner: Box, outer: Box) =>\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 isOutside = (inner: Box, outer: Box) =>\n\t\tinner.right < outer.left ||\n\t\tinner.bottom < outer.top ||\n\t\tinner.left > outer.right ||\n\t\tinner.top > 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 = (\n\t\tx: number,\n\t\ty: number,\n\t\tlabel: string,\n\t\tcolor: string,\n\t\ttextColor: string,\n\t\tscale: number,\n\t) => {\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 = textColor;\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 = this.SM.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(\n\t\t\tthis.ctx,\n\t\t\tnode.x + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.y + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.width - NODE_BORDER_WIDTH,\n\t\t\tnode.height - NODE_BORDER_WIDTH,\n\t\t\tradius,\n\t\t);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = NODE_BORDER_WIDTH;\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\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, color.active, color.text, scale);\n\t\t}\n\t};\n\n\tprivate drawFile = (item: NodeItem) => {\n\t\tthis.ctx.fillStyle = this.SM.getColor().text;\n\t\tconst node = item.ref;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(item.fileName ?? '', node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (item: EdgeItem) => {\n\t\tconst edge = item.ref;\n\t\tconst fromNode = this.DM.data.nodeMap[edge.fromNode].ref;\n\t\tconst toNode = this.DM.data.nodeMap[edge.toNode].ref;\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst { x: startX, y: startY } = gac(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = gac(toNode, edge.toSide);\n\t\tconst color = this.SM.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!item.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\titem.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = item.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\tcolor.active,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, color.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 = color.active;\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 = color.text;\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 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 drawGridDots = (scale: number, offsetX: number, offsetY: number) => {\n\t\tconst scaleLevel = -Math.floor(Math.log2(scale));\n\t\tconst actualGap = DOT_BASE_GAP * 2 ** scaleLevel * scale;\n\t\tconst width = this.canvas.width;\n\t\tconst height = this.canvas.height;\n\t\tconst startX = offsetX % actualGap;\n\t\tconst startY = offsetY % actualGap;\n\t\tthis.ctx.fillStyle = this.SM.getNamedColor('dots');\n\t\tfor (let x = startX; x <= width; x += actualGap) {\n\t\t\tfor (let y = startY; y <= height; y += actualGap) {\n\t\t\t\tthis.ctx.beginPath();\n\t\t\t\tthis.ctx.arc(x, y, DOT_RADIUS, 0, 2 * Math.PI);\n\t\t\t\tthis.ctx.fill();\n\t\t\t}\n\t\t}\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 = (\n\t\ttipX: number,\n\t\ttipY: number,\n\t\tfromX: number,\n\t\tfromY: number,\n\t\tcolor: string,\n\t) => {\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\tprivate dispose = () => {\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 {\n\tModuleInputCtor,\n\tModuleInput,\n\tOptions,\n\tAugmentation,\n\tGeneralModuleCtor,\n} from '$/BaseModule';\nimport type { GeneralObject } from '$/types';\nimport type { JSONCanvas } from '@repo/shared';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\nimport { Container } from '@needle-di/core';\n\nexport interface BaseOptions {\n\tcontainer: HTMLElement;\n\tloading?: 'normal' | 'lazy' | 'none';\n}\n\nconst internalModules = [\n\tDataManager,\n\tStyleManager,\n\tController,\n\tOverlayManager,\n\tInteractionHandler,\n\tRenderer,\n];\n\ntype InternalModules = typeof internalModules;\n\nexport type AllOptions<M extends ModuleInput = []> = Options<M> & Options<InternalModules>;\ntype AllAugmentation<M extends ModuleInput = []> = Augmentation<M> & Augmentation<InternalModules>;\n\nclass JSONCanvasViewer<M extends ModuleInputCtor> {\n\tprivate allModules: ModuleInputCtor;\n\tprivate IO: IntersectionObserver | null = null;\n\tprivate started = false;\n\tprivate disposed = false;\n\toptions: AllOptions<M>;\n\tcontainer: Container;\n\tonDispose = utilities.makeHook(true);\n\tonStart = utilities.makeHook();\n\tonRestart = utilities.makeHook();\n\n\tconstructor(options: AllOptions<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: () =>\n\t\t\t\t\tnew Class(\n\t\t\t\t\t\tthis.container,\n\t\t\t\t\t\tthis.options,\n\t\t\t\t\t\tthis.onStart,\n\t\t\t\t\t\tthis.onDispose,\n\t\t\t\t\t\tthis.onRestart,\n\t\t\t\t\t\tthis.augment,\n\t\t\t\t\t),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [...internalModules, ...(modules ?? [])];\n\t\tthis.allModules.forEach(bind);\n\t\tthis.allModules.forEach((Module) => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\n\t\tconst loading = this.options.loading ?? 'normal';\n\t\tif (loading === 'normal') this.load();\n\t\telse if (loading === 'lazy') {\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}\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\tprivate augment = (aug: GeneralObject) => {\n\t\tconst descriptors = Object.getOwnPropertyDescriptors(aug);\n\t\tObject.defineProperties(this, descriptors);\n\t};\n\n\tload = (options?: {\n\t\tcanvas?: JSONCanvas;\n\t\tattachmentDir?: string;\n\t\tattachments?: Record<string, string>;\n\t}) => {\n\t\tif (this.disposed) return;\n\t\tif (options) Object.assign(this.options, options);\n\t\tif (this.started) this.onRestart();\n\t\telse {\n\t\t\tthis.onStart();\n\t\t\tthis.started = true;\n\t\t}\n\t};\n\n\tdispose = () => {\n\t\tif (!this.started || this.disposed) return;\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.onDispose();\n\t\tthis.container.unbindAll();\n\t\tthis.disposed = true;\n\t};\n}\n\ntype JSONCanvasViewerType = new <M extends ModuleInputCtor = []>(\n\t...args: ConstructorParameters<typeof JSONCanvasViewer<M>>\n) => JSONCanvasViewer<M> & AllAugmentation<M>;\n\nexport type JSONCanvasViewerInterface<M extends ModuleInput = []> = JSONCanvasViewer<never> &\n\tAllAugmentation<M>;\n\nexport default JSONCanvasViewer as JSONCanvasViewerType;\n","import type { JSONCanvas, JSONCanvasFileNode, JSONCanvasNode, Parser } from '@repo/shared';\n\nexport default async function (options: {\n\tcanvas: JSONCanvas;\n\tattachments?: Record<string, string>;\n\tattachmentDir?: string;\n\tparser?: Parser;\n}) {\n\tconst render = async (node: JSONCanvasNode) =>\n\t\tawait renderer(node, options.parser ?? ((markdown: string) => markdown));\n\tconst nodes = options.canvas.nodes ?? [];\n\tconst basePath = options.attachmentDir ?? './';\n\tnodes.forEach((node) => {\n\t\tif (node.type === 'file' && !node.file.startsWith('http')) {\n\t\t\tconst file = node.file.split('/');\n\t\t\tconst name = file.pop() ?? '';\n\t\t\tif (options.attachments?.[name]) node.file = options.attachments[name];\n\t\t\telse node.file = basePath + name;\n\t\t}\n\t});\n\tconst renderedContent: Array<string> = [];\n\tawait Promise.all(nodes.map(async (node) => renderedContent.push(await render(node))));\n\treturn renderedContent.join('');\n}\n\nasync function renderer(node: JSONCanvasNode, parse: Parser) {\n\tswitch (node.type) {\n\t\tcase 'text':\n\t\t\treturn await parse(node.text);\n\t\tcase 'file':\n\t\t\treturn await fileProcessor(node, parse);\n\t\tcase 'link':\n\t\t\treturn `<a href=\"${node.url}\" target=\"_blank\" rel=\"nofollow\">${node.url}</a>`;\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n\nasync function fileProcessor(node: JSONCanvasFileNode, parse: Parser) {\n\tif (node.file.match(/\\.md$/i)) return await 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\treturn '';\n}\n\nasync function loadMarkdown(path: string, parse: Parser) {\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 = await parse(frontmatterMatch[2]);\n\t\telse parsedContent = await parse(result);\n\t} catch {\n\t\tparsedContent = 'Failed to load content.';\n\t}\n\treturn parsedContent;\n}\n","import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tcontrolsCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleControlsCollapse: Controls['toggleCollapse'];\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, Augmentation> {\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 IH: InteractionHandler;\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.IH = this.container.get(InteractionHandler);\n\t\tthis.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn);\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.updateSlider);\n\n\t\tthis._controlsPanel = document.createElement('div');\n\t\tthis._controlsPanel.className = 'JCV-controls';\n\t\tthis._controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\n\t\tutilities.applyStyles(this._controlsPanel, style);\n\n\t\tthis._toggleCollapseBtn = document.createElement('button');\n\t\tthis._toggleCollapseBtn.className = 'JCV-button JCV-collapse-button JCV-border-shadow-bg';\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 = 'JCV-controls-content';\n\n\t\tthis._toggleFullscreenBtn = document.createElement('button');\n\t\tthis._toggleFullscreenBtn.className = 'JCV-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.className = 'JCV-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 = 'JCV-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.className = 'JCV-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.className = 'JCV-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\n\t\tthis.augment({ toggleControlsCollapse: this.toggleCollapse });\n\t\tthis.onDispose(this.dispose);\n\t}\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateSlider();\n\t};\n\tprivate zoomIn = () => this.IH.zoom(1.3, this.DM.middleViewer());\n\tprivate zoomOut = () => this.IH.zoom(1 / 1.3, this.DM.middleViewer());\n\tprivate slide = () =>\n\t\tthis.IH.trueZoom(\n\t\t\t1.1 ** Number(this.zoomSlider.value) / this.DM.data.scale,\n\t\t\tthis.DM.middleViewer(),\n\t\t);\n\n\tprivate updateFullscreenBtn = (enter: 'enter' | 'exit') => {\n\t\tif (enter === 'enter') this.toggleFullscreenBtn.innerHTML = exitFullscreenIcon;\n\t\telse this.toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t};\n\tprivate toggleFullscreen = () => this.DM.toggleFullscreen();\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\tprivate dispose = () => {\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","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).onRefresh.subscribe(this.update);\n\t\tthis._debugPanel = document.createElement('div');\n\t\tthis._debugPanel.className = 'JCV-debug-panel JCV-border-shadow-bg';\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tutilities.applyStyles(HTMLContainer, style);\n\t\tHTMLContainer.appendChild(this._debugPanel);\n\t\tthis.onDispose(this.dispose);\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\tprivate dispose = () => {\n\t\tthis.debugPanel.remove();\n\t\tthis._debugPanel = null;\n\t};\n}\n","import type { BaseOptions } from '$';\nimport type { JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tminimapCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleMinimapCollapse: Minimap['toggleCollapse'];\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, Augmentation> {\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 SM: StyleManager;\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).onRefresh.subscribe(this.updateViewportRectangle);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\n\t\tthis._minimapContainer = document.createElement('div');\n\t\tthis._minimapContainer.className = 'JCV-minimap-container';\n\n\t\tutilities.applyStyles(this._minimapContainer, style);\n\n\t\tthis._toggleMinimapBtn = document.createElement('button');\n\t\tthis._toggleMinimapBtn.className =\n\t\t\t'JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg';\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 = 'JCV-minimap JCV-border-shadow-bg';\n\t\tconst minimapCanvas = document.createElement('canvas');\n\t\tminimapCanvas.className = 'JCV-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 = 'JCV-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('JCV-collapsed', this.collapsed);\n\n\t\tthis._toggleMinimapBtn.addEventListener('click', this.toggleCollapse);\n\t\tutilities.resizeCanvasForDPR(minimapCanvas, minimapCanvas.width, minimapCanvas.height);\n\n\t\tthis.augment({ toggleMinimapCollapse: this.toggleCollapse });\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.minimapContainer.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateViewportRectangle();\n\t};\n\n\tprivate start = () => {\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 = this.SM.getColor(node.color);\n\t\tconst radius = 25;\n\t\tthis.minimapCtx.fillStyle = colors.border;\n\t\tutilities.drawRoundRect(this.minimapCtx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.minimapCtx.fill();\n\t};\n\n\tprivate drawMinimapEdge = (edge: JSONCanvasEdge) => {\n\t\tconst canvasMap = this.DM.data.nodeMap;\n\t\tconst fromNode = canvasMap[edge.fromNode].ref;\n\t\tconst toNode = canvasMap[edge.toNode].ref;\n\t\tif (!fromNode || !toNode) return;\n\t\tconst { x: startX, y: startY } = utilities.getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: 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 = this.SM.getColor(edge.color).active;\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 =\n\t\t\t-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\tprivate dispose = () => {\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 { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tpreventMistouchAtStart?: boolean;\n\tmistouchPreventerBannerText?: string;\n}\n\ninterface Augmentation {\n\tstartMistouchPrevention: MistouchPreventer['startPrevention'];\n\tendMistouchPrevention: MistouchPreventer['endPrevention'];\n}\n\nexport default class MistouchPreventer extends BaseModule<Options, Augmentation> {\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\n\t\tconst preventionBanner = document.createElement('div');\n\t\tpreventionBanner.className = 'JCV-prevention-banner JCV-border-shadow-bg';\n\t\tpreventionBanner.textContent =\n\t\t\tthis.options.mistouchPreventerBannerText ?? 'Click on to unlock.';\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._preventionContainer = document.createElement('div');\n\t\tthis._preventionContainer.className =\n\t\t\t'JCV-prevention-container JCV-hidden JCV-full JCV-flex-center';\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 (this.options.preventMistouchAtStart) 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\n\t\tthis.augment({\n\t\t\tstartMistouchPrevention: this.startPrevention,\n\t\t\tendMistouchPrevention: this.endPrevention,\n\t\t});\n\t\tthis.onDispose(this.dispose);\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('JCV-hidden');\n\t\tthis.DM.data.container.classList.add('JCV-numb');\n\t\tthis.preventMt = true;\n\t};\n\n\tendPrevention = () => {\n\t\tthis.preventMt = false;\n\t\tthis.preventionContainer.classList.add('JCV-hidden');\n\t\tsetTimeout(() => this.DM.data.container.classList.remove('JCV-numb'), 50); // minimum delay to prevent triggering undesired button touch\n\t};\n\n\tprivate dispose = () => {\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","export { default as Controls } from '@/modules/Controls';\nexport { default as DebugPanel } from '@/modules/DebugPanel';\nexport { default as Minimap } from '@/modules/Minimap';\nexport { default as MistouchPreventer } from '@/modules/MistouchPreventer';\nexport { default as JSONCanvasViewer } from '$';\nimport type { JSONCanvas } from '@repo/shared';\nimport purify from 'dompurify';\nimport { marked } from 'marked';\n\nexport async function parser(markdown: string) {\n\treturn purify.sanitize(await marked(markdown));\n}\n\nexport async function fetchCanvas(path: `${string}.canvas` | `${string}.json`) {\n\treturn (await fetch(path).then((res) => res.json())) as JSONCanvas;\n}\n"],"names":["BaseModule","constructor","container","options","onStart","onDispose","onRestart","augment","this","subscribe","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","makeHook","reverse","async","result","args","items","Array","from","subs","callback","Set","add","unsubscribe","delete","destroyError","DataManager","onToggleFullscreen","data","canvasData","nodes","edges","nodeMap","edgeMap","canvasBaseDir","nodeBounds","maxX","maxY","minX","minY","centerX","centerY","offsetX","offsetY","super","viewerContainer","firstElementChild","remove","realContainer","shadowed","attachShadow","mode","extraCSS","classList","resetView","toggleFullscreen","start","dispose","Object","assign","processBaseDir","attachmentDir","calculateNodeBounds","forEach","item","ref","box","getNodeBox","id","type","fileName","file","split","pop","startsWith","userDefinedAttachment","attachments","noAttachmentRelocation","edge","getEdgeBox","baseDir","lastChar","slice","left","top","right","bottom","fromNode","to","toNode","fromAnchor","fromSide","toAnchor","toSide","strictBox","min","max","_min","margin","log2","Infinity","option","fullscreenElement","exitFullscreen","requestFullscreen","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","newScale","initialView","middleViewer","StyleManager","theme","onChangeTheme","definedColors","light","hue","saturation","lightness","dark","namedColors","dots","text","background","shadow","border","colorCache","colors","colorObject","entries","key","value","namedColorsDict","definedColorsDict","color","parseColor","console","warn","changeTheme","hslProcessor","active","card","alpha","toHslString","rgbToHsl","parseRgb","parseHex","parseHsl","getColor","colorIndex","getNamedColor","name","get","setProperty","Controller","animationId","resizeAnimationId","DM","SM","resizeObserver","perFrame","lastScale","lastOffsets","lastResizeCenter","onResize","onRefresh","ResizeObserver","onResizeCallback","refresh","observe","requestAnimationFrame","draw","center","cancelAnimationFrame","disconnect","fileRegex","markdown","image","audio","video","supportedTypes","OverlayManager","_overlaysLayer","overlays","selectedId","aborted","eventListeners","parse","componentDict","content","parsedContentWrapper","parsedContent","textContent","response","fetch","frontmatterMatch","match","err","error","link","iframe","src","sandbox","className","loading","controls","img","overlaysLayer","onInteractionStart","onInteractionEnd","onNodeActive","onNodeLosesActive","parser","updateOverlays","themeChanged","components","nodeComponents","restart","InteractionHandler","onClick","select","renderOverlays","clearOverlays","overlayMatcher","createOverlay","url","values","overlay","setOverlayColor","previousId","previous","current","nodeItem","onLoseActive","onActive","transform","element","constructOverlay","contentWrapper","clickLayer","overlayBorder","onBeforeUnmount","onEnd","addEventListener","removeEventListener","pointeract","coordinateOutput","lubricator","pan","zoom","drag","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","Lubricator","OM","stopInteract","startInteract","panToCoords","zoomToScale","on","onPan","onZoom","onTrueClick","stop","event","truePan","deltaX","deltaY","trueZoom","_factor","origin","canvasCoords","C2C","dispatch","containerX","containerY","e","target","isUIControl","findNodeId","closest","ele","parentElement","Renderer","_canvas","zoomInOptimize","lastDrawnScale","lastDrawnViewport","timeout","lastCallTime","controller","redraw","optimizeDPR","offsetWidth","offsetHeight","currentViewport","getCurrentViewport","zoomInOptimization","trueRedraw","clearTimeout","now","Date","isInside","setTimeout","fakeRedraw","clearRect","save","drawGridDots","translate","isOutside","drawFile","drawGroup","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","drawLabelBar","label","textColor","barHeight","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","fill","fillText","drawNodeBackground","globalAlpha","NODE_BORDER_WIDTH","strokeStyle","lineWidth","stroke","gac","startX","startY","endX","endY","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","abs","PADDING","val","actualGap","floor","arc","PI","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","length","sqrt","unitX","unitY","leftX","leftY","rightX","rightY","internalModules","JSONCanvasViewer","allModules","IO","started","disposed","modules","Container","Class","bind","provide","useFactory","Module","load","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","entry","isIntersecting","aug","descriptors","getOwnPropertyDescriptors","defineProperties","firstChild","unbindAll","renderToString","render","path","loadMarkdown","fileProcessor","renderer","basePath","renderedContent","Promise","all","map","push","join","enterFullscreenIcon","Controls","_controlsPanel","_toggleCollapseBtn","_toggleFullscreenBtn","_zoomOutBtn","_zoomSlider","_zoomInBtn","_resetViewBtn","IH","collapsed","controlsPanel","toggleCollapseBtn","toggleFullscreenBtn","zoomOutBtn","zoomSlider","zoomInBtn","resetViewBtn","controlsCollapsed","updateFullscreenBtn","updateSlider","toggle","controlsContent","toggleCollapse","zoomIn","zoomOut","slide","toggleControlsCollapse","Number","enter","String","scaleToSlider","log","DebugPanel","_debugPanel","debugPanel","update","HTMLContainer","Minimap","_minimapCtx","_viewportRectangle","_minimap","_minimapContainer","_toggleMinimapBtn","minimapCache","minimap","minimapCtx","viewportRectangle","minimapContainer","toggleMinimapBtn","minimapCollapsed","updateViewportRectangle","minimapCanvas","toggleMinimapCollapse","displayWidth","displayHeight","drawMinimapEdge","drawMinimapNode","canvasMap","viewportCenterX","viewportCenterY","viewRectX","viewRectY","viewRectWidth","viewRectHeight","MistouchPreventer","_preventionContainer","preventMt","preventMistouch","record","lastX","lastY","initialX","initialY","preventionContainer","preventionBanner","mistouchPreventerBannerText","preventMistouchAtStart","startPrevention","onPointerDown","onPointerMove","onPointerUp","startMistouchPrevention","endMistouchPrevention","endPrevention","getBoundingClientRect","clientX","clientY","purify","sanitize","marked","fetchCanvas","then","res","json"],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "json-canvas-viewer",
3
- "version": "3.4.3",
3
+ "version": "4.0.0",
4
4
  "description": "An extensible web-based viewer for JSON Canvas, easy to embed into websites.",
5
5
  "keywords": [
6
- "front-end",
6
+ "frontend",
7
7
  "html-canvas",
8
8
  "json-canvas",
9
- "obsidian",
9
+ "obsidian-md",
10
10
  "typescript"
11
11
  ],
12
- "homepage": "https://hesprs.github.io/json-canvas-viewer",
12
+ "homepage": "https://github.com/hesprs/json-canvas-viewer",
13
13
  "bugs": {
14
14
  "url": "https://github.com/hesprs/json-canvas-viewer/issues"
15
15
  },
@@ -23,73 +23,40 @@
23
23
  "url": "git+https://github.com/hesprs/json-canvas-viewer.git"
24
24
  },
25
25
  "files": [
26
- "dist"
26
+ "./dist"
27
27
  ],
28
28
  "type": "module",
29
29
  "sideEffects": false,
30
30
  "main": "./dist/index.js",
31
31
  "module": "./dist/index.js",
32
- "types": "./dist/types/index.d.ts",
32
+ "types": "./dist/index.d.ts",
33
33
  "unpkg": "./dist/chimp.js",
34
34
  "jsdelivr": "./dist/chimp.js",
35
35
  "exports": {
36
36
  ".": {
37
- "types": "./dist/types/index.d.ts",
37
+ "types": "./dist/index.d.ts",
38
38
  "import": "./dist/index.js"
39
- },
40
- "./dev": {
41
- "types": "./dist/types/dev.d.ts",
42
- "import": "./dist/dev.js"
43
- },
44
- "./modules": {
45
- "types": "./dist/types/modules.d.ts",
46
- "import": "./dist/modules.js"
47
- },
48
- "./bridges": {
49
- "types": "./dist/types/bridges.d.ts",
50
- "import": "./dist/bridges.js"
51
- },
52
- "./vue": {
53
- "types": "./dist/types/bridges/vueComponent.vue.d.ts",
54
- "import": "./dist/vue.js"
55
- },
56
- "./react": {
57
- "types": "./dist/types/bridges/reactComponent.d.ts",
58
- "import": "./dist/react.js"
59
39
  }
60
40
  },
61
41
  "publishConfig": {
62
- "access": "public",
63
- "provenance": true
42
+ "access": "public"
64
43
  },
65
44
  "dependencies": {
66
45
  "@ahmedsemih/color-fns": "^1.3.0",
67
- "@needle-di/core": "^1.1.0",
46
+ "@needle-di/core": "^1.1.1",
47
+ "dompurify": "^3.3.1",
48
+ "marked": "^17.0.3",
68
49
  "pointeract": "^1.1.1"
69
50
  },
70
51
  "devDependencies": {
71
- "@types/node": "^25.2.0",
72
- "@types/react": "^19.2.11",
73
- "@vitejs/plugin-vue": "^6.0.4",
74
- "dompurify": "^3.3.1",
75
- "marked": "^17.0.1",
76
- "oxfmt": "^0.28.0",
77
- "oxlint": "^1.43.0",
78
- "oxlint-tsgolint": "^0.11.4",
79
- "react": "^19.2.4",
80
52
  "sass": "^1.97.3",
81
- "schema-utils": "^4.3.3",
82
- "tsc-alias": "^1.8.16",
83
- "typescript": "^5.9.3",
84
- "vite": "^7.3.1",
85
- "vue": "^3.5.27",
86
- "vue-tsc": "^3.2.4",
87
- "webpack": "^5.105.0"
53
+ "vite-plugin-json-canvas": "1.0.0",
54
+ "@repo/shared": "0.0.1"
88
55
  },
89
56
  "scripts": {
90
57
  "dev": "vite",
91
58
  "lint": "oxlint --type-aware --fix && oxfmt",
92
- "build": "vite build && BUILD=webpack_loader vite build && BUILD=chimp vite build && vue-tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
93
- "check": "vue-tsc && oxfmt --check && oxlint --type-aware"
59
+ "build": "vite build && BUILD=chimp vite build",
60
+ "check": "tsc && oxfmt --check && oxlint --type-aware"
94
61
  }
95
62
  }
package/dist/bridges.js DELETED
@@ -1,2 +0,0 @@
1
- import{r as e}from"./renderToString-Dp8A-Rka.js";function a(e){return{name:"json-canvas-vite-plugin",async transform(a,r){if(!r.endsWith(".canvas"))return null;try{const r=JSON.parse(a);return e&&r.nodes&&await Promise.all(r.nodes.map(async a=>{"text"===a.type&&(a.text=await e(a.text))})),{code:`export default ${JSON.stringify(r)}`,map:null}}catch(s){throw console.error(`[json-canvas-vite-plugin] Failed to parse: ${r}`),s}}}}class r{parser;constructor(e){this.parser=e}apply(e){const a=require.resolve("./webpackLoader");e.options.module.rules.unshift({test:/\.canvas$/,use:[{loader:a,options:{parser:this.parser}}],type:"javascript/auto"})}}export{r as JSONCanvasWebpackPlugin,a as jsonCanvasVitePlugin,e as renderToString};
2
- //# sourceMappingURL=bridges.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bridges.js","sources":["../src/bridges/vitePlugin.ts","../src/bridges/webpackPlugin.ts"],"sourcesContent":["import type { MarkdownParser } from '$/declarations';\n\nexport default function (parser?: MarkdownParser) {\n\treturn {\n\t\tname: 'json-canvas-vite-plugin',\n\t\tasync transform(code: string, id: string) {\n\t\t\tif (!id.endsWith('.canvas')) return null;\n\t\t\ttry {\n\t\t\t\tconst json = JSON.parse(code) as JSONCanvas;\n\t\t\t\tif (parser && json.nodes)\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tjson.nodes.map(async (node) => {\n\t\t\t\t\t\t\tif (node.type === 'text') node.text = await parser(node.text);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tcode: `export default ${JSON.stringify(json)}`,\n\t\t\t\t\tmap: null,\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(`[json-canvas-vite-plugin] Failed to parse: ${id}`);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t},\n\t};\n}\n","import type { MarkdownParser } from '$/declarations';\nimport type { Compiler } from 'webpack';\n\nexport default class JsonCanvasWebpackPlugin {\n\tparser: MarkdownParser;\n\n\tconstructor(parser: MarkdownParser) {\n\t\tthis.parser = parser;\n\t}\n\n\tapply(compiler: Compiler) {\n\t\tconst loaderPath = require.resolve('./webpackLoader');\n\n\t\tcompiler.options.module.rules.unshift({\n\t\t\ttest: /\\.canvas$/,\n\t\t\tuse: [\n\t\t\t\t{\n\t\t\t\t\tloader: loaderPath,\n\t\t\t\t\toptions: { parser: this.parser },\n\t\t\t\t},\n\t\t\t],\n\t\t\t// Prevent Webpack's default JSON handling\n\t\t\ttype: 'javascript/auto',\n\t\t});\n\t}\n}\n"],"names":["vitePlugin","parser","name","transform","code","id","endsWith","json","JSON","parse","nodes","Promise","all","map","async","node","type","text","stringify","e","console","error","JsonCanvasWebpackPlugin","constructor","this","apply","compiler","loaderPath","require","options","module","rules","unshift","test","use","loader"],"mappings":"iDAEA,SAAAA,EAAyBC,GACxB,MAAO,CACNC,KAAM,0BACN,eAAMC,CAAUC,EAAcC,GAC7B,IAAKA,EAAGC,SAAS,WAAY,OAAO,KACpC,IACC,MAAMC,EAAOC,KAAKC,MAAML,GAOxB,OANIH,GAAUM,EAAKG,aACZC,QAAQC,IACbL,EAAKG,MAAMG,IAAIC,MAAOC,IACH,SAAdA,EAAKC,OAAiBD,EAAKE,WAAahB,EAAOc,EAAKE,UAGpD,CACNb,KAAM,kBAAkBI,KAAKU,UAAUX,KACvCM,IAAK,KAEP,OAASM,GAER,MADAC,QAAQC,MAAM,8CAA8ChB,KACtDc,CACP,CACD,EAEF,CCtBA,MAAqBG,EACpBrB,OAEA,WAAAsB,CAAYtB,GACXuB,KAAKvB,OAASA,CACf,CAEA,KAAAwB,CAAMC,GACL,MAAMC,EAAaC,gBAAgB,mBAEnCF,EAASG,QAAQC,OAAOC,MAAMC,QAAQ,CACrCC,KAAM,YACNC,IAAK,CACJ,CACCC,OAAQR,EACRE,QAAS,CAAE5B,OAAQuB,KAAKvB,UAI1Be,KAAM,mBAER"}
package/dist/dev.js DELETED
@@ -1,2 +0,0 @@
1
- import{B as a,C as r,D as e,I as n,O as s,S as t,u as o}from"./interactionHandler-CrVH9u7P.js";import{R as l}from"./renderer-BGA72dN1.js";export{a as BaseModule,r as Controller,e as DataManager,n as InteractionHandler,s as OverlayManager,l as Renderer,t as StyleManager,o as canvasUtils};
2
- //# sourceMappingURL=dev.js.map
package/dist/dev.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- import{u as t,D as s,S as i,C as o,O as n,I as e}from"./interactionHandler-CrVH9u7P.js";import{R as r}from"./renderer-BGA72dN1.js";import{Container as a}from"@needle-di/core";class h{allModules;IO=null;onDispose=t.makeHook(!0);onStart=t.makeHook();onRestart=t.makeHook();started=!1;options;container;constructor(t,h){this.container=new a,this.options=t;this.allModules=[s,i,o,n,e,r,...h??[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})}),this.allModules.forEach(t=>{this.container.get(t)});const l=this.options.loading??"normal";"normal"===l?this.load():"lazy"===l&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};augment=t=>{Object.entries(t).forEach(([t,s])=>{this[t]=s})};load=t=>{t&&Object.assign(this.options,t),this.started?this.onRestart():(this.onStart(),this.started=!0)};dispose=()=>{this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.onDispose(),this.container.unbindAll()}}export{h as J};
2
- //# sourceMappingURL=index-BPBGNZi4.js.map