json-canvas-viewer 3.3.0 → 3.3.1

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 (42) hide show
  1. package/README.md +5 -5
  2. package/dist/bridges.cjs +1 -1
  3. package/dist/bridges.cjs.map +1 -1
  4. package/dist/bridges.js +1 -1
  5. package/dist/bridges.js.map +1 -1
  6. package/dist/chimp.cjs +1 -1
  7. package/dist/chimp.js +1 -1
  8. package/dist/controller-CnUlrkdp.cjs +2 -0
  9. package/dist/controller-CnUlrkdp.cjs.map +1 -0
  10. package/dist/controller-UN-hOZ_r.js +2 -0
  11. package/dist/controller-UN-hOZ_r.js.map +1 -0
  12. package/dist/dev.cjs +1 -1
  13. package/dist/dev.js +1 -1
  14. package/dist/{index-BSkMdAcV.cjs → index-RXeXyAu0.cjs} +2 -2
  15. package/dist/{index-BSkMdAcV.cjs.map → index-RXeXyAu0.cjs.map} +1 -1
  16. package/dist/{index-u8PUIMyl.js → index-ujiv9m9Y.js} +2 -2
  17. package/dist/{index-u8PUIMyl.js.map → index-ujiv9m9Y.js.map} +1 -1
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/modules.cjs +1 -1
  21. package/dist/modules.cjs.map +1 -1
  22. package/dist/modules.js +1 -1
  23. package/dist/modules.js.map +1 -1
  24. package/dist/renderer-Bzv3aLXp.cjs +2 -0
  25. package/dist/renderer-Bzv3aLXp.cjs.map +1 -0
  26. package/dist/renderer-NPxavnke.js +2 -0
  27. package/dist/renderer-NPxavnke.js.map +1 -0
  28. package/dist/types/bridges/reactComponent.d.ts +9 -0
  29. package/dist/types/bridges/vueComponent.vue.d.ts +1 -1
  30. package/dist/types/bridges.d.ts +1 -0
  31. package/dist/types/core/dataManager.d.ts +13 -1
  32. package/dist/types/core/declarations.d.ts +0 -10
  33. package/dist/types/core/renderer.d.ts +1 -2
  34. package/package.json +4 -2
  35. package/dist/controller--Q72jFEw.cjs +0 -2
  36. package/dist/controller--Q72jFEw.cjs.map +0 -1
  37. package/dist/controller-siZ5v-SD.js +0 -2
  38. package/dist/controller-siZ5v-SD.js.map +0 -1
  39. package/dist/renderer-CZ85ZN6O.js +0 -2
  40. package/dist/renderer-CZ85ZN6O.js.map +0 -1
  41. package/dist/renderer-D9iInH9_.cjs +0 -2
  42. package/dist/renderer-D9iInH9_.cjs.map +0 -1
@@ -15,9 +15,8 @@ export default class Renderer extends BaseModule {
15
15
  private drawLabelBar;
16
16
  private drawNodeBackground;
17
17
  private drawGroup;
18
- private drawFileNode;
18
+ private drawFile;
19
19
  private drawEdge;
20
- private getEdgeNodes;
21
20
  private getControlPoints;
22
21
  private drawCurvedPath;
23
22
  private drawArrowhead;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-canvas-viewer",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "description": "An extensible web-based viewer for JSON Canvas, easy to embed into websites.",
5
5
  "type": "module",
6
6
  "types": "dist/types/index.d.ts",
@@ -32,7 +32,7 @@
32
32
  "type": "git",
33
33
  "url": "git+https://github.com/hesprs/json-canvas-viewer.git"
34
34
  },
35
- "homepage": "https://github.com/hesprs/json-canvas-viewer#readme",
35
+ "homepage": "https://hesprs.github.io/json-canvas-viewer",
36
36
  "bugs": {
37
37
  "url": "https://github.com/hesprs/json-canvas-viewer/issues"
38
38
  },
@@ -56,9 +56,11 @@
56
56
  "devDependencies": {
57
57
  "@biomejs/biome": "^2.3.10",
58
58
  "@types/node": "^25.0.6",
59
+ "@types/react": "^19.2.8",
59
60
  "@vitejs/plugin-vue": "^6.0.3",
60
61
  "dompurify": "^3.3.1",
61
62
  "marked": "^17.0.1",
63
+ "react": "^19.2.3",
62
64
  "sass": "^1.97.2",
63
65
  "tsc-alias": "^1.8.16",
64
66
  "typescript": "^5.9.3",
@@ -1,2 +0,0 @@
1
- "use strict";class t{constructor(t,e,s,i){this.container=t,Object.assign(this.options,e),this.onStart=s.subscribe,this.onDispose=i.subscribe}onStart;onDispose;options={}}const e={round:function(t,e){const s=10**e;return Math.round(t*s)/s},resizeCanvasForDPR:function(t,e,s){const i=window.devicePixelRatio||1,o=t.getContext("2d");if(!o)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*i),t.height=Math.round(s*i),o.setTransform(1,0,0,1,0,0),o.scale(i,i)},applyStyles:function(t,e){const s=document.createElement("style");s.innerHTML=e,t.appendChild(s)},drawRoundRect:function(t,e,s,i,o,a){t.beginPath(),t.moveTo(e+a,s),t.lineTo(e+i-a,s),t.quadraticCurveTo(e+i,s,e+i,s+a),t.lineTo(e+i,s+o-a),t.quadraticCurveTo(e+i,s+o,e+i-a,s+o),t.lineTo(e+a,s+o),t.quadraticCurveTo(e,s+o,e,s+o-a),t.lineTo(e,s+a),t.quadraticCurveTo(e,s,e+a,s),t.closePath()},getAnchorCoord:function(t,e){const s=t.x+t.width/2,i=t.y+t.height/2;switch(e){case"top":return[s,t.y];case"bottom":return[s,t.y+t.height];case"left":return[t.x,i];case"right":return[t.x+t.width,i];default:return[s,i]}},getColor:function(t="0"){let e=null;if(1===t.length)switch(t){case"1":e="rgba(255, 120, 129, ?)";break;case"2":e="rgba(251, 187, 131, ?)";break;case"3":e="rgba(255, 232, 139, ?)";break;case"4":e="rgba(124, 211, 124, ?)";break;case"5":e="rgba(134, 223, 226, ?)";break;case"6":e="rgba(203, 158, 255, ?)";break;default:e="rgba(140, 140, 140, ?)"}else{const s=function(t){const e=t.replace("#","");return{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16)}}(t);e=`rgba(${s.r}, ${s.g}, ${s.b}, ?)`}return{border:e.replace("?","0.75"),background:e.replace("?","0.1"),active:e.replace("?","1")}},makeHook:function(t=!1){const e=(...s)=>{if(t){Array.from(e.subs).reverse().forEach(t=>{t(...s)})}else e.subs.forEach(t=>{t(...s)})};return e.subs=new Set,e.subscribe=t=>{e.subs.add(t)},e.unsubscribe=t=>{e.subs.delete(t)},e}},s=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");const i=800;class o extends t{spatialGrid=null;onToggleFullscreen=e.makeHook();data;constructor(...t){super(...t);const s=this.options.container;for(;s.firstElementChild;)s.firstElementChild.remove();s.innerHTML="";const i=this.options.noShadow||!1?s:s.attachShadow({mode:"open"});e.applyStyles(i,".full,.click-layer,.link-iframe,.audio{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.overlay-container.markdown-content{display:flex;justify-content:center;align-items:center}.container{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:#fff;fill:#fff;stroke:#fff;position:relative;width:100%;height:100%;overflow:hidden;background-color:#141414}.container.numb,.container.numb *{pointer-events:none!important}.main-canvas{width:100%;height:100%;transform-origin:top left}.overlays{position:absolute;top:0;left:0;width:10000px;height:10000px;transform-origin:top left;will-change:transform}.parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.parsed-content-wrapper{padding:10px}}.overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;overflow:hidden;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto}.overlay-container:hover{box-shadow:0 2px 12px #00000080}.overlay-container{transition:var(--containerTransition)}.overlay-container .overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%;border-width:2px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.overlay-container img{width:100%;height:100%;object-fit:cover;pointer-events:none}.overlay-container.active .overlay-border{border:6px solid var(--active-color)}.overlay-container.markdown-content{position:absolute;padding:0 7px}.overlay-container.markdown-content.active .parsed-content-wrapper{overflow:auto;-webkit-user-select:text;user-select:text;pointer-events:auto}.overlay-container.markdown-content.rtl{direction:rtl;text-align:right}.link-iframe,.audio{border:none;background:transparent}.click-layer{background:transparent;pointer-events:auto}.active .click-layer{pointer-events:none}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background-color:transparent}::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}p{font-size:16px;line-height:21px}.parsed-content-wrapper img{width:100%;border-radius:8px}h1{font-size:25px}h2{font-size:23px}h3{font-size:22px}h4{font-size:20px}h5{font-size:19px}h6{font-size:17px}p,h1,h2,h3,h4,h5,h6,ol,ul{margin:0}h1,h2{font-weight:800}h3,h4{font-weight:700}h5,h6{font-weight:600}code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre code{display:block;box-sizing:border-box;width:100%}pre:has(code),table{margin:6px 0}strong{color:#fe8e7c}em{color:#5affb2}a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}a:hover{color:#86d3fd}hr{height:1px;width:100%;background-color:#fff3;border:none}li{margin:5px 0}ul{padding-left:16px}ol{padding-left:15px;padding-right:7.5px}table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}table th,table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}table th{background:#ffffff1f;font-weight:700}"+this.options.extraCSS);const o=document.createElement("div");o.classList.add("container"),i.appendChild(o);const a=Object.assign({nodes:[],edges:[]},this.options.canvas);this.data={canvasData:a,nodeMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(a),offsetX:0,offsetY:0,scale:1,container:o},this.data.canvasData.nodes.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=e[e.length-1]}this.data.nodeMap[t.id]=t}),this.buildSpatialGrid(),this.resetView(),this.onDispose(this.dispose)}processBaseDir=t=>{if(!t)return"./";const e=t?.slice(-1);return"/"===e?t:`${t}/`};findNodeAt=t=>{const{x:e,y:s}=this.C2W(this.C2C({x:t.x,y:t.y}));let o=[];if(this.spatialGrid){const t=`${Math.floor(e/i)},${Math.floor(s/i)}`;o=this.spatialGrid[t]||[]}else o=this.data.canvasData.nodes;for(const i of o)if(!(e<i.x||e>i.x+i.width||s<i.y||s>i.y+i.height||"non-interactive"===this.judgeInteract(i)))return i;return null};judgeInteract=t=>{switch(t?.type){case"text":case"link":return"select";case"file":return t.file.match(/\.(md|wav|mp3)$/i)?"select":"non-interactive";default:return"non-interactive"}};calculateNodeBounds(t){let e=1/0,s=1/0,i=-1/0,o=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),s=Math.min(s,t.y),i=Math.max(i,t.x+t.width),o=Math.max(o,t.y+t.height)});const a=i-e,r=o-s;return{minX:e,minY:s,maxX:i,maxY:o,width:a,height:r,centerX:e+a/2,centerY:s+r/2}}buildSpatialGrid(){const t=this.data.canvasData;if(!(t.nodes.length<50)){this.spatialGrid={};for(const e of t.nodes){const t=Math.floor(e.x/i),s=Math.floor((e.x+e.width)/i),o=Math.floor(e.y/i),a=Math.floor((e.y+e.height)/i);for(let i=t;i<=s;i++)for(let t=o;t<=a;t++){const s=`${i},${t}`;this.spatialGrid[s]||(this.spatialGrid[s]=[]),this.spatialGrid[s].push(e)}}}}zoom=(t,e)=>{const s=this.data.scale*t;this.zoomToScale(s,e)};zoomToScale=(t,e)=>{const s=Math.max(Math.min(t,20),.05),i=this.data.scale;if(s===i)return;const o=this.C2C(e);this.data.offsetX=e.x-o.x*s/i,this.data.offsetY=e.y-o.y*s/i,this.data.scale=s};pan=({x:t,y:e})=>{this.data.offsetX=this.data.offsetX+t,this.data.offsetY=this.data.offsetY+e};panToCoords=({x:t,y:e})=>{this.data.offsetX=t,this.data.offsetY=e};shiftFullscreen=(t="toggle")=>{document.fullscreenElement||"toggle"!==t&&"enter"!==t?!document.fullscreenElement||"toggle"!==t&&"exit"!==t||(document.exitFullscreen(),this.onToggleFullscreen(!1)):(this.data.container.requestFullscreen(),this.onToggleFullscreen(!0))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const s=t.width+200,i=t.height+200,o=e.clientWidth,a=e.clientHeight,r=o/s,n=a/i,l=Math.round(1e3*Math.min(r,n))/1e3,c={scale:l,offsetX:o/2-t.centerX*l,offsetY:a/2-t.centerY*l};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.scale};C2C=({x:t,y:e})=>({x:t-this.data.offsetX,y:e-this.data.offsetY});C2W=({x:t,y:e})=>({x:t/this.data.scale,y:e/this.data.scale});middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>this.data.container.remove()}exports.BaseModule=t,exports.Controller=class extends t{animationId=null;resizeAnimationId=null;DM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};hooks={onResize:e.makeHook(),onRefresh:e.makeHook()};constructor(...t){super(...t),this.onStart(this.start),this.onDispose(this.dispose),this.DM=this.container.get(o),this.resizeObserver=new ResizeObserver(this.onResize)}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,this.perFrame.lastOffsets={x:this.DM.data.offsetX,y:this.DM.data.offsetY},this.hooks.onRefresh()};onResize=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const t=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+t.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+t.y-this.lastResizeCenter.y),this.lastResizeCenter.x=t.x,this.lastResizeCenter.y=t.y,this.hooks.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}},exports.DataManager=o,exports.destroyError=s,exports.utilities=e;
2
- //# sourceMappingURL=controller--Q72jFEw.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller--Q72jFEw.cjs","sources":["../src/core/baseModule.ts","../src/core/utilities.ts","../src/core/dataManager.ts","../src/core/controller.ts"],"sourcesContent":["import type { Container } from '@needle-di/core';\nimport type { DefaultOptions, Empty, GeneralFunction, GeneralObject } from '$/declarations';\nimport type utilities from '$/utilities';\n\ntype Hook = ReturnType<typeof utilities.makeHook>;\n\nexport type BaseArgs = [Container, GeneralObject, Hook, Hook];\n\nexport type GeneralModuleCtor = typeof BaseModule<GeneralObject>;\nexport type GeneralModule = BaseModule<GeneralObject>;\n\nexport class BaseModule<O extends GeneralObject = Empty> {\n\tonStart: (callback: GeneralFunction) => void;\n\tonDispose: (callback: GeneralFunction) => void;\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tonStart: Hook,\n\t\tonDispose: Hook,\n\t) {\n\t\tObject.assign(this.options, options);\n\t\tthis.onStart = onStart.subscribe;\n\t\tthis.onDispose = onDispose.subscribe;\n\t}\n\toptions = {} as DefaultOptions & O;\n}\n","import type { GeneralArguments } from '$/declarations';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tgetColor,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\");\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn [midX, node.y];\n\t\tcase 'bottom':\n\t\t\treturn [midX, node.y + node.height];\n\t\tcase 'left':\n\t\t\treturn [node.x, midY];\n\t\tcase 'right':\n\t\t\treturn [node.x + node.width, midY];\n\t\tdefault:\n\t\t\treturn [midX, midY];\n\t}\n}\n\nfunction getColor(colorIndex: string = '0') {\n\tlet themeColor = null;\n\n\tfunction hexToRgb(hex: string) {\n\t\tconst cleanHex = hex.replace('#', '');\n\t\tconst r = parseInt(cleanHex.substring(0, 2), 16);\n\t\tconst g = parseInt(cleanHex.substring(2, 4), 16);\n\t\tconst b = parseInt(cleanHex.substring(4, 6), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (colorIndex.length === 1) {\n\t\tswitch (colorIndex) {\n\t\t\tcase '1':\n\t\t\t\tthemeColor = 'rgba(255, 120, 129, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '2':\n\t\t\t\tthemeColor = 'rgba(251, 187, 131, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '3':\n\t\t\t\tthemeColor = 'rgba(255, 232, 139, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '4':\n\t\t\t\tthemeColor = 'rgba(124, 211, 124, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '5':\n\t\t\t\tthemeColor = 'rgba(134, 223, 226, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '6':\n\t\t\t\tthemeColor = 'rgba(203, 158, 255, ?)';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthemeColor = 'rgba(140, 140, 140, ?)';\n\t\t}\n\t} else {\n\t\tconst rgb = hexToRgb(colorIndex);\n\t\tthemeColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ?)`;\n\t}\n\treturn {\n\t\tborder: themeColor.replace('?', '0.75'),\n\t\tbackground: themeColor.replace('?', '0.1'),\n\t\tactive: themeColor.replace('?', '1'),\n\t};\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio || 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx)\n\t\tthrow new Error(\n\t\t\t'[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.',\n\t\t);\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n\nfunction makeHook<Args extends GeneralArguments = []>(reverse: boolean = false) {\n\ttype MatchingFunc = (...args: Args) => unknown;\n\ttype Hook = {\n\t\t(...args: Args): void;\n\t\tsubs: Set<MatchingFunc>;\n\t\tsubscribe(callback: MatchingFunc): void;\n\t\tunsubscribe(callback: MatchingFunc): void;\n\t};\n\tconst result: Hook = (...args: Args) => {\n\t\tif (reverse) {\n\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\titems.forEach(callback => {\n\t\t\t\tcallback(...args);\n\t\t\t});\n\t\t} else\n\t\t\tresult.subs.forEach(callback => {\n\t\t\t\tcallback(...args);\n\t\t\t});\n\t};\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport type { Coordinates, NodeBounds } from '$/declarations';\nimport style from '$/styles.scss?inline';\nimport utilities from '$/utilities';\n\nconst GRID_CELL_SIZE = 800;\nconst INITIAL_VIEWPORT_PADDING = 100;\n\ntype Options = {\n\tnoShadow?: boolean;\n\tcanvas: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n};\n\nexport default class DataManager extends BaseModule<Options> {\n\tprivate spatialGrid: Record<string, Array<JSONCanvasNode>> | null = null;\n\tonToggleFullscreen = utilities.makeHook<[boolean]>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: Record<string, JSONCanvasNode>;\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\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst parentContainer = this.options.container;\n\t\twhile (parentContainer.firstElementChild) parentContainer.firstElementChild.remove();\n\t\tparentContainer.innerHTML = '';\n\n\t\tconst noShadow = this.options.noShadow || false;\n\t\tconst realContainer = noShadow ? parentContainer : parentContainer.attachShadow({ mode: 'open' });\n\n\t\tutilities.applyStyles(realContainer, style + this.options.extraCSS);\n\n\t\tconst HTMLContainer = document.createElement('div');\n\t\tHTMLContainer.classList.add('container');\n\t\trealContainer.appendChild(HTMLContainer);\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\tthis.data = {\n\t\t\tcanvasData: canvasData,\n\t\t\tnodeMap: {},\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\tcontainer: HTMLContainer,\n\t\t};\n\n\t\tthis.data.canvasData.nodes.forEach(node => {\n\t\t\tif (node.type === 'file' && !node.file.includes('http')) {\n\t\t\t\tconst file = node.file.split('/');\n\t\t\t\tnode.file = file[file.length - 1];\n\t\t\t}\n\t\t\tthis.data.nodeMap[node.id] = node;\n\t\t});\n\n\t\tthis.buildSpatialGrid();\n\t\tthis.resetView();\n\t\tthis.onDispose(this.dispose);\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\tfindNodeAt = (screenCoords: Coordinates) => {\n\t\tconst { x, y } = this.C2W(this.C2C({ x: screenCoords.x, y: screenCoords.y }));\n\t\tlet candidates: Array<JSONCanvasNode> = [];\n\t\tif (!this.spatialGrid) candidates = this.data.canvasData.nodes;\n\t\telse {\n\t\t\tconst col = Math.floor(x / GRID_CELL_SIZE);\n\t\t\tconst row = Math.floor(y / GRID_CELL_SIZE);\n\t\t\tconst key = `${col},${row}`;\n\t\t\tcandidates = this.spatialGrid[key] || [];\n\t\t}\n\t\tfor (const node of candidates) {\n\t\t\tif (\n\t\t\t\tx < node.x ||\n\t\t\t\tx > node.x + node.width ||\n\t\t\t\ty < node.y ||\n\t\t\t\ty > node.y + node.height ||\n\t\t\t\tthis.judgeInteract(node) === 'non-interactive'\n\t\t\t)\n\t\t\t\tcontinue;\n\t\t\treturn node;\n\t\t}\n\t\treturn null;\n\t};\n\n\t// how should the app handle node interactions\n\tprivate judgeInteract = (node: JSONCanvasNode | null) => {\n\t\tswitch (node?.type) {\n\t\t\tcase 'text':\n\t\t\tcase 'link':\n\t\t\t\treturn 'select';\n\t\t\tcase 'file': {\n\t\t\t\tif (node.file.match(/\\.(md|wav|mp3)$/i)) return 'select';\n\t\t\t\telse return 'non-interactive';\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn 'non-interactive';\n\t\t}\n\t};\n\n\tprivate calculateNodeBounds(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\n\tprivate buildSpatialGrid() {\n\t\tconst canvasData = this.data.canvasData;\n\t\tif (canvasData.nodes.length < 50) return;\n\t\tthis.spatialGrid = {};\n\t\tfor (const node of canvasData.nodes) {\n\t\t\tconst minCol = Math.floor(node.x / GRID_CELL_SIZE);\n\t\t\tconst maxCol = Math.floor((node.x + node.width) / GRID_CELL_SIZE);\n\t\t\tconst minRow = Math.floor(node.y / GRID_CELL_SIZE);\n\t\t\tconst maxRow = Math.floor((node.y + node.height) / GRID_CELL_SIZE);\n\t\t\tfor (let col = minCol; col <= maxCol; col++) {\n\t\t\t\tfor (let row = minRow; row <= maxRow; row++) {\n\t\t\t\t\tconst key = `${col},${row}`;\n\t\t\t\t\tif (!this.spatialGrid[key]) this.spatialGrid[key] = [];\n\t\t\t\t\tthis.spatialGrid[key].push(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tzoom = (factor: number, origin: Coordinates) => {\n\t\tconst newScale = this.data.scale * factor;\n\t\tthis.zoomToScale(newScale, origin);\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst validNewScale = Math.max(Math.min(newScale, 20), 0.05);\n\t\tconst scale = this.data.scale;\n\t\tif (validNewScale === scale) return;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.data.offsetX = origin.x - (canvasCoords.x * validNewScale) / scale;\n\t\tthis.data.offsetY = origin.y - (canvasCoords.y * validNewScale) / scale;\n\t\tthis.data.scale = validNewScale;\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = this.data.offsetX + x;\n\t\tthis.data.offsetY = this.data.offsetY + y;\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = x;\n\t\tthis.data.offsetY = y;\n\t};\n\tshiftFullscreen = (option: string = 'toggle') => {\n\t\tif (!document.fullscreenElement && (option === 'toggle' || option === 'enter')) {\n\t\t\tthis.data.container.requestFullscreen();\n\t\t\tthis.onToggleFullscreen(true);\n\t\t} else if (document.fullscreenElement && (option === 'toggle' || option === 'exit')) {\n\t\t\tdocument.exitFullscreen();\n\t\t\tthis.onToggleFullscreen(false);\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\t// Container to Canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.data.offsetX,\n\t\ty: containerY - this.data.offsetY,\n\t});\n\t// Canvas to World\n\tprivate C2W = ({ x: canvasX, y: canvasY }: Coordinates) => ({\n\t\tx: canvasX / this.data.scale,\n\t\ty: canvasY / this.data.scale,\n\t});\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tprivate dispose = () => this.data.container.remove();\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport DataManager from '$/dataManager';\nimport utilities from '$/utilities';\n\nexport default class Controller extends BaseModule {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\thooks = {\n\t\tonResize: utilities.makeHook<[number, number]>(),\n\t\tonRefresh: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResize);\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.lastScale = this.DM.data.scale;\n\t\tthis.perFrame.lastOffsets = {\n\t\t\tx: this.DM.data.offsetX,\n\t\t\ty: this.DM.data.offsetY,\n\t\t};\n\t\tthis.hooks.onRefresh();\n\t};\n\n\tprivate onResize = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.hooks.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\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"],"names":["BaseModule","constructor","container","options","onStart","onDispose","this","Object","assign","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","getColor","colorIndex","themeColor","length","rgb","hex","cleanHex","replace","r","parseInt","substring","g","b","hexToRgb","border","background","active","makeHook","reverse","result","args","Array","from","subs","forEach","callback","Set","add","unsubscribe","delete","destroyError","GRID_CELL_SIZE","DataManager","spatialGrid","onToggleFullscreen","data","super","parentContainer","firstElementChild","remove","realContainer","noShadow","attachShadow","mode","extraCSS","HTMLContainer","classList","canvasData","nodes","edges","nodeMap","canvasBaseDir","processBaseDir","attachmentDir","nodeBounds","calculateNodeBounds","offsetX","offsetY","type","file","includes","split","id","buildSpatialGrid","resetView","dispose","baseDir","lastChar","slice","findNodeAt","screenCoords","C2W","C2C","candidates","key","floor","judgeInteract","match","minX","Infinity","minY","maxX","maxY","min","max","centerX","centerY","minCol","maxCol","minRow","maxRow","col","row","push","zoom","origin","newScale","zoomToScale","validNewScale","canvasCoords","pan","panToCoords","shiftFullscreen","option","fullscreenElement","exitFullscreen","requestFullscreen","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","initialView","containerX","containerY","canvasX","canvasY","middleViewer","animationId","resizeAnimationId","DM","resizeObserver","perFrame","lastScale","lastOffsets","lastResizeCenter","hooks","onResize","onRefresh","start","get","ResizeObserver","observe","requestAnimationFrame","draw","refresh","center","cancelAnimationFrame","disconnect"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- class t{constructor(t,e,s,i){this.container=t,Object.assign(this.options,e),this.onStart=s.subscribe,this.onDispose=i.subscribe}onStart;onDispose;options={}}const e={round:function(t,e){const s=10**e;return Math.round(t*s)/s},resizeCanvasForDPR:function(t,e,s){const i=window.devicePixelRatio||1,o=t.getContext("2d");if(!o)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*i),t.height=Math.round(s*i),o.setTransform(1,0,0,1,0,0),o.scale(i,i)},applyStyles:function(t,e){const s=document.createElement("style");s.innerHTML=e,t.appendChild(s)},drawRoundRect:function(t,e,s,i,o,a){t.beginPath(),t.moveTo(e+a,s),t.lineTo(e+i-a,s),t.quadraticCurveTo(e+i,s,e+i,s+a),t.lineTo(e+i,s+o-a),t.quadraticCurveTo(e+i,s+o,e+i-a,s+o),t.lineTo(e+a,s+o),t.quadraticCurveTo(e,s+o,e,s+o-a),t.lineTo(e,s+a),t.quadraticCurveTo(e,s,e+a,s),t.closePath()},getAnchorCoord:function(t,e){const s=t.x+t.width/2,i=t.y+t.height/2;switch(e){case"top":return[s,t.y];case"bottom":return[s,t.y+t.height];case"left":return[t.x,i];case"right":return[t.x+t.width,i];default:return[s,i]}},getColor:function(t="0"){let e=null;if(1===t.length)switch(t){case"1":e="rgba(255, 120, 129, ?)";break;case"2":e="rgba(251, 187, 131, ?)";break;case"3":e="rgba(255, 232, 139, ?)";break;case"4":e="rgba(124, 211, 124, ?)";break;case"5":e="rgba(134, 223, 226, ?)";break;case"6":e="rgba(203, 158, 255, ?)";break;default:e="rgba(140, 140, 140, ?)"}else{const s=function(t){const e=t.replace("#","");return{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16)}}(t);e=`rgba(${s.r}, ${s.g}, ${s.b}, ?)`}return{border:e.replace("?","0.75"),background:e.replace("?","0.1"),active:e.replace("?","1")}},makeHook:function(t=!1){const e=(...s)=>{if(t){Array.from(e.subs).reverse().forEach(t=>{t(...s)})}else e.subs.forEach(t=>{t(...s)})};return e.subs=/* @__PURE__ */new Set,e.subscribe=t=>{e.subs.add(t)},e.unsubscribe=t=>{e.subs.delete(t)},e}},s=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");const i=800;class o extends t{spatialGrid=null;onToggleFullscreen=e.makeHook();data;constructor(...t){super(...t);const s=this.options.container;for(;s.firstElementChild;)s.firstElementChild.remove();s.innerHTML="";const i=this.options.noShadow||!1?s:s.attachShadow({mode:"open"});e.applyStyles(i,".full,.click-layer,.link-iframe,.audio{top:0;left:0;width:100%;height:100%;position:absolute}.flex-center,.overlay-container.markdown-content{display:flex;justify-content:center;align-items:center}.container{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:#fff;fill:#fff;stroke:#fff;position:relative;width:100%;height:100%;overflow:hidden;background-color:#141414}.container.numb,.container.numb *{pointer-events:none!important}.main-canvas{width:100%;height:100%;transform-origin:top left}.overlays{position:absolute;top:0;left:0;width:10000px;height:10000px;transform-origin:top left;will-change:transform}.parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.parsed-content-wrapper{padding:10px}}.overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;overflow:hidden;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto}.overlay-container:hover{box-shadow:0 2px 12px #00000080}.overlay-container{transition:var(--containerTransition)}.overlay-container .overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%;border-width:2px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.overlay-container img{width:100%;height:100%;object-fit:cover;pointer-events:none}.overlay-container.active .overlay-border{border:6px solid var(--active-color)}.overlay-container.markdown-content{position:absolute;padding:0 7px}.overlay-container.markdown-content.active .parsed-content-wrapper{overflow:auto;-webkit-user-select:text;user-select:text;pointer-events:auto}.overlay-container.markdown-content.rtl{direction:rtl;text-align:right}.link-iframe,.audio{border:none;background:transparent}.click-layer{background:transparent;pointer-events:auto}.active .click-layer{pointer-events:none}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background-color:transparent}::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}p{font-size:16px;line-height:21px}.parsed-content-wrapper img{width:100%;border-radius:8px}h1{font-size:25px}h2{font-size:23px}h3{font-size:22px}h4{font-size:20px}h5{font-size:19px}h6{font-size:17px}p,h1,h2,h3,h4,h5,h6,ol,ul{margin:0}h1,h2{font-weight:800}h3,h4{font-weight:700}h5,h6{font-weight:600}code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre code{display:block;box-sizing:border-box;width:100%}pre:has(code),table{margin:6px 0}strong{color:#fe8e7c}em{color:#5affb2}a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}a:hover{color:#86d3fd}hr{height:1px;width:100%;background-color:#fff3;border:none}li{margin:5px 0}ul{padding-left:16px}ol{padding-left:15px;padding-right:7.5px}table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}table th,table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}table th{background:#ffffff1f;font-weight:700}"+this.options.extraCSS);const o=document.createElement("div");o.classList.add("container"),i.appendChild(o);const a=Object.assign({nodes:[],edges:[]},this.options.canvas);this.data={canvasData:a,nodeMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(a),offsetX:0,offsetY:0,scale:1,container:o},this.data.canvasData.nodes.forEach(t=>{if("file"===t.type&&!t.file.includes("http")){const e=t.file.split("/");t.file=e[e.length-1]}this.data.nodeMap[t.id]=t}),this.buildSpatialGrid(),this.resetView(),this.onDispose(this.dispose)}processBaseDir=t=>{if(!t)return"./";const e=t?.slice(-1);return"/"===e?t:`${t}/`};findNodeAt=t=>{const{x:e,y:s}=this.C2W(this.C2C({x:t.x,y:t.y}));let o=[];if(this.spatialGrid){const t=`${Math.floor(e/i)},${Math.floor(s/i)}`;o=this.spatialGrid[t]||[]}else o=this.data.canvasData.nodes;for(const i of o)if(!(e<i.x||e>i.x+i.width||s<i.y||s>i.y+i.height||"non-interactive"===this.judgeInteract(i)))return i;return null};judgeInteract=t=>{switch(t?.type){case"text":case"link":return"select";case"file":return t.file.match(/\.(md|wav|mp3)$/i)?"select":"non-interactive";default:return"non-interactive"}};calculateNodeBounds(t){let e=1/0,s=1/0,i=-1/0,o=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),s=Math.min(s,t.y),i=Math.max(i,t.x+t.width),o=Math.max(o,t.y+t.height)});const a=i-e,n=o-s;return{minX:e,minY:s,maxX:i,maxY:o,width:a,height:n,centerX:e+a/2,centerY:s+n/2}}buildSpatialGrid(){const t=this.data.canvasData;if(!(t.nodes.length<50)){this.spatialGrid={};for(const e of t.nodes){const t=Math.floor(e.x/i),s=Math.floor((e.x+e.width)/i),o=Math.floor(e.y/i),a=Math.floor((e.y+e.height)/i);for(let i=t;i<=s;i++)for(let t=o;t<=a;t++){const s=`${i},${t}`;this.spatialGrid[s]||(this.spatialGrid[s]=[]),this.spatialGrid[s].push(e)}}}}zoom=(t,e)=>{const s=this.data.scale*t;this.zoomToScale(s,e)};zoomToScale=(t,e)=>{const s=Math.max(Math.min(t,20),.05),i=this.data.scale;if(s===i)return;const o=this.C2C(e);this.data.offsetX=e.x-o.x*s/i,this.data.offsetY=e.y-o.y*s/i,this.data.scale=s};pan=({x:t,y:e})=>{this.data.offsetX=this.data.offsetX+t,this.data.offsetY=this.data.offsetY+e};panToCoords=({x:t,y:e})=>{this.data.offsetX=t,this.data.offsetY=e};shiftFullscreen=(t="toggle")=>{document.fullscreenElement||"toggle"!==t&&"enter"!==t?!document.fullscreenElement||"toggle"!==t&&"exit"!==t||(document.exitFullscreen(),this.onToggleFullscreen(!1)):(this.data.container.requestFullscreen(),this.onToggleFullscreen(!0))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const s=t.width+200,i=t.height+200,o=e.clientWidth,a=e.clientHeight,n=o/s,r=a/i,l=Math.round(1e3*Math.min(n,r))/1e3,c={scale:l,offsetX:o/2-t.centerX*l,offsetY:a/2-t.centerY*l};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.scale};C2C=({x:t,y:e})=>({x:t-this.data.offsetX,y:e-this.data.offsetY});C2W=({x:t,y:e})=>({x:t/this.data.scale,y:e/this.data.scale});middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>this.data.container.remove()}class a extends t{animationId=null;resizeAnimationId=null;DM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};hooks={onResize:e.makeHook(),onRefresh:e.makeHook()};constructor(...t){super(...t),this.onStart(this.start),this.onDispose(this.dispose),this.DM=this.container.get(o),this.resizeObserver=new ResizeObserver(this.onResize)}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,this.perFrame.lastOffsets={x:this.DM.data.offsetX,y:this.DM.data.offsetY},this.hooks.onRefresh()};onResize=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const t=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+t.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+t.y-this.lastResizeCenter.y),this.lastResizeCenter.x=t.x,this.lastResizeCenter.y=t.y,this.hooks.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}export{t as B,a as C,o as D,s as d,e as u};
2
- //# sourceMappingURL=controller-siZ5v-SD.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller-siZ5v-SD.js","sources":["../src/core/baseModule.ts","../src/core/utilities.ts","../src/core/dataManager.ts","../src/core/controller.ts"],"sourcesContent":["import type { Container } from '@needle-di/core';\nimport type { DefaultOptions, Empty, GeneralFunction, GeneralObject } from '$/declarations';\nimport type utilities from '$/utilities';\n\ntype Hook = ReturnType<typeof utilities.makeHook>;\n\nexport type BaseArgs = [Container, GeneralObject, Hook, Hook];\n\nexport type GeneralModuleCtor = typeof BaseModule<GeneralObject>;\nexport type GeneralModule = BaseModule<GeneralObject>;\n\nexport class BaseModule<O extends GeneralObject = Empty> {\n\tonStart: (callback: GeneralFunction) => void;\n\tonDispose: (callback: GeneralFunction) => void;\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tonStart: Hook,\n\t\tonDispose: Hook,\n\t) {\n\t\tObject.assign(this.options, options);\n\t\tthis.onStart = onStart.subscribe;\n\t\tthis.onDispose = onDispose.subscribe;\n\t}\n\toptions = {} as DefaultOptions & O;\n}\n","import type { GeneralArguments } from '$/declarations';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tgetColor,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\");\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn [midX, node.y];\n\t\tcase 'bottom':\n\t\t\treturn [midX, node.y + node.height];\n\t\tcase 'left':\n\t\t\treturn [node.x, midY];\n\t\tcase 'right':\n\t\t\treturn [node.x + node.width, midY];\n\t\tdefault:\n\t\t\treturn [midX, midY];\n\t}\n}\n\nfunction getColor(colorIndex: string = '0') {\n\tlet themeColor = null;\n\n\tfunction hexToRgb(hex: string) {\n\t\tconst cleanHex = hex.replace('#', '');\n\t\tconst r = parseInt(cleanHex.substring(0, 2), 16);\n\t\tconst g = parseInt(cleanHex.substring(2, 4), 16);\n\t\tconst b = parseInt(cleanHex.substring(4, 6), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (colorIndex.length === 1) {\n\t\tswitch (colorIndex) {\n\t\t\tcase '1':\n\t\t\t\tthemeColor = 'rgba(255, 120, 129, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '2':\n\t\t\t\tthemeColor = 'rgba(251, 187, 131, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '3':\n\t\t\t\tthemeColor = 'rgba(255, 232, 139, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '4':\n\t\t\t\tthemeColor = 'rgba(124, 211, 124, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '5':\n\t\t\t\tthemeColor = 'rgba(134, 223, 226, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '6':\n\t\t\t\tthemeColor = 'rgba(203, 158, 255, ?)';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthemeColor = 'rgba(140, 140, 140, ?)';\n\t\t}\n\t} else {\n\t\tconst rgb = hexToRgb(colorIndex);\n\t\tthemeColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ?)`;\n\t}\n\treturn {\n\t\tborder: themeColor.replace('?', '0.75'),\n\t\tbackground: themeColor.replace('?', '0.1'),\n\t\tactive: themeColor.replace('?', '1'),\n\t};\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio || 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx)\n\t\tthrow new Error(\n\t\t\t'[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.',\n\t\t);\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n\nfunction makeHook<Args extends GeneralArguments = []>(reverse: boolean = false) {\n\ttype MatchingFunc = (...args: Args) => unknown;\n\ttype Hook = {\n\t\t(...args: Args): void;\n\t\tsubs: Set<MatchingFunc>;\n\t\tsubscribe(callback: MatchingFunc): void;\n\t\tunsubscribe(callback: MatchingFunc): void;\n\t};\n\tconst result: Hook = (...args: Args) => {\n\t\tif (reverse) {\n\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\titems.forEach(callback => {\n\t\t\t\tcallback(...args);\n\t\t\t});\n\t\t} else\n\t\t\tresult.subs.forEach(callback => {\n\t\t\t\tcallback(...args);\n\t\t\t});\n\t};\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport type { Coordinates, NodeBounds } from '$/declarations';\nimport style from '$/styles.scss?inline';\nimport utilities from '$/utilities';\n\nconst GRID_CELL_SIZE = 800;\nconst INITIAL_VIEWPORT_PADDING = 100;\n\ntype Options = {\n\tnoShadow?: boolean;\n\tcanvas: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n};\n\nexport default class DataManager extends BaseModule<Options> {\n\tprivate spatialGrid: Record<string, Array<JSONCanvasNode>> | null = null;\n\tonToggleFullscreen = utilities.makeHook<[boolean]>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: Record<string, JSONCanvasNode>;\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\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst parentContainer = this.options.container;\n\t\twhile (parentContainer.firstElementChild) parentContainer.firstElementChild.remove();\n\t\tparentContainer.innerHTML = '';\n\n\t\tconst noShadow = this.options.noShadow || false;\n\t\tconst realContainer = noShadow ? parentContainer : parentContainer.attachShadow({ mode: 'open' });\n\n\t\tutilities.applyStyles(realContainer, style + this.options.extraCSS);\n\n\t\tconst HTMLContainer = document.createElement('div');\n\t\tHTMLContainer.classList.add('container');\n\t\trealContainer.appendChild(HTMLContainer);\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\tthis.data = {\n\t\t\tcanvasData: canvasData,\n\t\t\tnodeMap: {},\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\tcontainer: HTMLContainer,\n\t\t};\n\n\t\tthis.data.canvasData.nodes.forEach(node => {\n\t\t\tif (node.type === 'file' && !node.file.includes('http')) {\n\t\t\t\tconst file = node.file.split('/');\n\t\t\t\tnode.file = file[file.length - 1];\n\t\t\t}\n\t\t\tthis.data.nodeMap[node.id] = node;\n\t\t});\n\n\t\tthis.buildSpatialGrid();\n\t\tthis.resetView();\n\t\tthis.onDispose(this.dispose);\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\tfindNodeAt = (screenCoords: Coordinates) => {\n\t\tconst { x, y } = this.C2W(this.C2C({ x: screenCoords.x, y: screenCoords.y }));\n\t\tlet candidates: Array<JSONCanvasNode> = [];\n\t\tif (!this.spatialGrid) candidates = this.data.canvasData.nodes;\n\t\telse {\n\t\t\tconst col = Math.floor(x / GRID_CELL_SIZE);\n\t\t\tconst row = Math.floor(y / GRID_CELL_SIZE);\n\t\t\tconst key = `${col},${row}`;\n\t\t\tcandidates = this.spatialGrid[key] || [];\n\t\t}\n\t\tfor (const node of candidates) {\n\t\t\tif (\n\t\t\t\tx < node.x ||\n\t\t\t\tx > node.x + node.width ||\n\t\t\t\ty < node.y ||\n\t\t\t\ty > node.y + node.height ||\n\t\t\t\tthis.judgeInteract(node) === 'non-interactive'\n\t\t\t)\n\t\t\t\tcontinue;\n\t\t\treturn node;\n\t\t}\n\t\treturn null;\n\t};\n\n\t// how should the app handle node interactions\n\tprivate judgeInteract = (node: JSONCanvasNode | null) => {\n\t\tswitch (node?.type) {\n\t\t\tcase 'text':\n\t\t\tcase 'link':\n\t\t\t\treturn 'select';\n\t\t\tcase 'file': {\n\t\t\t\tif (node.file.match(/\\.(md|wav|mp3)$/i)) return 'select';\n\t\t\t\telse return 'non-interactive';\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn 'non-interactive';\n\t\t}\n\t};\n\n\tprivate calculateNodeBounds(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\n\tprivate buildSpatialGrid() {\n\t\tconst canvasData = this.data.canvasData;\n\t\tif (canvasData.nodes.length < 50) return;\n\t\tthis.spatialGrid = {};\n\t\tfor (const node of canvasData.nodes) {\n\t\t\tconst minCol = Math.floor(node.x / GRID_CELL_SIZE);\n\t\t\tconst maxCol = Math.floor((node.x + node.width) / GRID_CELL_SIZE);\n\t\t\tconst minRow = Math.floor(node.y / GRID_CELL_SIZE);\n\t\t\tconst maxRow = Math.floor((node.y + node.height) / GRID_CELL_SIZE);\n\t\t\tfor (let col = minCol; col <= maxCol; col++) {\n\t\t\t\tfor (let row = minRow; row <= maxRow; row++) {\n\t\t\t\t\tconst key = `${col},${row}`;\n\t\t\t\t\tif (!this.spatialGrid[key]) this.spatialGrid[key] = [];\n\t\t\t\t\tthis.spatialGrid[key].push(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tzoom = (factor: number, origin: Coordinates) => {\n\t\tconst newScale = this.data.scale * factor;\n\t\tthis.zoomToScale(newScale, origin);\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst validNewScale = Math.max(Math.min(newScale, 20), 0.05);\n\t\tconst scale = this.data.scale;\n\t\tif (validNewScale === scale) return;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.data.offsetX = origin.x - (canvasCoords.x * validNewScale) / scale;\n\t\tthis.data.offsetY = origin.y - (canvasCoords.y * validNewScale) / scale;\n\t\tthis.data.scale = validNewScale;\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = this.data.offsetX + x;\n\t\tthis.data.offsetY = this.data.offsetY + y;\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = x;\n\t\tthis.data.offsetY = y;\n\t};\n\tshiftFullscreen = (option: string = 'toggle') => {\n\t\tif (!document.fullscreenElement && (option === 'toggle' || option === 'enter')) {\n\t\t\tthis.data.container.requestFullscreen();\n\t\t\tthis.onToggleFullscreen(true);\n\t\t} else if (document.fullscreenElement && (option === 'toggle' || option === 'exit')) {\n\t\t\tdocument.exitFullscreen();\n\t\t\tthis.onToggleFullscreen(false);\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\t// Container to Canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.data.offsetX,\n\t\ty: containerY - this.data.offsetY,\n\t});\n\t// Canvas to World\n\tprivate C2W = ({ x: canvasX, y: canvasY }: Coordinates) => ({\n\t\tx: canvasX / this.data.scale,\n\t\ty: canvasY / this.data.scale,\n\t});\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tprivate dispose = () => this.data.container.remove();\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport DataManager from '$/dataManager';\nimport utilities from '$/utilities';\n\nexport default class Controller extends BaseModule {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\thooks = {\n\t\tonResize: utilities.makeHook<[number, number]>(),\n\t\tonRefresh: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResize);\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.lastScale = this.DM.data.scale;\n\t\tthis.perFrame.lastOffsets = {\n\t\t\tx: this.DM.data.offsetX,\n\t\t\ty: this.DM.data.offsetY,\n\t\t};\n\t\tthis.hooks.onRefresh();\n\t};\n\n\tprivate onResize = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.hooks.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\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"],"names":["BaseModule","constructor","container","options","onStart","onDispose","this","Object","assign","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","getColor","colorIndex","themeColor","length","rgb","hex","cleanHex","replace","r","parseInt","substring","g","b","hexToRgb","border","background","active","makeHook","reverse","result","args","Array","from","subs","forEach","callback","Set","add","unsubscribe","delete","destroyError","GRID_CELL_SIZE","DataManager","spatialGrid","onToggleFullscreen","data","super","parentContainer","firstElementChild","remove","realContainer","noShadow","attachShadow","mode","extraCSS","HTMLContainer","classList","canvasData","nodes","edges","nodeMap","canvasBaseDir","processBaseDir","attachmentDir","nodeBounds","calculateNodeBounds","offsetX","offsetY","type","file","includes","split","id","buildSpatialGrid","resetView","dispose","baseDir","lastChar","slice","findNodeAt","screenCoords","C2W","C2C","candidates","key","floor","judgeInteract","match","minX","Infinity","minY","maxX","maxY","min","max","centerX","centerY","minCol","maxCol","minRow","maxRow","col","row","push","zoom","origin","newScale","zoomToScale","validNewScale","canvasCoords","pan","panToCoords","shiftFullscreen","option","fullscreenElement","exitFullscreen","requestFullscreen","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","initialView","containerX","containerY","canvasX","canvasY","middleViewer","Controller","animationId","resizeAnimationId","DM","resizeObserver","perFrame","lastScale","lastOffsets","lastResizeCenter","hooks","onResize","onRefresh","start","get","ResizeObserver","observe","requestAnimationFrame","draw","refresh","center","cancelAnimationFrame","disconnect"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{Pointeract as t,Click as e,Drag as s,WheelPanZoom as i,PreventDefault as a,MultitouchPanZoom as o}from"pointeract";import{B as n,d as r,u as c,D as h,C as l}from"./controller-siZ5v-SD.js";class d extends n{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;eventListeners={};DM;IH;parse;get overlaysLayer(){if(!this._overlaysLayer)throw r;return this._overlaysLayer}hooks={onInteractionStart:c.makeHook(),onInteractionEnd:c.makeHook()};constructor(...t){super(...t),this.parse=this.options.markdownParser||(t=>t),this.DM=this.container.get(h),this.IH=this.container.get(p,{lazy:!0});this.container.get(l).hooks.onRefresh.subscribe(this.updateOverlays),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="overlays",this.DM.data.container.appendChild(this.overlaysLayer),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.IH().onClick.subscribe(this.select);const t=this.DM.data.canvasBaseDir,e=async e=>{switch(e.type){case"text":this.updateOverlay(e,e.text,"text");break;case"file":e.file.match(/\.md$/i)?this.loadMarkdownForNode(e):e.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(e,t+e.file,"image"):e.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(e,t+e.file,"audio");break;case"link":this.updateOverlay(e,e.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(t=>{e(t)})};select=t=>{const e=this.selectedId?this.overlays[this.selectedId]:null,s=t?this.overlays[t]:null;e&&e.classList.remove("active"),s?(s.classList.add("active"),this.hooks.onInteractionStart()):this.hooks.onInteractionEnd(),this.selectedId=t};loadMarkdownForNode=async t=>{let e;this.updateOverlay(t,"Loading...","text");try{const s=await fetch(this.DM.data.canvasBaseDir+t.file),i=await s.text(),a=i.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=a?await this.parse(a[2]):await this.parse(i)}catch(s){console.error("[JSONCanvasViewer] Failed to load markdown:",s),e="Failed to load content."}this.updateOverlay(t,e,"text")};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};async updateOverlay(t,e,s){let i=this.overlays[t.id];if(i){if("text"===s){i.getElementsByClassName("parsed-content-wrapper")[0].innerHTML=e}}else i=await this.constructOverlay(t,e,s),this.overlaysLayer.appendChild(i),this.overlays[t.id]=i,i.style.left=`${t.x}px`,i.style.top=`${t.y}px`,i.style.width=`${t.width}px`,i.style.height=`${t.height}px`}async constructOverlay(t,e,s){const i=c.getColor(t.color),a=document.createElement("div");switch(a.classList.add("overlay-container"),a.id=t.id,a.style.backgroundColor=i.background,a.style.setProperty("--active-color",i.active),s){case"text":{a.classList.add("markdown-content");const t=document.createElement("div");t.innerHTML=await this.parse(e||""),t.classList.add("parsed-content-wrapper"),a.appendChild(t);break}case"link":{const t=document.createElement("iframe");t.src=e,t.sandbox="allow-scripts allow-same-origin",t.className="link-iframe",t.loading="lazy",a.appendChild(t);break}case"audio":{const t=document.createElement("audio");t.className="audio",t.src=e,t.controls=!0,a.appendChild(t);break}case"image":{const t=document.createElement("img");t.src=e,t.loading="lazy",a.appendChild(t)}}switch(s){case"link":case"audio":{const t=document.createElement("div");t.className="click-layer",a.appendChild(t)}}const o=document.createElement("div");o.className="overlay-border",o.style.borderColor=i.border,a.appendChild(o);const n=()=>{t.id===this.selectedId&&this.hooks.onInteractionStart()},r=()=>{t.id===this.selectedId&&this.hooks.onInteractionEnd()};return a.addEventListener("pointerenter",n),a.addEventListener("pointerleave",r),a.addEventListener("touchstart",n),a.addEventListener("touchend",r),this.eventListeners[t.id]=[n,r],a}dispose=()=>{for(;this.overlaysLayer.firstElementChild;){const t=this.overlaysLayer.firstElementChild;if(this.eventListeners[t.id]){const e=this.eventListeners[t.id][0],s=this.eventListeners[t.id][1];if(!e||!s)throw r;t.removeEventListener("pointerenter",e),t.removeEventListener("pointerleave",s),t.removeEventListener("touchstart",e),t.removeEventListener("touchend",s),this.eventListeners[t.id][0]=null,this.eventListeners[t.id][1]=null}t.remove()}this.overlaysLayer.remove(),this._overlaysLayer=null}}class p extends n{pointeract;DM;onClick=c.makeHook();stopInteraction;startInteraction;constructor(...n){super(...n),this.DM=this.container.get(h);const r=Object.assign(this.options.pointeract||{},{coordinateOutput:"relative"});this.pointeract=new t(this.DM.data.container,[e,s,i,a,o],r),this.startInteraction=this.pointeract.start,this.stopInteraction=this.pointeract.stop;const c=this.container.get(d);c.hooks.onInteractionStart.subscribe(this.stopInteraction),c.hooks.onInteractionEnd.subscribe(this.startInteraction),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.pointeract.on("pan",this.onPan),this.pointeract.on("drag",this.onPan),this.pointeract.on("zoom",this.onZoom),this.pointeract.on("trueClick",this.onTrueClick),this.pointeract.start()};onPan=t=>{this.DM.pan(t.detail)};onZoom=t=>{const e=t.detail;this.DM.zoom(e.factor,{x:e.x,y:e.y})};onTrueClick=t=>{const e=t.detail;if((s=t.detail.target)&&(s.closest(".controls")||s.closest("button")||s.closest("input")))return;var s;const i=this.DM.findNodeAt({x:e.x,y:e.y});this.onClick(i?i.id:null)};dispose=()=>{this.pointeract.off("pan",this.onPan),this.pointeract.off("zoom",this.onZoom),this.pointeract.off("trueClick",this.onTrueClick),this.pointeract.dispose()}}const m="#fff";class u extends n{_canvas;ctx;DM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(null===this._canvas)throw r;return this._canvas}constructor(...t){super(...t);const e=this.container.get(l);e.hooks.onRefresh.subscribe(this.redraw),e.hooks.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(h),this._canvas=document.createElement("canvas"),this._canvas.className="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;c.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const t=Date.now(),e=this.DM.data.offsetX,s=this.DM.data.offsetY,i=this.DM.data.scale,a=this.getCurrentViewport(e,s,i);if(this.isViewportInside(a,this.zoomInOptimize.lastDrawnViewport)&&i!==this.zoomInOptimize.lastDrawnScale){if(t-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(e,s,i,a),this.zoomInOptimize.lastCallTime=t,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(a,i)}this.zoomInOptimize.lastCallTime=t,this.trueRedraw(e,s,i,a)};trueRedraw(t,e,s,i){this.zoomInOptimize.lastDrawnViewport=i,this.zoomInOptimize.lastDrawnScale=s,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(s,s);const a=this.DM.data.canvasData;a.nodes.forEach(t=>{switch(t.type){case"group":this.drawGroup(t,s);break;case"file":this.drawFileNode(t)}}),a.edges.forEach(t=>{this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,e){const s=e/this.zoomInOptimize.lastDrawnScale,i=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*e,a=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*e;this.canvas.style.transform=`translate(${i}px, ${a}px) scale(${s})`}isViewportInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;getCurrentViewport=(t,e,s)=>{const i=-t/s,a=-e/s,o=this.DM.data.container;return{left:i,top:a,right:i+o.clientWidth/s,bottom:a+o.clientHeight/s}};drawLabelBar=(t,e,s,i,a)=>{const o=30*a,n=6*a,r=8*a,c=16*a,h=6*a;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/a,1/a),this.ctx.font=`${c}px 'Inter', sans-serif`;const l=this.ctx.measureText(s).width+2*h;this.ctx.translate(0,-o-r),this.ctx.fillStyle=i,this.ctx.beginPath(),this.ctx.moveTo(n,0),this.ctx.lineTo(l-n,0),this.ctx.quadraticCurveTo(l,0,l,n),this.ctx.lineTo(l,o-n),this.ctx.quadraticCurveTo(l,o,l-n,o),this.ctx.lineTo(n,o),this.ctx.quadraticCurveTo(0,o,0,o-n),this.ctx.lineTo(0,n),this.ctx.quadraticCurveTo(0,0,n,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=m,this.ctx.fillText(s,h,.65*o),this.ctx.restore()};drawNodeBackground=t=>{const e=c.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=e.background,c.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=e.border,this.ctx.lineWidth=2,c.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,e)=>{this.drawNodeBackground(t),t.label&&this.drawLabelBar(t.x,t.y,t.label,c.getColor(t.color).active,e)};drawFileNode=t=>{this.ctx.fillStyle=m,this.ctx.font="16px sans-serif",this.ctx.fillText(t.file,t.x+5,t.y-10)};drawEdge=t=>{const{fromNode:e,toNode:s}=this.getEdgeNodes(t),i=c.getAnchorCoord,[a,o]=i(e,t.fromSide),[n,r]=i(s,t.toSide),{active:h}=c.getColor(t.color);let[l,d,p,m]=[0,0,0,0];if(t.controlPoints?[l,d,p,m]=t.controlPoints:([l,d,p,m]=this.getControlPoints(a,o,n,r,t.fromSide,t.toSide),t.controlPoints=[l,d,p,m]),this.drawCurvedPath(a,o,n,r,l,d,p,m,h),this.drawArrowhead(n,r,p,m,h),t.label){const e=.5,s=(1-e)**3*a+3*(1-e)**2*e*l+3*(1-e)*e*e*p+e**3*n,i=(1-e)**3*o+3*(1-e)**2*e*d+3*(1-e)*e*e*m+e**3*r;this.ctx.font="18px sans-serif";const h=8,u=this.ctx.measureText(t.label).width+2*h,v=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),c.drawRoundRect(this.ctx,s-u/2,i-v/2-2,u,v,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(t.label,s,i-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getEdgeNodes=t=>({fromNode:this.DM.data.nodeMap[t.fromNode],toNode:this.DM.data.nodeMap[t.toNode]});getControlPoints=(t,e,s,i,a,o)=>{const n=s-t,r=i-e,c=Math.min(Math.abs(n),Math.abs(r))+.3*Math.max(Math.abs(n),Math.abs(r)),h=(l=.5*c,d=60,p=300,Math.max(d,Math.min(p,l)));var l,d,p;let m=t,u=e,v=s,x=i;switch(a){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":x=i-h;break;case"bottom":x=i+h;break;case"left":v=s-h;break;case"right":v=s+h}return[m,u,v,x]};drawCurvedPath=(t,e,s,i,a,o,n,r,c)=>{this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.bezierCurveTo(a,o,n,r,s,i),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,e,s,i,a)=>{const o=t-s,n=e-i,r=Math.sqrt(o*o+n*n);if(0===r)return;const c=o/r,h=n/r,l=t-12*c-7*h,d=e-12*h+7*c,p=t-12*c+7*h,m=e-12*h-7*c;this.ctx.beginPath(),this.ctx.fillStyle=a,this.ctx.moveTo(t,e),this.ctx.lineTo(l,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}}export{p as I,d as O,u as R};
2
- //# sourceMappingURL=renderer-CZ85ZN6O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer-CZ85ZN6O.js","sources":["../src/core/overlayManager.ts","../src/core/interactionHandler.ts","../src/core/renderer.ts"],"sourcesContent":["import { type BaseArgs, BaseModule } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport InteractionHandler from '$/interactionHandler';\nimport utilities, { destroyError } from '$/utilities';\nimport type { MarkdownParser } from './declarations';\n\ntype Options = {\n\tmarkdownParser?: MarkdownParser;\n};\n\nexport default class OverlayManager extends BaseModule<Options> {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate IH: () => InteractionHandler;\n\tprivate parse: MarkdownParser;\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\thooks = {\n\t\tonInteractionStart: utilities.makeHook(),\n\t\tonInteractionEnd: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.markdownParser || ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler, { lazy: true });\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.updateOverlays);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.IH().onClick.subscribe(this.select);\n\t\tconst cbd = this.DM.data.canvasBaseDir;\n\t\tconst createOverlay = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.updateOverlay(node, node.text, 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tif (node.file.match(/\\.md$/i)) this.loadMarkdownForNode(node);\n\t\t\t\t\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'image');\n\t\t\t\t\telse if (node.file.match(/\\.(mp3|wav)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'audio');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.updateOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(node => {\n\t\t\tcreateOverlay(node);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previous = !this.selectedId ? null : this.overlays[this.selectedId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous) previous.classList.remove('active');\n\t\tif (current) {\n\t\t\tcurrent.classList.add('active');\n\t\t\tthis.hooks.onInteractionStart();\n\t\t} else this.hooks.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate loadMarkdownForNode = async (node: JSONCanvasFileNode) => {\n\t\tthis.updateOverlay(node, 'Loading...', 'text');\n\t\tlet parsedContent: string;\n\t\ttry {\n\t\t\tconst response = await fetch(this.DM.data.canvasBaseDir + node.file);\n\t\t\tconst result = await response.text();\n\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\tif (frontmatterMatch) parsedContent = await this.parse(frontmatterMatch[2]);\n\t\t\telse parsedContent = await this.parse(result);\n\t\t} catch (err) {\n\t\t\tconsole.error('[JSONCanvasViewer] Failed to load markdown:', err);\n\t\t\tparsedContent = 'Failed to load content.';\n\t\t}\n\t\tthis.updateOverlay(node, parsedContent, 'text');\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate async updateOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = await this.constructOverlay(node, content, type);\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t} else if (type === 'text') {\n\t\t\tconst parsedContentContainer = element.getElementsByClassName('parsed-content-wrapper')[0];\n\t\t\tparsedContentContainer.innerHTML = content;\n\t\t}\n\t}\n\n\tprivate async constructOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tconst color = utilities.getColor(node.color);\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('overlay-container');\n\t\toverlay.id = node.id;\n\t\toverlay.style.backgroundColor = color.background;\n\t\toverlay.style.setProperty('--active-color', color.active);\n\t\tswitch (type) {\n\t\t\tcase 'text': {\n\t\t\t\toverlay.classList.add('markdown-content');\n\t\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\t\tparsedContentWrapper.innerHTML = await this.parse(content || '');\n\t\t\t\tparsedContentWrapper.classList.add('parsed-content-wrapper');\n\t\t\t\toverlay.appendChild(parsedContentWrapper);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'link': {\n\t\t\t\tconst iframe = document.createElement('iframe');\n\t\t\t\tiframe.src = content;\n\t\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\t\tiframe.className = 'link-iframe';\n\t\t\t\tiframe.loading = 'lazy';\n\t\t\t\toverlay.appendChild(iframe);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'audio': {\n\t\t\t\tconst audio = document.createElement('audio');\n\t\t\t\taudio.className = 'audio';\n\t\t\t\taudio.src = content;\n\t\t\t\taudio.controls = true;\n\t\t\t\toverlay.appendChild(audio);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst img = document.createElement('img');\n\t\t\t\timg.src = content;\n\t\t\t\timg.loading = 'lazy';\n\t\t\t\toverlay.appendChild(img);\n\t\t\t}\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase 'link':\n\t\t\tcase 'audio': {\n\t\t\t\tconst clickLayer = document.createElement('div');\n\t\t\t\tclickLayer.className = 'click-layer';\n\t\t\t\toverlay.appendChild(clickLayer);\n\t\t\t}\n\t\t}\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'overlay-border';\n\t\toverlayBorder.style.borderColor = color.border;\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t}\n\n\tprivate dispose = () => {\n\t\twhile (this.overlaysLayer.firstElementChild) {\n\t\t\tconst child = this.overlaysLayer.firstElementChild;\n\t\t\tif (this.eventListeners[child.id]) {\n\t\t\t\tconst onStart = this.eventListeners[child.id][0];\n\t\t\t\tconst onEnd = this.eventListeners[child.id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\tchild.removeEventListener('pointerenter', onStart);\n\t\t\t\tchild.removeEventListener('pointerleave', onEnd);\n\t\t\t\tchild.removeEventListener('touchstart', onStart);\n\t\t\t\tchild.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[child.id][0] = null;\n\t\t\t\tthis.eventListeners[child.id][1] = null;\n\t\t\t}\n\t\t\tchild.remove();\n\t\t}\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import {\n\tClick,\n\ttype Ctors,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype StdEvents,\n\tWheelPanZoom,\n} from 'pointeract';\nimport { type BaseArgs, BaseModule } from '$/baseModule';\nimport DataManager from '$/dataManager';\nimport OverlayManager from '$/overlayManager';\nimport utilities from '$/utilities';\n\ntype Options = {\n\tpointeract?: PointeractOptions<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n};\n\nexport default class InteractionHandler extends BaseModule<Options> {\n\tprivate pointeract: Pointeract<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n\tprivate DM: DataManager;\n\tonClick = utilities.makeHook<[string | null]>();\n\tstopInteraction: Pointeract['stop'];\n\tstartInteraction: Pointeract['start'];\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tconst options = Object.assign(this.options.pointeract || {}, {\n\t\t\tcoordinateOutput: 'relative',\n\t\t});\n\t\tthis.pointeract = new Pointeract(\n\t\t\tthis.DM.data.container,\n\t\t\t[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom],\n\t\t\toptions,\n\t\t);\n\t\tthis.startInteraction = this.pointeract.start;\n\t\tthis.stopInteraction = this.pointeract.stop;\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.hooks.onInteractionStart.subscribe(this.stopInteraction);\n\t\tOM.hooks.onInteractionEnd.subscribe(this.startInteraction);\n\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.pointeract.on('pan', this.onPan);\n\t\tthis.pointeract.on('drag', this.onPan);\n\t\tthis.pointeract.on('zoom', this.onZoom);\n\t\tthis.pointeract.on('trueClick', this.onTrueClick);\n\t\tthis.pointeract.start();\n\t};\n\n\tprivate onPan = (event: StdEvents['pan']) => {\n\t\tthis.DM.pan(event.detail);\n\t};\n\tprivate onZoom = (event: StdEvents['zoom']) => {\n\t\tconst detail = event.detail;\n\t\tthis.DM.zoom(detail.factor, { x: detail.x, y: detail.y });\n\t};\n\n\tprivate onTrueClick = (e: StdEvents['trueClick']) => {\n\t\tconst detail = e.detail;\n\t\tfunction isUIControl(target: HTMLElement | null) {\n\t\t\tif (!target) return false;\n\t\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t\t}\n\t\tif (isUIControl(e.detail.target as HTMLElement | null)) return;\n\t\tconst node = this.DM.findNodeAt({ x: detail.x, y: detail.y });\n\t\tthis.onClick(node ? node.id : null);\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.pointeract.off('pan', this.onPan);\n\t\tthis.pointeract.off('zoom', this.onZoom);\n\t\tthis.pointeract.off('trueClick', this.onTrueClick);\n\t\tthis.pointeract.dispose();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport utilities, { destroyError } from '$/utilities';\n\ninterface viewport {\n\tleft: number;\n\tright: number;\n\ttop: number;\n\tbottom: number;\n}\n\ninterface RuntimeJSONCanvasEdge extends JSONCanvasEdge {\n\tcontrolPoints?: Array<number>;\n}\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 7;\nconst NODE_RADIUS = 12;\nconst FONT_COLOR = '#fff';\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\n\nexport default class Renderer extends BaseModule {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: viewport;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (this._canvas === null) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.redraw);\n\t\tcontroller.hooks.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t\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\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (\n\t\t\tthis.isViewportInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: viewport) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tcanvasData.nodes.forEach(node => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'group':\n\t\t\t\t\tthis.drawGroup(node, scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'file':\n\t\t\t\t\tthis.drawFileNode(node);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\tcanvasData.edges.forEach(edge => {\n\t\t\tthis.drawEdge(edge);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: viewport, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX = (this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY = (this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isViewportInside = (inner: viewport, outer: viewport) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (x: number, y: number, label: string, color: string, scale: number) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = utilities.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tutilities.drawRoundRect(this.ctx, node.x + 1, node.y + 1, node.width - 2, node.height - 2, radius);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = 2;\n\t\tutilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasGroupNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label)\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, utilities.getColor(node.color).active, scale);\n\t};\n\n\tprivate drawFileNode = (node: JSONCanvasFileNode) => {\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(node.file, node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (edge: RuntimeJSONCanvasEdge) => {\n\t\tconst { fromNode, toNode } = this.getEdgeNodes(edge);\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst [startX, startY] = gac(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = gac(toNode, edge.toSide);\n\t\tconst { active } = utilities.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!edge.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\tedge.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = edge.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\tactive,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, active);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = '#222';\n\t\t\tthis.ctx.beginPath();\n\t\t\tutilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = '#ccc';\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getEdgeNodes = (edge: JSONCanvasEdge) => ({\n\t\tfromNode: this.DM.data.nodeMap[edge.fromNode],\n\t\ttoNode: this.DM.data.nodeMap[edge.toNode],\n\t});\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t\tcolor: string,\n\t) => {\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(startX, startY);\n\t\tthis.ctx.bezierCurveTo(c1x, c1y, c2x, c2y, endX, endY);\n\t\tthis.ctx.strokeStyle = color;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (tipX: number, tipY: number, fromX: number, fromY: number, color: string) => {\n\t\tconst dx = tipX - fromX;\n\t\tconst dy = tipY - fromY;\n\t\tconst length = Math.sqrt(dx * dx + dy * dy);\n\t\tif (length === 0) return;\n\t\tconst unitX = dx / length;\n\t\tconst unitY = dy / length;\n\t\tconst leftX = tipX - unitX * ARROW_LENGTH - unitY * ARROW_WIDTH;\n\t\tconst leftY = tipY - unitY * ARROW_LENGTH + unitX * ARROW_WIDTH;\n\t\tconst rightX = tipX - unitX * ARROW_LENGTH + unitY * ARROW_WIDTH;\n\t\tconst rightY = tipY - unitY * ARROW_LENGTH - unitX * ARROW_WIDTH;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.moveTo(tipX, tipY);\n\t\tthis.ctx.lineTo(leftX, leftY);\n\t\tthis.ctx.lineTo(rightX, rightY);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t};\n\n\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"],"names":["OverlayManager","BaseModule","_overlaysLayer","document","createElement","overlays","selectedId","eventListeners","DM","IH","parse","overlaysLayer","this","destroyError","hooks","onInteractionStart","utilities","makeHook","onInteractionEnd","constructor","args","super","options","markdownParser","markdown","container","get","DataManager","InteractionHandler","lazy","Controller","onRefresh","subscribe","updateOverlays","className","data","appendChild","onStart","start","onDispose","dispose","onClick","select","cbd","canvasBaseDir","createOverlay","async","node","type","updateOverlay","text","file","match","loadMarkdownForNode","url","Object","values","nodeMap","forEach","id","previous","current","classList","remove","add","parsedContent","response","fetch","result","frontmatterMatch","err","console","error","style","transform","offsetX","offsetY","scale","content","element","getElementsByClassName","innerHTML","constructOverlay","left","x","top","y","width","height","color","getColor","overlay","backgroundColor","background","setProperty","active","parsedContentWrapper","iframe","src","sandbox","loading","audio","controls","img","clickLayer","overlayBorder","borderColor","border","onEnd","addEventListener","firstElementChild","child","removeEventListener","pointeract","stopInteraction","startInteraction","assign","coordinateOutput","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","stop","OM","on","onPan","onZoom","onTrueClick","event","pan","detail","zoom","factor","e","target","closest","findNodeAt","off","FONT_COLOR","Renderer","_canvas","ctx","zoomInOptimize","lastDrawnScale","lastDrawnViewport","right","bottom","timeout","lastCallTime","canvas","controller","redraw","onResize","optimizeDPR","getContext","resizeCanvasForDPR","offsetWidth","offsetHeight","clearTimeout","now","Date","currentViewport","getCurrentViewport","isViewportInside","setTimeout","trueRedraw","fakeRedraw","clearRect","save","translate","canvasData","nodes","drawGroup","drawFileNode","edges","edge","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","clientWidth","clientHeight","drawLabelBar","label","barHeight","radius","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillText","drawNodeBackground","colors","globalAlpha","drawRoundRect","strokeStyle","lineWidth","stroke","fromNode","toNode","getEdgeNodes","gac","getAnchorCoord","startX","startY","fromSide","endX","endY","toSide","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","Math","min","abs","max","PADDING","val","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","length","sqrt","unitX","unitY","leftX","leftY","rightX","rightY"],"mappings":"mMAWA,MAAqBA,UAAuBC,EACnCC,eAAwCC,SAASC,cAAc,OAC/DC,SAA2C,CAAA,EAC3CC,WAA4B,KAC5BC,eAA8D,CAAA,EAC9DC,GACAC,GACAC,MAER,iBAAYC,GACX,IAAKC,KAAKV,eAAgB,MAAMW,EAChC,OAAOD,KAAKV,cACb,CAEAY,MAAQ,CACPC,mBAAoBC,EAAUC,WAC9BC,iBAAkBF,EAAUC,YAG7B,WAAAE,IAAeC,GACdC,SAASD,GACTR,KAAKF,MAAQE,KAAKU,QAAQC,gBAAA,CAAoBC,GAAqBA,GACnEZ,KAAKJ,GAAKI,KAAKa,UAAUC,IAAIC,GAC7Bf,KAAKH,GAAKG,KAAKa,UAAUC,IAAIE,EAAoB,CAAEC,MAAM,IACtCjB,KAAKa,UAAUC,IAAII,GAC3BhB,MAAMiB,UAAUC,UAAUpB,KAAKqB,gBAE1CrB,KAAKV,eAAiBC,SAASC,cAAc,OAC7CQ,KAAKV,eAAegC,UAAY,WAChCtB,KAAKJ,GAAG2B,KAAKV,UAAUW,YAAYxB,KAAKD,eAExCC,KAAKyB,QAAQzB,KAAK0B,OAClB1B,KAAK2B,UAAU3B,KAAK4B,QACrB,CAEQF,MAAQ,KACf1B,KAAKH,KAAKgC,QAAQT,UAAUpB,KAAK8B,QACjC,MAAMC,EAAM/B,KAAKJ,GAAG2B,KAAKS,cACnBC,EAAgBC,MAAOC,IAC5B,OAAQA,EAAKC,MACZ,IAAK,OACJpC,KAAKqC,cAAcF,EAAMA,EAAKG,KAAM,QACpC,MAED,IAAK,OACAH,EAAKI,KAAKC,MAAM,UAAWxC,KAAKyC,oBAAoBN,GAC/CA,EAAKI,KAAKC,MAAM,mCACxBxC,KAAKqC,cAAcF,EAAMJ,EAAMI,EAAKI,KAAM,SAClCJ,EAAKI,KAAKC,MAAM,kBACxBxC,KAAKqC,cAAcF,EAAMJ,EAAMI,EAAKI,KAAM,SAC3C,MAED,IAAK,OACJvC,KAAKqC,cAAcF,EAAMA,EAAKO,IAAK,UAKtCC,OAAOC,OAAO5C,KAAKJ,GAAG2B,KAAKsB,SAASC,QAAQX,IAC3CF,EAAcE,MAIRL,OAAUiB,IACjB,MAAMC,EAAYhD,KAAKN,WAAoBM,KAAKP,SAASO,KAAKN,YAA1B,KAC9BuD,EAAWF,EAAY/C,KAAKP,SAASsD,GAArB,KAClBC,GAAUA,EAASE,UAAUC,OAAO,UACpCF,GACHA,EAAQC,UAAUE,IAAI,UACtBpD,KAAKE,MAAMC,sBACLH,KAAKE,MAAMI,mBAClBN,KAAKN,WAAaqD,GAGXN,oBAAsBP,MAAOC,IAEpC,IAAIkB,EADJrD,KAAKqC,cAAcF,EAAM,aAAc,QAEvC,IACC,MAAMmB,QAAiBC,MAAMvD,KAAKJ,GAAG2B,KAAKS,cAAgBG,EAAKI,MACzDiB,QAAeF,EAAShB,OACxBmB,EAAmBD,EAAOhB,MAAM,qCAChBa,EAAlBI,QAAwCzD,KAAKF,MAAM2D,EAAiB,UAC7CzD,KAAKF,MAAM0D,EACvC,OAASE,GACRC,QAAQC,MAAM,8CAA+CF,GAC7DL,EAAgB,yBACjB,CACArD,KAAKqC,cAAcF,EAAMkB,EAAe,SAGjChC,eAAiB,KACxB,MAAME,EAAOvB,KAAKJ,GAAG2B,KACrBvB,KAAKD,cAAc8D,MAAMC,UAAY,aAAavC,EAAKwC,cAAcxC,EAAKyC,oBAAoBzC,EAAK0C,UAGpG,mBAAc5B,CAAcF,EAAsB+B,EAAiB9B,GAClE,IAAI+B,EAAUnE,KAAKP,SAAS0C,EAAKY,IACjC,GAAKoB,GAQL,GAAoB,SAAT/B,EAAiB,CACI+B,EAAQC,uBAAuB,0BAA0B,GACjEC,UAAYH,CACpC,OAVCC,QAAgBnE,KAAKsE,iBAAiBnC,EAAM+B,EAAS9B,GACrDpC,KAAKD,cAAcyB,YAAY2C,GAC/BnE,KAAKP,SAAS0C,EAAKY,IAAMoB,EACzBA,EAAQN,MAAMU,KAAO,GAAGpC,EAAKqC,MAC7BL,EAAQN,MAAMY,IAAM,GAAGtC,EAAKuC,MAC5BP,EAAQN,MAAMc,MAAQ,GAAGxC,EAAKwC,UAC9BR,EAAQN,MAAMe,OAAS,GAAGzC,EAAKyC,UAKjC,CAEA,sBAAcN,CAAiBnC,EAAsB+B,EAAiB9B,GACrE,MAAMyC,EAAQzE,EAAU0E,SAAS3C,EAAK0C,OAChCE,EAAUxF,SAASC,cAAc,OAKvC,OAJAuF,EAAQ7B,UAAUE,IAAI,qBACtB2B,EAAQhC,GAAKZ,EAAKY,GAClBgC,EAAQlB,MAAMmB,gBAAkBH,EAAMI,WACtCF,EAAQlB,MAAMqB,YAAY,iBAAkBL,EAAMM,QAC1C/C,GACP,IAAK,OAAQ,CACZ2C,EAAQ7B,UAAUE,IAAI,oBACtB,MAAMgC,EAAuB7F,SAASC,cAAc,OACpD4F,EAAqBf,gBAAkBrE,KAAKF,MAAMoE,GAAW,IAC7DkB,EAAqBlC,UAAUE,IAAI,0BACnC2B,EAAQvD,YAAY4D,GACpB,KACD,CACA,IAAK,OAAQ,CACZ,MAAMC,EAAS9F,SAASC,cAAc,UACtC6F,EAAOC,IAAMpB,EACbmB,EAAOE,QAAU,kCACjBF,EAAO/D,UAAY,cACnB+D,EAAOG,QAAU,OACjBT,EAAQvD,YAAY6D,GACpB,KACD,CACA,IAAK,QAAS,CACb,MAAMI,EAAQlG,SAASC,cAAc,SACrCiG,EAAMnE,UAAY,QAClBmE,EAAMH,IAAMpB,EACZuB,EAAMC,UAAW,EACjBX,EAAQvD,YAAYiE,GACpB,KACD,CACA,IAAK,QAAS,CACb,MAAME,EAAMpG,SAASC,cAAc,OACnCmG,EAAIL,IAAMpB,EACVyB,EAAIH,QAAU,OACdT,EAAQvD,YAAYmE,EACrB,EAED,OAAQvD,GACP,IAAK,OACL,IAAK,QAAS,CACb,MAAMwD,EAAarG,SAASC,cAAc,OAC1CoG,EAAWtE,UAAY,cACvByD,EAAQvD,YAAYoE,EACrB,EAED,MAAMC,EAAgBtG,SAASC,cAAc,OAC7CqG,EAAcvE,UAAY,iBAC1BuE,EAAchC,MAAMiC,YAAcjB,EAAMkB,OACxChB,EAAQvD,YAAYqE,GACpB,MAAMpE,EAAU,KACXU,EAAKY,KAAO/C,KAAKN,YAAYM,KAAKE,MAAMC,sBAEvC6F,EAAQ,KACT7D,EAAKY,KAAO/C,KAAKN,YAAYM,KAAKE,MAAMI,oBAO7C,OALAyE,EAAQkB,iBAAiB,eAAgBxE,GACzCsD,EAAQkB,iBAAiB,eAAgBD,GACzCjB,EAAQkB,iBAAiB,aAAcxE,GACvCsD,EAAQkB,iBAAiB,WAAYD,GACrChG,KAAKL,eAAewC,EAAKY,IAAM,CAACtB,EAASuE,GAClCjB,CACR,CAEQnD,QAAU,KACjB,KAAO5B,KAAKD,cAAcmG,mBAAmB,CAC5C,MAAMC,EAAQnG,KAAKD,cAAcmG,kBACjC,GAAIlG,KAAKL,eAAewG,EAAMpD,IAAK,CAClC,MAAMtB,EAAUzB,KAAKL,eAAewG,EAAMpD,IAAI,GACxCiD,EAAQhG,KAAKL,eAAewG,EAAMpD,IAAI,GAC5C,IAAKtB,IAAYuE,EAAO,MAAM/F,EAC9BkG,EAAMC,oBAAoB,eAAgB3E,GAC1C0E,EAAMC,oBAAoB,eAAgBJ,GAC1CG,EAAMC,oBAAoB,aAAc3E,GACxC0E,EAAMC,oBAAoB,WAAYJ,GACtChG,KAAKL,eAAewG,EAAMpD,IAAI,GAAK,KACnC/C,KAAKL,eAAewG,EAAMpD,IAAI,GAAK,IACpC,CACAoD,EAAMhD,QACP,CACAnD,KAAKD,cAAcoD,SACnBnD,KAAKV,eAAiB,MCzLxB,MAAqB0B,UAA2B3B,EACvCgH,WACAzG,GACRiC,QAAUzB,EAAUC,WACpBiG,gBACAC,iBAEA,WAAAhG,IAAeC,GACdC,SAASD,GACTR,KAAKJ,GAAKI,KAAKa,UAAUC,IAAIC,GAC7B,MAAML,EAAUiC,OAAO6D,OAAOxG,KAAKU,QAAQ2F,YAAc,GAAI,CAC5DI,iBAAkB,aAEnBzG,KAAKqG,WAAa,IAAIK,EACrB1G,KAAKJ,GAAG2B,KAAKV,UACb,CAAC8F,EAAOC,EAAMC,EAAcC,EAAgBC,GAC5CrG,GAEDV,KAAKuG,iBAAmBvG,KAAKqG,WAAW3E,MACxC1B,KAAKsG,gBAAkBtG,KAAKqG,WAAWW,KACvC,MAAMC,EAAKjH,KAAKa,UAAUC,IAAI1B,GAC9B6H,EAAG/G,MAAMC,mBAAmBiB,UAAUpB,KAAKsG,iBAC3CW,EAAG/G,MAAMI,iBAAiBc,UAAUpB,KAAKuG,kBAEzCvG,KAAKyB,QAAQzB,KAAK0B,OAClB1B,KAAK2B,UAAU3B,KAAK4B,QACrB,CAEQF,MAAQ,KACf1B,KAAKqG,WAAWa,GAAG,MAAOlH,KAAKmH,OAC/BnH,KAAKqG,WAAWa,GAAG,OAAQlH,KAAKmH,OAChCnH,KAAKqG,WAAWa,GAAG,OAAQlH,KAAKoH,QAChCpH,KAAKqG,WAAWa,GAAG,YAAalH,KAAKqH,aACrCrH,KAAKqG,WAAW3E,SAGTyF,MAASG,IAChBtH,KAAKJ,GAAG2H,IAAID,EAAME,SAEXJ,OAAUE,IACjB,MAAME,EAASF,EAAME,OACrBxH,KAAKJ,GAAG6H,KAAKD,EAAOE,OAAQ,CAAElD,EAAGgD,EAAOhD,EAAGE,EAAG8C,EAAO9C,KAG9C2C,YAAeM,IACtB,MAAMH,EAASG,EAAEH,OAKjB,IAJqBI,EAILD,EAAEH,OAAOI,UAFjBA,EAAOC,QAAQ,cAAgBD,EAAOC,QAAQ,WAAaD,EAAOC,QAAQ,UAE1B,OAJxD,IAAqBD,EAKrB,MAAMzF,EAAOnC,KAAKJ,GAAGkI,WAAW,CAAEtD,EAAGgD,EAAOhD,EAAGE,EAAG8C,EAAO9C,IACzD1E,KAAK6B,QAAQM,EAAOA,EAAKY,GAAK,OAGvBnB,QAAU,KACjB5B,KAAKqG,WAAW0B,IAAI,MAAO/H,KAAKmH,OAChCnH,KAAKqG,WAAW0B,IAAI,OAAQ/H,KAAKoH,QACjCpH,KAAKqG,WAAW0B,IAAI,YAAa/H,KAAKqH,aACtCrH,KAAKqG,WAAWzE,WC/DlB,MAGMoG,EAAa,OAGnB,MAAqBC,UAAiB5I,EAC7B6I,QACAC,IACAvI,GACAwI,eAKJ,CACHC,eAAgB,EAChBC,kBAAmB,CAClB/D,KAAM,EACNgE,MAAO,EACP9D,IAAK,EACL+D,OAAQ,GAETC,QAAS,KACTC,aAAc,GAGf,UAAYC,GACX,GAAqB,OAAjB3I,KAAKkI,QAAkB,MAAMjI,EACjC,OAAOD,KAAKkI,OACb,CAEA,WAAA3H,IAAeC,GACdC,SAASD,GACT,MAAMoI,EAAa5I,KAAKa,UAAUC,IAAII,GACtC0H,EAAW1I,MAAMiB,UAAUC,UAAUpB,KAAK6I,QAC1CD,EAAW1I,MAAM4I,SAAS1H,UAAUpB,KAAK+I,aACzC/I,KAAKJ,GAAKI,KAAKa,UAAUC,IAAIC,GAC7Bf,KAAKkI,QAAU3I,SAASC,cAAc,UACtCQ,KAAKkI,QAAQ5G,UAAY,cACzBtB,KAAKmI,IAAMnI,KAAKkI,QAAQc,WAAW,MACnChJ,KAAKJ,GAAG2B,KAAKV,UAAUW,YAAYxB,KAAKkI,SACxClI,KAAK2B,UAAU3B,KAAK4B,QACrB,CAEQmH,YAAc,KACrB,MAAMlI,EAAYb,KAAKJ,GAAG2B,KAAKV,UAC/BT,EAAU6I,mBAAmBjJ,KAAK2I,OAAQ9H,EAAUqI,YAAarI,EAAUsI,eAGpEN,OAAS,KACZ7I,KAAKoI,eAAeK,UACvBW,aAAapJ,KAAKoI,eAAeK,SACjCzI,KAAKoI,eAAeK,QAAU,MAE/B,MAAMY,EAAMC,KAAKD,MACXtF,EAAU/D,KAAKJ,GAAG2B,KAAKwC,QACvBC,EAAUhE,KAAKJ,GAAG2B,KAAKyC,QACvBC,EAAQjE,KAAKJ,GAAG2B,KAAK0C,MACrBsF,EAAkBvJ,KAAKwJ,mBAAmBzF,EAASC,EAASC,GAClE,GACCjE,KAAKyJ,iBAAiBF,EAAiBvJ,KAAKoI,eAAeE,oBAC3DrE,IAAUjE,KAAKoI,eAAeC,eAC7B,CAED,GADsBgB,EAAMrJ,KAAKoI,eAAeM,aA5DlB,IAoE7B,OANA1I,KAAKoI,eAAeK,QAAUiB,WAAW,KACxC1J,KAAK2J,WAAW5F,EAASC,EAASC,EAAOsF,GACzCvJ,KAAKoI,eAAeM,aAAeW,EACnCrJ,KAAKoI,eAAeK,QAAU,MAC5B,SACHzI,KAAK4J,WAAWL,EAAiBtF,EAGnC,CACAjE,KAAKoI,eAAeM,aAAeW,EACnCrJ,KAAK2J,WAAW5F,EAASC,EAASC,EAAOsF,IAGlC,UAAAI,CAAW5F,EAAiBC,EAAiBC,EAAesF,GACnEvJ,KAAKoI,eAAeE,kBAAoBiB,EACxCvJ,KAAKoI,eAAeC,eAAiBpE,EACrCjE,KAAK2I,OAAO9E,MAAMC,UAAY,GAC9B9D,KAAKmI,IAAI0B,UAAU,EAAG,EAAG7J,KAAK2I,OAAOhE,MAAO3E,KAAK2I,OAAO/D,QACxD5E,KAAKmI,IAAI2B,OACT9J,KAAKmI,IAAI4B,UAAUhG,EAASC,GAC5BhE,KAAKmI,IAAIlE,MAAMA,EAAOA,GACtB,MAAM+F,EAAahK,KAAKJ,GAAG2B,KAAKyI,WAChCA,EAAWC,MAAMnH,QAAQX,IACxB,OAAQA,EAAKC,MACZ,IAAK,QACJpC,KAAKkK,UAAU/H,EAAM8B,GACrB,MACD,IAAK,OACJjE,KAAKmK,aAAahI,MAIrB6H,EAAWI,MAAMtH,QAAQuH,IACxBrK,KAAKsK,SAASD,KAEfrK,KAAKmI,IAAIoC,SACV,CAEQ,UAAAX,CAAWL,EAA2BtF,GAC7C,MAAMuG,EAAWvG,EAAQjE,KAAKoI,eAAeC,eACvCoC,GAAkBzK,KAAKoI,eAAeE,kBAAkB/D,KAAOgF,EAAgBhF,MAAQN,EACvFyG,GAAkB1K,KAAKoI,eAAeE,kBAAkB7D,IAAM8E,EAAgB9E,KAAOR,EAC3FjE,KAAK2I,OAAO9E,MAAMC,UAAY,aAAa2G,QAAqBC,cAA2BF,IAC5F,CAEQf,iBAAmB,CAACkB,EAAiBC,IAC5CD,EAAMpG,KAAOqG,EAAMrG,MACnBoG,EAAMlG,IAAMmG,EAAMnG,KAClBkG,EAAMpC,MAAQqC,EAAMrC,OACpBoC,EAAMnC,OAASoC,EAAMpC,OAEdgB,mBAAqB,CAACzF,EAAiBC,EAAiBC,KAC/D,MAAMM,GAAQR,EAAUE,EAClBQ,GAAOT,EAAUC,EACjBpD,EAAYb,KAAKJ,GAAG2B,KAAKV,UAG/B,MAAO,CAAE0D,OAAME,MAAK8D,MAFNhE,EAAO1D,EAAUgK,YAAc5G,EAElBuE,OADZ/D,EAAM5D,EAAUiK,aAAe7G,IAIvC8G,aAAe,CAACvG,EAAWE,EAAWsG,EAAenG,EAAeZ,KAC3E,MAAMgH,EAAY,GAAKhH,EACjBiH,EAAS,EAAIjH,EACbkH,EAAU,EAAIlH,EACdmH,EAAW,GAAKnH,EAChBoH,EAAW,EAAIpH,EACrBjE,KAAKmI,IAAI2B,OACT9J,KAAKmI,IAAI4B,UAAUvF,EAAGE,GACtB1E,KAAKmI,IAAIlE,MAAM,EAAIA,EAAO,EAAIA,GAC9BjE,KAAKmI,IAAImD,KAAO,GAAGF,0BACnB,MAAMG,EAAWvL,KAAKmI,IAAIqD,YAAYR,GAAOrG,MAAQ,EAAI0G,EACzDrL,KAAKmI,IAAI4B,UAAU,GAAIkB,EAAYE,GACnCnL,KAAKmI,IAAIsD,UAAY5G,EACrB7E,KAAKmI,IAAIuD,YACT1L,KAAKmI,IAAIwD,OAAOT,EAAQ,GACxBlL,KAAKmI,IAAIyD,OAAOL,EAAWL,EAAQ,GACnClL,KAAKmI,IAAI0D,iBAAiBN,EAAU,EAAGA,EAAUL,GACjDlL,KAAKmI,IAAIyD,OAAOL,EAAUN,EAAYC,GACtClL,KAAKmI,IAAI0D,iBAAiBN,EAAUN,EAAWM,EAAWL,EAAQD,GAClEjL,KAAKmI,IAAIyD,OAAOV,EAAQD,GACxBjL,KAAKmI,IAAI0D,iBAAiB,EAAGZ,EAAW,EAAGA,EAAYC,GACvDlL,KAAKmI,IAAIyD,OAAO,EAAGV,GACnBlL,KAAKmI,IAAI0D,iBAAiB,EAAG,EAAGX,EAAQ,GACxClL,KAAKmI,IAAI2D,YACT9L,KAAKmI,IAAI4D,OACT/L,KAAKmI,IAAIsD,UAAYzD,EACrBhI,KAAKmI,IAAI6D,SAAShB,EAAOK,EAAsB,IAAZJ,GACnCjL,KAAKmI,IAAIoC,WAGF0B,mBAAsB9J,IAC7B,MAAM+J,EAAS9L,EAAU0E,SAAS3C,EAAK0C,OAEvC7E,KAAKmI,IAAIgE,YAAc,EACvBnM,KAAKmI,IAAIsD,UAAYS,EAAOjH,WAC5B7E,EAAUgM,cAAcpM,KAAKmI,IAAKhG,EAAKqC,EAAI,EAAGrC,EAAKuC,EAAI,EAAGvC,EAAKwC,MAAQ,EAAGxC,EAAKyC,OAAS,EA/JtE,IAgKlB5E,KAAKmI,IAAI4D,OACT/L,KAAKmI,IAAIkE,YAAcH,EAAOnG,OAC9B/F,KAAKmI,IAAImE,UAAY,EACrBlM,EAAUgM,cAAcpM,KAAKmI,IAAKhG,EAAKqC,EAAGrC,EAAKuC,EAAGvC,EAAKwC,MAAOxC,EAAKyC,OAnKjD,IAoKlB5E,KAAKmI,IAAIoE,UAGFrC,UAAY,CAAC/H,EAA2B8B,KAC/CjE,KAAKiM,mBAAmB9J,GACpBA,EAAK6I,OACRhL,KAAK+K,aAAa5I,EAAKqC,EAAGrC,EAAKuC,EAAGvC,EAAK6I,MAAO5K,EAAU0E,SAAS3C,EAAK0C,OAAOM,OAAQlB,IAG/EkG,aAAgBhI,IACvBnC,KAAKmI,IAAIsD,UAAYzD,EACrBhI,KAAKmI,IAAImD,KAAO,kBAChBtL,KAAKmI,IAAI6D,SAAS7J,EAAKI,KAAMJ,EAAKqC,EAAI,EAAGrC,EAAKuC,EAAI,KAG3C4F,SAAYD,IACnB,MAAMmC,SAAEA,EAAAC,OAAUA,GAAWzM,KAAK0M,aAAarC,GACzCsC,EAAMvM,EAAUwM,gBACfC,EAAQC,GAAUH,EAAIH,EAAUnC,EAAK0C,WACrCC,EAAMC,GAAQN,EAAIF,EAAQpC,EAAK6C,SAChC/H,OAAEA,GAAW/E,EAAU0E,SAASuF,EAAKxF,OAC3C,IAAKsI,EAAeC,EAAeC,EAAaC,GAAe,CAAC,EAAG,EAAG,EAAG,GAwBzE,GAvBKjD,EAAKkD,eAUFJ,EAAeC,EAAeC,EAAaC,GAAejD,EAAKkD,gBATrEJ,EAAeC,EAAeC,EAAaC,GAAetN,KAAKwN,iBAC/DX,EACAC,EACAE,EACAC,EACA5C,EAAK0C,SACL1C,EAAK6C,QAEN7C,EAAKkD,cAAgB,CAACJ,EAAeC,EAAeC,EAAaC,IAElEtN,KAAKyN,eACJZ,EACAC,EACAE,EACAC,EACAE,EACAC,EACAC,EACAC,EACAnI,GAEDnF,KAAK0N,cAAcV,EAAMC,EAAMI,EAAaC,EAAanI,GACrDkF,EAAKW,MAAO,CACf,MAAM2C,EAAI,GACJnJ,GACJ,EAAImJ,IAAM,EAAId,EACf,GAAK,EAAIc,IAAM,EAAIA,EAAIR,EACvB,GAAK,EAAIQ,GAAKA,EAAIA,EAAIN,EACtBM,GAAK,EAAIX,EACJtI,GACJ,EAAIiJ,IAAM,EAAIb,EACf,GAAK,EAAIa,IAAM,EAAIA,EAAIP,EACvB,GAAK,EAAIO,GAAKA,EAAIA,EAAIL,EACtBK,GAAK,EAAIV,EACVjN,KAAKmI,IAAImD,KAAO,kBAChB,MACMsC,EAAU,EACVC,EAFU7N,KAAKmI,IAAIqD,YAAYnB,EAAKW,OAEfrG,MAAkB,EAAViJ,EAC7BE,EAAc,GACpB9N,KAAKmI,IAAIsD,UAAY,OACrBzL,KAAKmI,IAAIuD,YACTtL,EAAUgM,cACTpM,KAAKmI,IACL3D,EAAIqJ,EAAa,EACjBnJ,EAAIoJ,EAAc,EAAI,EACtBD,EACAC,EACA,GAED9N,KAAKmI,IAAI4D,OACT/L,KAAKmI,IAAIsD,UAAY,OACrBzL,KAAKmI,IAAI4F,UAAY,SACrB/N,KAAKmI,IAAI6F,aAAe,SACxBhO,KAAKmI,IAAI6D,SAAS3B,EAAKW,MAAOxG,EAAGE,EAAI,GACrC1E,KAAKmI,IAAI4F,UAAY,OACrB/N,KAAKmI,IAAI6F,aAAe,YACzB,GAGOtB,aAAgBrC,IAAA,CACvBmC,SAAUxM,KAAKJ,GAAG2B,KAAKsB,QAAQwH,EAAKmC,UACpCC,OAAQzM,KAAKJ,GAAG2B,KAAKsB,QAAQwH,EAAKoC,UAG3Be,iBAAmB,CAC1BX,EACAC,EACAE,EACAC,EACAF,EACAG,KAEA,MAAMe,EAAYjB,EAAOH,EACnBqB,EAAYjB,EAAOH,EACnBqB,EACLC,KAAKC,IAAID,KAAKE,IAAIL,GAAYG,KAAKE,IAAIJ,IACvC,GAAME,KAAKG,IAAIH,KAAKE,IAAIL,GAAYG,KAAKE,IAAIJ,IAExCM,GADSC,EACsB,GAAfN,EADME,EACc,GADDE,EACK,IADWH,KAAKG,IAAIF,EAAKD,KAAKC,IAAIE,EAAKE,KAAvE,IAACA,EAAaJ,EAAaE,EAEzC,IAAIpB,EAAgBN,EAChBO,EAAgBN,EAChBO,EAAcL,EACdM,EAAcL,EAClB,OAAQF,GACP,IAAK,MACJK,EAAgBN,EAAS0B,EACzB,MACD,IAAK,SACJpB,EAAgBN,EAAS0B,EACzB,MACD,IAAK,OACJrB,EAAgBN,EAAS2B,EACzB,MACD,IAAK,QACJrB,EAAgBN,EAAS2B,EAG3B,OAAQtB,GACP,IAAK,MACJI,EAAcL,EAAOuB,EACrB,MACD,IAAK,SACJlB,EAAcL,EAAOuB,EACrB,MACD,IAAK,OACJnB,EAAcL,EAAOwB,EACrB,MACD,IAAK,QACJnB,EAAcL,EAAOwB,EAGvB,MAAO,CAACrB,EAAeC,EAAeC,EAAaC,IAG5CG,eAAiB,CACxBZ,EACAC,EACAE,EACAC,EACAyB,EACAC,EACAC,EACAC,EACAhK,KAEA7E,KAAKmI,IAAIuD,YACT1L,KAAKmI,IAAIwD,OAAOkB,EAAQC,GACxB9M,KAAKmI,IAAI2G,cAAcJ,EAAKC,EAAKC,EAAKC,EAAK7B,EAAMC,GACjDjN,KAAKmI,IAAIkE,YAAcxH,EACvB7E,KAAKmI,IAAImE,UAAY,EACrBtM,KAAKmI,IAAIoE,UAGFmB,cAAgB,CAACqB,EAAcC,EAAcC,EAAeC,EAAerK,KAClF,MAAMsK,EAAKJ,EAAOE,EACZG,EAAKJ,EAAOE,EACZG,EAASjB,KAAKkB,KAAKH,EAAKA,EAAKC,EAAKA,GACxC,GAAe,IAAXC,EAAc,OAClB,MAAME,EAAQJ,EAAKE,EACbG,EAAQJ,EAAKC,EACbI,EAAQV,EAzUK,GAyUEQ,EAxUH,EAwU0BC,EACtCE,EAAQV,EA1UK,GA0UEQ,EAzUH,EAyU0BD,EACtCI,EAASZ,EA3UI,GA2UGQ,EA1UJ,EA0U2BC,EACvCI,EAASZ,EA5UI,GA4UGQ,EA3UJ,EA2U2BD,EAC7CvP,KAAKmI,IAAIuD,YACT1L,KAAKmI,IAAIsD,UAAY5G,EACrB7E,KAAKmI,IAAIwD,OAAOoD,EAAMC,GACtBhP,KAAKmI,IAAIyD,OAAO6D,EAAOC,GACvB1P,KAAKmI,IAAIyD,OAAO+D,EAAQC,GACxB5P,KAAKmI,IAAI2D,YACT9L,KAAKmI,IAAI4D,QAGFnK,QAAU,KACb5B,KAAKoI,eAAeK,UACvBW,aAAapJ,KAAKoI,eAAeK,SACjCzI,KAAKoI,eAAeK,QAAU,MAE/BzI,KAAK2I,OAAOxF,SACZnD,KAAKkI,QAAU"}
@@ -1,2 +0,0 @@
1
- "use strict";const t=require("pointeract"),e=require("./controller--Q72jFEw.cjs");class i extends e.BaseModule{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;eventListeners={};DM;IH;parse;get overlaysLayer(){if(!this._overlaysLayer)throw e.destroyError;return this._overlaysLayer}hooks={onInteractionStart:e.utilities.makeHook(),onInteractionEnd:e.utilities.makeHook()};constructor(...t){super(...t),this.parse=this.options.markdownParser||(t=>t),this.DM=this.container.get(e.DataManager),this.IH=this.container.get(s,{lazy:!0});this.container.get(e.Controller).hooks.onRefresh.subscribe(this.updateOverlays),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="overlays",this.DM.data.container.appendChild(this.overlaysLayer),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.IH().onClick.subscribe(this.select);const t=this.DM.data.canvasBaseDir,e=async e=>{switch(e.type){case"text":this.updateOverlay(e,e.text,"text");break;case"file":e.file.match(/\.md$/i)?this.loadMarkdownForNode(e):e.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(e,t+e.file,"image"):e.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(e,t+e.file,"audio");break;case"link":this.updateOverlay(e,e.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(t=>{e(t)})};select=t=>{const e=this.selectedId?this.overlays[this.selectedId]:null,i=t?this.overlays[t]:null;e&&e.classList.remove("active"),i?(i.classList.add("active"),this.hooks.onInteractionStart()):this.hooks.onInteractionEnd(),this.selectedId=t};loadMarkdownForNode=async t=>{let e;this.updateOverlay(t,"Loading...","text");try{const i=await fetch(this.DM.data.canvasBaseDir+t.file),s=await i.text(),a=s.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=a?await this.parse(a[2]):await this.parse(s)}catch(i){console.error("[JSONCanvasViewer] Failed to load markdown:",i),e="Failed to load content."}this.updateOverlay(t,e,"text")};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};async updateOverlay(t,e,i){let s=this.overlays[t.id];if(s){if("text"===i){s.getElementsByClassName("parsed-content-wrapper")[0].innerHTML=e}}else s=await this.constructOverlay(t,e,i),this.overlaysLayer.appendChild(s),this.overlays[t.id]=s,s.style.left=`${t.x}px`,s.style.top=`${t.y}px`,s.style.width=`${t.width}px`,s.style.height=`${t.height}px`}async constructOverlay(t,i,s){const a=e.utilities.getColor(t.color),o=document.createElement("div");switch(o.classList.add("overlay-container"),o.id=t.id,o.style.backgroundColor=a.background,o.style.setProperty("--active-color",a.active),s){case"text":{o.classList.add("markdown-content");const t=document.createElement("div");t.innerHTML=await this.parse(i||""),t.classList.add("parsed-content-wrapper"),o.appendChild(t);break}case"link":{const t=document.createElement("iframe");t.src=i,t.sandbox="allow-scripts allow-same-origin",t.className="link-iframe",t.loading="lazy",o.appendChild(t);break}case"audio":{const t=document.createElement("audio");t.className="audio",t.src=i,t.controls=!0,o.appendChild(t);break}case"image":{const t=document.createElement("img");t.src=i,t.loading="lazy",o.appendChild(t)}}switch(s){case"link":case"audio":{const t=document.createElement("div");t.className="click-layer",o.appendChild(t)}}const r=document.createElement("div");r.className="overlay-border",r.style.borderColor=a.border,o.appendChild(r);const n=()=>{t.id===this.selectedId&&this.hooks.onInteractionStart()},c=()=>{t.id===this.selectedId&&this.hooks.onInteractionEnd()};return o.addEventListener("pointerenter",n),o.addEventListener("pointerleave",c),o.addEventListener("touchstart",n),o.addEventListener("touchend",c),this.eventListeners[t.id]=[n,c],o}dispose=()=>{for(;this.overlaysLayer.firstElementChild;){const t=this.overlaysLayer.firstElementChild;if(this.eventListeners[t.id]){const i=this.eventListeners[t.id][0],s=this.eventListeners[t.id][1];if(!i||!s)throw e.destroyError;t.removeEventListener("pointerenter",i),t.removeEventListener("pointerleave",s),t.removeEventListener("touchstart",i),t.removeEventListener("touchend",s),this.eventListeners[t.id][0]=null,this.eventListeners[t.id][1]=null}t.remove()}this.overlaysLayer.remove(),this._overlaysLayer=null}}class s extends e.BaseModule{pointeract;DM;onClick=e.utilities.makeHook();stopInteraction;startInteraction;constructor(...s){super(...s),this.DM=this.container.get(e.DataManager);const a=Object.assign(this.options.pointeract||{},{coordinateOutput:"relative"});this.pointeract=new t.Pointeract(this.DM.data.container,[t.Click,t.Drag,t.WheelPanZoom,t.PreventDefault,t.MultitouchPanZoom],a),this.startInteraction=this.pointeract.start,this.stopInteraction=this.pointeract.stop;const o=this.container.get(i);o.hooks.onInteractionStart.subscribe(this.stopInteraction),o.hooks.onInteractionEnd.subscribe(this.startInteraction),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.pointeract.on("pan",this.onPan),this.pointeract.on("drag",this.onPan),this.pointeract.on("zoom",this.onZoom),this.pointeract.on("trueClick",this.onTrueClick),this.pointeract.start()};onPan=t=>{this.DM.pan(t.detail)};onZoom=t=>{const e=t.detail;this.DM.zoom(e.factor,{x:e.x,y:e.y})};onTrueClick=t=>{const e=t.detail;if((i=t.detail.target)&&(i.closest(".controls")||i.closest("button")||i.closest("input")))return;var i;const s=this.DM.findNodeAt({x:e.x,y:e.y});this.onClick(s?s.id:null)};dispose=()=>{this.pointeract.off("pan",this.onPan),this.pointeract.off("zoom",this.onZoom),this.pointeract.off("trueClick",this.onTrueClick),this.pointeract.dispose()}}const a="#fff";class o extends e.BaseModule{_canvas;ctx;DM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(null===this._canvas)throw e.destroyError;return this._canvas}constructor(...t){super(...t);const i=this.container.get(e.Controller);i.hooks.onRefresh.subscribe(this.redraw),i.hooks.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(e.DataManager),this._canvas=document.createElement("canvas"),this._canvas.className="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;e.utilities.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const t=Date.now(),e=this.DM.data.offsetX,i=this.DM.data.offsetY,s=this.DM.data.scale,a=this.getCurrentViewport(e,i,s);if(this.isViewportInside(a,this.zoomInOptimize.lastDrawnViewport)&&s!==this.zoomInOptimize.lastDrawnScale){if(t-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(e,i,s,a),this.zoomInOptimize.lastCallTime=t,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(a,s)}this.zoomInOptimize.lastCallTime=t,this.trueRedraw(e,i,s,a)};trueRedraw(t,e,i,s){this.zoomInOptimize.lastDrawnViewport=s,this.zoomInOptimize.lastDrawnScale=i,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(i,i);const a=this.DM.data.canvasData;a.nodes.forEach(t=>{switch(t.type){case"group":this.drawGroup(t,i);break;case"file":this.drawFileNode(t)}}),a.edges.forEach(t=>{this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,e){const i=e/this.zoomInOptimize.lastDrawnScale,s=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*e,a=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*e;this.canvas.style.transform=`translate(${s}px, ${a}px) scale(${i})`}isViewportInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;getCurrentViewport=(t,e,i)=>{const s=-t/i,a=-e/i,o=this.DM.data.container;return{left:s,top:a,right:s+o.clientWidth/i,bottom:a+o.clientHeight/i}};drawLabelBar=(t,e,i,s,o)=>{const r=30*o,n=6*o,c=8*o,l=16*o,h=6*o;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/o,1/o),this.ctx.font=`${l}px 'Inter', sans-serif`;const d=this.ctx.measureText(i).width+2*h;this.ctx.translate(0,-r-c),this.ctx.fillStyle=s,this.ctx.beginPath(),this.ctx.moveTo(n,0),this.ctx.lineTo(d-n,0),this.ctx.quadraticCurveTo(d,0,d,n),this.ctx.lineTo(d,r-n),this.ctx.quadraticCurveTo(d,r,d-n,r),this.ctx.lineTo(n,r),this.ctx.quadraticCurveTo(0,r,0,r-n),this.ctx.lineTo(0,n),this.ctx.quadraticCurveTo(0,0,n,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=a,this.ctx.fillText(i,h,.65*r),this.ctx.restore()};drawNodeBackground=t=>{const i=e.utilities.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=i.background,e.utilities.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=i.border,this.ctx.lineWidth=2,e.utilities.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,i)=>{this.drawNodeBackground(t),t.label&&this.drawLabelBar(t.x,t.y,t.label,e.utilities.getColor(t.color).active,i)};drawFileNode=t=>{this.ctx.fillStyle=a,this.ctx.font="16px sans-serif",this.ctx.fillText(t.file,t.x+5,t.y-10)};drawEdge=t=>{const{fromNode:i,toNode:s}=this.getEdgeNodes(t),a=e.utilities.getAnchorCoord,[o,r]=a(i,t.fromSide),[n,c]=a(s,t.toSide),{active:l}=e.utilities.getColor(t.color);let[h,d,p,m]=[0,0,0,0];if(t.controlPoints?[h,d,p,m]=t.controlPoints:([h,d,p,m]=this.getControlPoints(o,r,n,c,t.fromSide,t.toSide),t.controlPoints=[h,d,p,m]),this.drawCurvedPath(o,r,n,c,h,d,p,m,l),this.drawArrowhead(n,c,p,m,l),t.label){const i=.5,s=(1-i)**3*o+3*(1-i)**2*i*h+3*(1-i)*i*i*p+i**3*n,a=(1-i)**3*r+3*(1-i)**2*i*d+3*(1-i)*i*i*m+i**3*c;this.ctx.font="18px sans-serif";const l=8,u=this.ctx.measureText(t.label).width+2*l,v=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),e.utilities.drawRoundRect(this.ctx,s-u/2,a-v/2-2,u,v,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(t.label,s,a-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getEdgeNodes=t=>({fromNode:this.DM.data.nodeMap[t.fromNode],toNode:this.DM.data.nodeMap[t.toNode]});getControlPoints=(t,e,i,s,a,o)=>{const r=i-t,n=s-e,c=Math.min(Math.abs(r),Math.abs(n))+.3*Math.max(Math.abs(r),Math.abs(n)),l=(h=.5*c,d=60,p=300,Math.max(d,Math.min(p,h)));var h,d,p;let m=t,u=e,v=i,x=s;switch(a){case"top":u=e-l;break;case"bottom":u=e+l;break;case"left":m=t-l;break;case"right":m=t+l}switch(o){case"top":x=s-l;break;case"bottom":x=s+l;break;case"left":v=i-l;break;case"right":v=i+l}return[m,u,v,x]};drawCurvedPath=(t,e,i,s,a,o,r,n,c)=>{this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.bezierCurveTo(a,o,r,n,i,s),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,e,i,s,a)=>{const o=t-i,r=e-s,n=Math.sqrt(o*o+r*r);if(0===n)return;const c=o/n,l=r/n,h=t-12*c-7*l,d=e-12*l+7*c,p=t-12*c+7*l,m=e-12*l-7*c;this.ctx.beginPath(),this.ctx.fillStyle=a,this.ctx.moveTo(t,e),this.ctx.lineTo(h,d),this.ctx.lineTo(p,m),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null),this.canvas.remove(),this._canvas=null}}exports.InteractionHandler=s,exports.OverlayManager=i,exports.Renderer=o;
2
- //# sourceMappingURL=renderer-D9iInH9_.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer-D9iInH9_.cjs","sources":["../src/core/overlayManager.ts","../src/core/interactionHandler.ts","../src/core/renderer.ts"],"sourcesContent":["import { type BaseArgs, BaseModule } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport InteractionHandler from '$/interactionHandler';\nimport utilities, { destroyError } from '$/utilities';\nimport type { MarkdownParser } from './declarations';\n\ntype Options = {\n\tmarkdownParser?: MarkdownParser;\n};\n\nexport default class OverlayManager extends BaseModule<Options> {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate IH: () => InteractionHandler;\n\tprivate parse: MarkdownParser;\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\thooks = {\n\t\tonInteractionStart: utilities.makeHook(),\n\t\tonInteractionEnd: utilities.makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.markdownParser || ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler, { lazy: true });\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.updateOverlays);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.IH().onClick.subscribe(this.select);\n\t\tconst cbd = this.DM.data.canvasBaseDir;\n\t\tconst createOverlay = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.updateOverlay(node, node.text, 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tif (node.file.match(/\\.md$/i)) this.loadMarkdownForNode(node);\n\t\t\t\t\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'image');\n\t\t\t\t\telse if (node.file.match(/\\.(mp3|wav)$/i))\n\t\t\t\t\t\tthis.updateOverlay(node, cbd + node.file, 'audio');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.updateOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(node => {\n\t\t\tcreateOverlay(node);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previous = !this.selectedId ? null : this.overlays[this.selectedId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous) previous.classList.remove('active');\n\t\tif (current) {\n\t\t\tcurrent.classList.add('active');\n\t\t\tthis.hooks.onInteractionStart();\n\t\t} else this.hooks.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate loadMarkdownForNode = async (node: JSONCanvasFileNode) => {\n\t\tthis.updateOverlay(node, 'Loading...', 'text');\n\t\tlet parsedContent: string;\n\t\ttry {\n\t\t\tconst response = await fetch(this.DM.data.canvasBaseDir + node.file);\n\t\t\tconst result = await response.text();\n\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\tif (frontmatterMatch) parsedContent = await this.parse(frontmatterMatch[2]);\n\t\t\telse parsedContent = await this.parse(result);\n\t\t} catch (err) {\n\t\t\tconsole.error('[JSONCanvasViewer] Failed to load markdown:', err);\n\t\t\tparsedContent = 'Failed to load content.';\n\t\t}\n\t\tthis.updateOverlay(node, parsedContent, 'text');\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate async updateOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = await this.constructOverlay(node, content, type);\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t} else if (type === 'text') {\n\t\t\tconst parsedContentContainer = element.getElementsByClassName('parsed-content-wrapper')[0];\n\t\t\tparsedContentContainer.innerHTML = content;\n\t\t}\n\t}\n\n\tprivate async constructOverlay(node: JSONCanvasNode, content: string, type: string) {\n\t\tconst color = utilities.getColor(node.color);\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('overlay-container');\n\t\toverlay.id = node.id;\n\t\toverlay.style.backgroundColor = color.background;\n\t\toverlay.style.setProperty('--active-color', color.active);\n\t\tswitch (type) {\n\t\t\tcase 'text': {\n\t\t\t\toverlay.classList.add('markdown-content');\n\t\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\t\tparsedContentWrapper.innerHTML = await this.parse(content || '');\n\t\t\t\tparsedContentWrapper.classList.add('parsed-content-wrapper');\n\t\t\t\toverlay.appendChild(parsedContentWrapper);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'link': {\n\t\t\t\tconst iframe = document.createElement('iframe');\n\t\t\t\tiframe.src = content;\n\t\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\t\tiframe.className = 'link-iframe';\n\t\t\t\tiframe.loading = 'lazy';\n\t\t\t\toverlay.appendChild(iframe);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'audio': {\n\t\t\t\tconst audio = document.createElement('audio');\n\t\t\t\taudio.className = 'audio';\n\t\t\t\taudio.src = content;\n\t\t\t\taudio.controls = true;\n\t\t\t\toverlay.appendChild(audio);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst img = document.createElement('img');\n\t\t\t\timg.src = content;\n\t\t\t\timg.loading = 'lazy';\n\t\t\t\toverlay.appendChild(img);\n\t\t\t}\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase 'link':\n\t\t\tcase 'audio': {\n\t\t\t\tconst clickLayer = document.createElement('div');\n\t\t\t\tclickLayer.className = 'click-layer';\n\t\t\t\toverlay.appendChild(clickLayer);\n\t\t\t}\n\t\t}\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'overlay-border';\n\t\toverlayBorder.style.borderColor = color.border;\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t}\n\n\tprivate dispose = () => {\n\t\twhile (this.overlaysLayer.firstElementChild) {\n\t\t\tconst child = this.overlaysLayer.firstElementChild;\n\t\t\tif (this.eventListeners[child.id]) {\n\t\t\t\tconst onStart = this.eventListeners[child.id][0];\n\t\t\t\tconst onEnd = this.eventListeners[child.id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\tchild.removeEventListener('pointerenter', onStart);\n\t\t\t\tchild.removeEventListener('pointerleave', onEnd);\n\t\t\t\tchild.removeEventListener('touchstart', onStart);\n\t\t\t\tchild.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[child.id][0] = null;\n\t\t\t\tthis.eventListeners[child.id][1] = null;\n\t\t\t}\n\t\t\tchild.remove();\n\t\t}\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import {\n\tClick,\n\ttype Ctors,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype StdEvents,\n\tWheelPanZoom,\n} from 'pointeract';\nimport { type BaseArgs, BaseModule } from '$/baseModule';\nimport DataManager from '$/dataManager';\nimport OverlayManager from '$/overlayManager';\nimport utilities from '$/utilities';\n\ntype Options = {\n\tpointeract?: PointeractOptions<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n};\n\nexport default class InteractionHandler extends BaseModule<Options> {\n\tprivate pointeract: Pointeract<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n\tprivate DM: DataManager;\n\tonClick = utilities.makeHook<[string | null]>();\n\tstopInteraction: Pointeract['stop'];\n\tstartInteraction: Pointeract['start'];\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tconst options = Object.assign(this.options.pointeract || {}, {\n\t\t\tcoordinateOutput: 'relative',\n\t\t});\n\t\tthis.pointeract = new Pointeract(\n\t\t\tthis.DM.data.container,\n\t\t\t[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom],\n\t\t\toptions,\n\t\t);\n\t\tthis.startInteraction = this.pointeract.start;\n\t\tthis.stopInteraction = this.pointeract.stop;\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.hooks.onInteractionStart.subscribe(this.stopInteraction);\n\t\tOM.hooks.onInteractionEnd.subscribe(this.startInteraction);\n\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.pointeract.on('pan', this.onPan);\n\t\tthis.pointeract.on('drag', this.onPan);\n\t\tthis.pointeract.on('zoom', this.onZoom);\n\t\tthis.pointeract.on('trueClick', this.onTrueClick);\n\t\tthis.pointeract.start();\n\t};\n\n\tprivate onPan = (event: StdEvents['pan']) => {\n\t\tthis.DM.pan(event.detail);\n\t};\n\tprivate onZoom = (event: StdEvents['zoom']) => {\n\t\tconst detail = event.detail;\n\t\tthis.DM.zoom(detail.factor, { x: detail.x, y: detail.y });\n\t};\n\n\tprivate onTrueClick = (e: StdEvents['trueClick']) => {\n\t\tconst detail = e.detail;\n\t\tfunction isUIControl(target: HTMLElement | null) {\n\t\t\tif (!target) return false;\n\t\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t\t}\n\t\tif (isUIControl(e.detail.target as HTMLElement | null)) return;\n\t\tconst node = this.DM.findNodeAt({ x: detail.x, y: detail.y });\n\t\tthis.onClick(node ? node.id : null);\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.pointeract.off('pan', this.onPan);\n\t\tthis.pointeract.off('zoom', this.onZoom);\n\t\tthis.pointeract.off('trueClick', this.onTrueClick);\n\t\tthis.pointeract.dispose();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport utilities, { destroyError } from '$/utilities';\n\ninterface viewport {\n\tleft: number;\n\tright: number;\n\ttop: number;\n\tbottom: number;\n}\n\ninterface RuntimeJSONCanvasEdge extends JSONCanvasEdge {\n\tcontrolPoints?: Array<number>;\n}\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 7;\nconst NODE_RADIUS = 12;\nconst FONT_COLOR = '#fff';\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\n\nexport default class Renderer extends BaseModule {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: viewport;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (this._canvas === null) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.redraw);\n\t\tcontroller.hooks.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t\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\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (\n\t\t\tthis.isViewportInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: viewport) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tcanvasData.nodes.forEach(node => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'group':\n\t\t\t\t\tthis.drawGroup(node, scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'file':\n\t\t\t\t\tthis.drawFileNode(node);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\tcanvasData.edges.forEach(edge => {\n\t\t\tthis.drawEdge(edge);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: viewport, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX = (this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY = (this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isViewportInside = (inner: viewport, outer: viewport) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (x: number, y: number, label: string, color: string, scale: number) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = utilities.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tutilities.drawRoundRect(this.ctx, node.x + 1, node.y + 1, node.width - 2, node.height - 2, radius);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = 2;\n\t\tutilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasGroupNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label)\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, utilities.getColor(node.color).active, scale);\n\t};\n\n\tprivate drawFileNode = (node: JSONCanvasFileNode) => {\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(node.file, node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (edge: RuntimeJSONCanvasEdge) => {\n\t\tconst { fromNode, toNode } = this.getEdgeNodes(edge);\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst [startX, startY] = gac(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = gac(toNode, edge.toSide);\n\t\tconst { active } = utilities.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!edge.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\tedge.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = edge.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\tactive,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, active);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = '#222';\n\t\t\tthis.ctx.beginPath();\n\t\t\tutilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = '#ccc';\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getEdgeNodes = (edge: JSONCanvasEdge) => ({\n\t\tfromNode: this.DM.data.nodeMap[edge.fromNode],\n\t\ttoNode: this.DM.data.nodeMap[edge.toNode],\n\t});\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t\tcolor: string,\n\t) => {\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(startX, startY);\n\t\tthis.ctx.bezierCurveTo(c1x, c1y, c2x, c2y, endX, endY);\n\t\tthis.ctx.strokeStyle = color;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (tipX: number, tipY: number, fromX: number, fromY: number, color: string) => {\n\t\tconst dx = tipX - fromX;\n\t\tconst dy = tipY - fromY;\n\t\tconst length = Math.sqrt(dx * dx + dy * dy);\n\t\tif (length === 0) return;\n\t\tconst unitX = dx / length;\n\t\tconst unitY = dy / length;\n\t\tconst leftX = tipX - unitX * ARROW_LENGTH - unitY * ARROW_WIDTH;\n\t\tconst leftY = tipY - unitY * ARROW_LENGTH + unitX * ARROW_WIDTH;\n\t\tconst rightX = tipX - unitX * ARROW_LENGTH + unitY * ARROW_WIDTH;\n\t\tconst rightY = tipY - unitY * ARROW_LENGTH - unitX * ARROW_WIDTH;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.moveTo(tipX, tipY);\n\t\tthis.ctx.lineTo(leftX, leftY);\n\t\tthis.ctx.lineTo(rightX, rightY);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t};\n\n\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"],"names":["OverlayManager","BaseModule","_overlaysLayer","document","createElement","overlays","selectedId","eventListeners","DM","IH","parse","overlaysLayer","this","destroyError","hooks","onInteractionStart","utilities","makeHook","onInteractionEnd","constructor","args","super","options","markdownParser","markdown","container","get","DataManager","InteractionHandler","lazy","Controller","onRefresh","subscribe","updateOverlays","className","data","appendChild","onStart","start","onDispose","dispose","onClick","select","cbd","canvasBaseDir","createOverlay","async","node","type","updateOverlay","text","file","match","loadMarkdownForNode","url","Object","values","nodeMap","forEach","id","previous","current","classList","remove","add","parsedContent","response","fetch","result","frontmatterMatch","err","console","error","style","transform","offsetX","offsetY","scale","content","element","getElementsByClassName","innerHTML","constructOverlay","left","x","top","y","width","height","color","getColor","overlay","backgroundColor","background","setProperty","active","parsedContentWrapper","iframe","src","sandbox","loading","audio","controls","img","clickLayer","overlayBorder","borderColor","border","onEnd","addEventListener","firstElementChild","child","removeEventListener","pointeract","stopInteraction","startInteraction","assign","coordinateOutput","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","stop","OM","on","onPan","onZoom","onTrueClick","event","pan","detail","zoom","factor","e","target","closest","findNodeAt","off","FONT_COLOR","Renderer","_canvas","ctx","zoomInOptimize","lastDrawnScale","lastDrawnViewport","right","bottom","timeout","lastCallTime","canvas","controller","redraw","onResize","optimizeDPR","getContext","resizeCanvasForDPR","offsetWidth","offsetHeight","clearTimeout","now","Date","currentViewport","getCurrentViewport","isViewportInside","setTimeout","trueRedraw","fakeRedraw","clearRect","save","translate","canvasData","nodes","drawGroup","drawFileNode","edges","edge","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","clientWidth","clientHeight","drawLabelBar","label","barHeight","radius","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillText","drawNodeBackground","colors","globalAlpha","drawRoundRect","strokeStyle","lineWidth","stroke","fromNode","toNode","getEdgeNodes","gac","getAnchorCoord","startX","startY","fromSide","endX","endY","toSide","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","Math","min","abs","max","PADDING","val","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","length","sqrt","unitX","unitY","leftX","leftY","rightX","rightY"],"mappings":"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"}