json-canvas-viewer 3.3.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +145 -156
  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-BRBUPg_j.js +2 -0
  9. package/dist/controller-BRBUPg_j.js.map +1 -0
  10. package/dist/controller-Bc-S4ZVK.cjs +2 -0
  11. package/dist/controller-Bc-S4ZVK.cjs.map +1 -0
  12. package/dist/dev.cjs +1 -1
  13. package/dist/dev.js +1 -1
  14. package/dist/index-DJQyGIFX.js +2 -0
  15. package/dist/index-DJQyGIFX.js.map +1 -0
  16. package/dist/index-DwvIUSbr.cjs +2 -0
  17. package/dist/index-DwvIUSbr.cjs.map +1 -0
  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/react.cjs +2 -0
  25. package/dist/react.cjs.map +1 -0
  26. package/dist/react.js +2 -0
  27. package/dist/react.js.map +1 -0
  28. package/dist/renderToString-ChykAKof.js +2 -0
  29. package/dist/renderToString-ChykAKof.js.map +1 -0
  30. package/dist/renderToString-Cxh5DtRo.cjs +2 -0
  31. package/dist/renderToString-Cxh5DtRo.cjs.map +1 -0
  32. package/dist/renderer-0RqgAOLH.js +2 -0
  33. package/dist/renderer-0RqgAOLH.js.map +1 -0
  34. package/dist/renderer-BEKV7hr3.cjs +2 -0
  35. package/dist/renderer-BEKV7hr3.cjs.map +1 -0
  36. package/dist/types/bridges/reactComponent.d.ts +6 -3
  37. package/dist/types/bridges/vueComponent.vue.d.ts +7 -2
  38. package/dist/types/bridges/webpackPlugin.d.ts +7 -0
  39. package/dist/types/bridges.d.ts +1 -2
  40. package/dist/types/core/baseModule.d.ts +13 -9
  41. package/dist/types/core/controller.d.ts +6 -1
  42. package/dist/types/core/dataManager.d.ts +23 -16
  43. package/dist/types/core/declarations.d.ts +20 -4
  44. package/dist/types/core/index.d.ts +16 -5
  45. package/dist/types/core/interactionHandler.d.ts +3 -1
  46. package/dist/types/core/overlayManager.d.ts +7 -1
  47. package/dist/types/core/renderer.d.ts +9 -2
  48. package/dist/types/core/styleManager.d.ts +48 -0
  49. package/dist/types/core/utilities.d.ts +3 -6
  50. package/dist/types/dev.d.ts +1 -0
  51. package/dist/types/index.d.ts +1 -1
  52. package/dist/types/modules/controls/index.d.ts +4 -1
  53. package/dist/types/modules/minimap/index.d.ts +5 -1
  54. package/dist/types/modules/mistouchPreventer/index.d.ts +7 -5
  55. package/dist/vue.cjs +2 -0
  56. package/dist/vue.cjs.map +1 -0
  57. package/dist/vue.js +2 -0
  58. package/dist/vue.js.map +1 -0
  59. package/dist/webpackLoader.js +33 -0
  60. package/package.json +56 -41
  61. package/dist/controller-CnUlrkdp.cjs +0 -2
  62. package/dist/controller-CnUlrkdp.cjs.map +0 -1
  63. package/dist/controller-UN-hOZ_r.js +0 -2
  64. package/dist/controller-UN-hOZ_r.js.map +0 -1
  65. package/dist/index-RXeXyAu0.cjs +0 -2
  66. package/dist/index-RXeXyAu0.cjs.map +0 -1
  67. package/dist/index-ujiv9m9Y.js +0 -2
  68. package/dist/index-ujiv9m9Y.js.map +0 -1
  69. package/dist/renderer-Bzv3aLXp.cjs +0 -2
  70. package/dist/renderer-Bzv3aLXp.cjs.map +0 -1
  71. package/dist/renderer-NPxavnke.js +0 -2
  72. package/dist/renderer-NPxavnke.js.map +0 -1
@@ -0,0 +1,33 @@
1
+ import { validate } from "schema-utils";
2
+ const schema = {
3
+ type: "object",
4
+ properties: {
5
+ parser: { instanceof: "Function" }
6
+ }
7
+ };
8
+ async function jsonCanvasLoader(source) {
9
+ const options = this.getOptions() || {};
10
+ validate(schema, options, { name: "JSON Canvas Loader" });
11
+ const { parser } = options;
12
+ this.cacheable(true);
13
+ try {
14
+ const json = JSON.parse(source);
15
+ if (parser && Array.isArray(json.nodes)) {
16
+ await Promise.all(
17
+ json.nodes.map(async (node) => {
18
+ if (node.type === "text") {
19
+ node.text = await parser(node.text);
20
+ }
21
+ })
22
+ );
23
+ }
24
+ return `export default ${JSON.stringify(json)}`;
25
+ } catch (e) {
26
+ this.emitError(`[json-canvas] Failed to parse ${this.resourcePath}: ${e.message}`);
27
+ }
28
+ }
29
+ const raw = true;
30
+ export {
31
+ jsonCanvasLoader as default,
32
+ raw
33
+ };
package/package.json CHANGED
@@ -1,11 +1,35 @@
1
1
  {
2
2
  "name": "json-canvas-viewer",
3
- "version": "3.3.1",
3
+ "version": "3.4.0",
4
4
  "description": "An extensible web-based viewer for JSON Canvas, easy to embed into websites.",
5
+ "keywords": [
6
+ "front-end",
7
+ "html-canvas",
8
+ "json-canvas",
9
+ "obsidian",
10
+ "typescript"
11
+ ],
12
+ "homepage": "https://hesprs.github.io/json-canvas-viewer",
13
+ "bugs": {
14
+ "url": "https://github.com/hesprs/json-canvas-viewer/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": {
18
+ "name": "Hēsperus",
19
+ "email": "hesprs@outlook.com"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/hesprs/json-canvas-viewer.git"
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
5
28
  "type": "module",
6
- "types": "dist/types/index.d.ts",
29
+ "sideEffects": false,
7
30
  "main": "dist/index.cjs",
8
31
  "module": "dist/index.js",
32
+ "types": "dist/types/index.d.ts",
9
33
  "exports": {
10
34
  ".": {
11
35
  "types": "./dist/types/index.d.ts",
@@ -26,59 +50,50 @@
26
50
  "types": "./dist/types/bridges.d.ts",
27
51
  "import": "./dist/bridges.js",
28
52
  "require": "./dist/bridges.cjs"
53
+ },
54
+ "./vue": {
55
+ "types": "./dist/types/bridges/vueComponent.d.ts",
56
+ "import": "./dist/vue.js",
57
+ "require": "./dist/vue.cjs"
58
+ },
59
+ "./react": {
60
+ "types": "./dist/types/bridges/reactComponent.d.ts",
61
+ "import": "./dist/react.js",
62
+ "require": "./dist/react.cjs"
29
63
  }
30
64
  },
31
- "repository": {
32
- "type": "git",
33
- "url": "git+https://github.com/hesprs/json-canvas-viewer.git"
34
- },
35
- "homepage": "https://hesprs.github.io/json-canvas-viewer",
36
- "bugs": {
37
- "url": "https://github.com/hesprs/json-canvas-viewer/issues"
38
- },
39
- "keywords": [
40
- "obsidian",
41
- "json-canvas",
42
- "front-end",
43
- "html-canvas",
44
- "typescript"
45
- ],
46
- "author": {
47
- "name": "Hēsperus",
48
- "email": "hesprs@outlook.com"
49
- },
50
- "sideEffects": false,
51
65
  "publishConfig": {
52
- "provenance": true,
53
- "access": "public"
66
+ "access": "public",
67
+ "provenance": true
68
+ },
69
+ "dependencies": {
70
+ "@ahmedsemih/color-fns": "^1.3.0",
71
+ "@needle-di/core": "^1.1.0",
72
+ "pointeract": "^1.0.1"
54
73
  },
55
- "license": "MIT",
56
74
  "devDependencies": {
57
- "@biomejs/biome": "^2.3.10",
58
- "@types/node": "^25.0.6",
59
- "@types/react": "^19.2.8",
75
+ "@types/node": "^25.0.10",
76
+ "@types/react": "^19.2.9",
60
77
  "@vitejs/plugin-vue": "^6.0.3",
61
78
  "dompurify": "^3.3.1",
62
79
  "marked": "^17.0.1",
80
+ "oxfmt": "^0.26.0",
81
+ "oxlint": "^1.41.0",
82
+ "oxlint-tsgolint": "^0.11.1",
63
83
  "react": "^19.2.3",
64
- "sass": "^1.97.2",
84
+ "sass": "^1.97.3",
85
+ "schema-utils": "^4.3.3",
65
86
  "tsc-alias": "^1.8.16",
66
87
  "typescript": "^5.9.3",
67
88
  "vite": "^7.3.1",
68
- "vue": "^3.5.26",
69
- "vue-tsc": "^3.2.2"
70
- },
71
- "files": [
72
- "dist"
73
- ],
74
- "dependencies": {
75
- "@needle-di/core": "^1.1.0",
76
- "pointeract": "^1.0.1"
89
+ "vue": "^3.5.27",
90
+ "vue-tsc": "^3.2.3",
91
+ "webpack": "^5.104.1"
77
92
  },
78
93
  "scripts": {
79
94
  "dev": "vite",
80
- "lint": "biome check --write",
81
- "build": "vite build && BUILD=chimp vite build && vue-tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
82
- "check": "tsc --noEmit && biome check"
95
+ "lint": "oxlint --type-aware --fix && oxfmt",
96
+ "build": "vite build && BUILD=webpack_loader vite build && BUILD=chimp vite build && vue-tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
97
+ "check": "vue-tsc && oxfmt --check && oxlint --type-aware"
83
98
  }
84
99
  }
@@ -1,2 +0,0 @@
1
- "use strict";class t{constructor(t,e,s,a){this.container=t,Object.assign(this.options,e),this.onStart=s.subscribe,this.onDispose=a.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 a=window.devicePixelRatio||1,i=t.getContext("2d");if(!i)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*a),t.height=Math.round(s*a),i.setTransform(1,0,0,1,0,0),i.scale(a,a)},applyStyles:function(t,e){const s=document.createElement("style");s.innerHTML=e,t.appendChild(s)},drawRoundRect:function(t,e,s,a,i,o){t.beginPath(),t.moveTo(e+o,s),t.lineTo(e+a-o,s),t.quadraticCurveTo(e+a,s,e+a,s+o),t.lineTo(e+a,s+i-o),t.quadraticCurveTo(e+a,s+i,e+a-o,s+i),t.lineTo(e+o,s+i),t.quadraticCurveTo(e,s+i,e,s+i-o),t.lineTo(e,s+o),t.quadraticCurveTo(e,s,e+o,s),t.closePath()},getAnchorCoord:function(t,e){const s=t.x+t.width/2,a=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,a];case"right":return[t.x+t.width,a];default:return[s,a]}},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 a=800;class i 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 a=this.options.noShadow||!1?s:s.attachShadow({mode:"open"});e.applyStyles(a,".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 i=document.createElement("div");i.classList.add("container"),a.appendChild(i);const o=Object.assign({nodes:[],edges:[]},this.options.canvas);this.data={canvasData:o,canvasMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(o),offsetX:0,offsetY:0,scale:1,container:i},this.data.canvasData.nodes.forEach(t=>{this.data.canvasMap[t.id]={type:"node",ref:t};const e=this.data.canvasMap[t.id],s=e.ref;if("file"===s.type){const t=s.file.split("/").pop()||"";e.fileName=t,s.file.startsWith("http://")||s.file.startsWith("https://")||(s.file=this.data.canvasBaseDir+t)}}),this.data.canvasData.edges.forEach(t=>{this.data.canvasMap[t.id]={type:"edge",ref: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 i=[];if(this.spatialGrid){const t=`${Math.floor(e/a)},${Math.floor(s/a)}`;i=this.spatialGrid[t]||[]}else i=this.data.canvasData.nodes;for(const a of i)if(!(e<a.x||e>a.x+a.width||s<a.y||s>a.y+a.height||"non-interactive"===this.judgeInteract(a)))return a;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,a=-1/0,i=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),s=Math.min(s,t.y),a=Math.max(a,t.x+t.width),i=Math.max(i,t.y+t.height)});const o=a-e,r=i-s;return{minX:e,minY:s,maxX:a,maxY:i,width:o,height:r,centerX:e+o/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/a),s=Math.floor((e.x+e.width)/a),i=Math.floor(e.y/a),o=Math.floor((e.y+e.height)/a);for(let a=t;a<=s;a++)for(let t=i;t<=o;t++){const s=`${a},${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),a=this.data.scale;if(s===a)return;const i=this.C2C(e);this.data.offsetX=e.x-i.x*s/a,this.data.offsetY=e.y-i.y*s/a,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,a=t.height+200,i=e.clientWidth,o=e.clientHeight,r=i/s,n=o/a,l=Math.round(1e3*Math.min(r,n))/1e3,c={scale:l,offsetX:i/2-t.centerX*l,offsetY:o/2-t.centerY*l};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.scale};C2C=({x:t,y:e})=>({x:t-this.data.offsetX,y:e-this.data.offsetY});C2W=({x:t,y:e})=>({x:t/this.data.scale,y:e/this.data.scale});middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>this.data.container.remove()}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(i),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=i,exports.destroyError=s,exports.utilities=e;
2
- //# sourceMappingURL=controller-CnUlrkdp.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller-CnUlrkdp.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 interface MapNodeItem {\n\ttype: 'node';\n\tref: JSONCanvasNode;\n\tfileName?: string;\n}\n\nexport interface MapEdgeItem {\n\ttype: 'edge';\n\tref: JSONCanvasEdge;\n\tcontrolPoints?: Array<number>;\n}\n\ntype MapItem = MapEdgeItem | MapNodeItem;\n\ntype CanvasMap = Record<string, MapItem>;\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\tcanvasMap: CanvasMap;\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\tcanvasMap: {},\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\tthis.data.canvasMap[node.id] = {\n\t\t\t\ttype: 'node',\n\t\t\t\tref: node,\n\t\t\t};\n\t\t\tconst target = this.data.canvasMap[node.id] as MapNodeItem;\n\t\t\tconst ref = target.ref;\n\t\t\tif (ref.type === 'file') {\n\t\t\t\tconst path = ref.file.split('/');\n\t\t\t\tconst fileName = path.pop() || '';\n\t\t\t\ttarget.fileName = fileName;\n\t\t\t\tif (!ref.file.startsWith('http://') && !ref.file.startsWith('https://'))\n\t\t\t\t\tref.file = this.data.canvasBaseDir + fileName;\n\t\t\t}\n\t\t});\n\t\tthis.data.canvasData.edges.forEach(edge => {\n\t\t\tthis.data.canvasMap[edge.id] = {\n\t\t\t\ttype: 'edge',\n\t\t\t\tref: edge,\n\t\t\t};\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","canvasMap","canvasBaseDir","processBaseDir","attachmentDir","nodeBounds","calculateNodeBounds","offsetX","offsetY","id","type","ref","target","fileName","file","split","pop","startsWith","edge","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,a,s){this.container=t,Object.assign(this.options,e),this.onStart=a.subscribe,this.onDispose=s.subscribe}onStart;onDispose;options={}}const e={round:function(t,e){const a=10**e;return Math.round(t*a)/a},resizeCanvasForDPR:function(t,e,a){const s=window.devicePixelRatio||1,i=t.getContext("2d");if(!i)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*s),t.height=Math.round(a*s),i.setTransform(1,0,0,1,0,0),i.scale(s,s)},applyStyles:function(t,e){const a=document.createElement("style");a.innerHTML=e,t.appendChild(a)},drawRoundRect:function(t,e,a,s,i,o){t.beginPath(),t.moveTo(e+o,a),t.lineTo(e+s-o,a),t.quadraticCurveTo(e+s,a,e+s,a+o),t.lineTo(e+s,a+i-o),t.quadraticCurveTo(e+s,a+i,e+s-o,a+i),t.lineTo(e+o,a+i),t.quadraticCurveTo(e,a+i,e,a+i-o),t.lineTo(e,a+o),t.quadraticCurveTo(e,a,e+o,a),t.closePath()},getAnchorCoord:function(t,e){const a=t.x+t.width/2,s=t.y+t.height/2;switch(e){case"top":return[a,t.y];case"bottom":return[a,t.y+t.height];case"left":return[t.x,s];case"right":return[t.x+t.width,s];default:return[a,s]}},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 a=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(${a.r}, ${a.g}, ${a.b}, ?)`}return{border:e.replace("?","0.75"),background:e.replace("?","0.1"),active:e.replace("?","1")}},makeHook:function(t=!1){const e=(...a)=>{if(t){Array.from(e.subs).reverse().forEach(t=>{t(...a)})}else e.subs.forEach(t=>{t(...a)})};return e.subs=/* @__PURE__ */new Set,e.subscribe=t=>{e.subs.add(t)},e.unsubscribe=t=>{e.subs.delete(t)},e}},a=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");const s=800;class i extends t{spatialGrid=null;onToggleFullscreen=e.makeHook();data;constructor(...t){super(...t);const a=this.options.container;for(;a.firstElementChild;)a.firstElementChild.remove();a.innerHTML="";const s=this.options.noShadow||!1?a:a.attachShadow({mode:"open"});e.applyStyles(s,".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 i=document.createElement("div");i.classList.add("container"),s.appendChild(i);const o=Object.assign({nodes:[],edges:[]},this.options.canvas);this.data={canvasData:o,canvasMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(o),offsetX:0,offsetY:0,scale:1,container:i},this.data.canvasData.nodes.forEach(t=>{this.data.canvasMap[t.id]={type:"node",ref:t};const e=this.data.canvasMap[t.id],a=e.ref;if("file"===a.type){const t=a.file.split("/").pop()||"";e.fileName=t,a.file.startsWith("http://")||a.file.startsWith("https://")||(a.file=this.data.canvasBaseDir+t)}}),this.data.canvasData.edges.forEach(t=>{this.data.canvasMap[t.id]={type:"edge",ref: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:a}=this.C2W(this.C2C({x:t.x,y:t.y}));let i=[];if(this.spatialGrid){const t=`${Math.floor(e/s)},${Math.floor(a/s)}`;i=this.spatialGrid[t]||[]}else i=this.data.canvasData.nodes;for(const s of i)if(!(e<s.x||e>s.x+s.width||a<s.y||a>s.y+s.height||"non-interactive"===this.judgeInteract(s)))return s;return null};judgeInteract=t=>{switch(t?.type){case"text":case"link":return"select";case"file":return t.file.match(/\.(md|wav|mp3)$/i)?"select":"non-interactive";default:return"non-interactive"}};calculateNodeBounds(t){let e=1/0,a=1/0,s=-1/0,i=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),a=Math.min(a,t.y),s=Math.max(s,t.x+t.width),i=Math.max(i,t.y+t.height)});const o=s-e,n=i-a;return{minX:e,minY:a,maxX:s,maxY:i,width:o,height:n,centerX:e+o/2,centerY:a+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/s),a=Math.floor((e.x+e.width)/s),i=Math.floor(e.y/s),o=Math.floor((e.y+e.height)/s);for(let s=t;s<=a;s++)for(let t=i;t<=o;t++){const a=`${s},${t}`;this.spatialGrid[a]||(this.spatialGrid[a]=[]),this.spatialGrid[a].push(e)}}}}zoom=(t,e)=>{const a=this.data.scale*t;this.zoomToScale(a,e)};zoomToScale=(t,e)=>{const a=Math.max(Math.min(t,20),.05),s=this.data.scale;if(a===s)return;const i=this.C2C(e);this.data.offsetX=e.x-i.x*a/s,this.data.offsetY=e.y-i.y*a/s,this.data.scale=a};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 a=t.width+200,s=t.height+200,i=e.clientWidth,o=e.clientHeight,n=i/a,r=o/s,c=Math.round(1e3*Math.min(n,r))/1e3,h={scale:c,offsetX:i/2-t.centerX*c,offsetY:o/2-t.centerY*c};this.data.offsetX=h.offsetX,this.data.offsetY=h.offsetY,this.data.scale=h.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 o 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(i),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,o as C,i as D,a as d,e as u};
2
- //# sourceMappingURL=controller-UN-hOZ_r.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller-UN-hOZ_r.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 interface MapNodeItem {\n\ttype: 'node';\n\tref: JSONCanvasNode;\n\tfileName?: string;\n}\n\nexport interface MapEdgeItem {\n\ttype: 'edge';\n\tref: JSONCanvasEdge;\n\tcontrolPoints?: Array<number>;\n}\n\ntype MapItem = MapEdgeItem | MapNodeItem;\n\ntype CanvasMap = Record<string, MapItem>;\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\tcanvasMap: CanvasMap;\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\tcanvasMap: {},\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\tthis.data.canvasMap[node.id] = {\n\t\t\t\ttype: 'node',\n\t\t\t\tref: node,\n\t\t\t};\n\t\t\tconst target = this.data.canvasMap[node.id] as MapNodeItem;\n\t\t\tconst ref = target.ref;\n\t\t\tif (ref.type === 'file') {\n\t\t\t\tconst path = ref.file.split('/');\n\t\t\t\tconst fileName = path.pop() || '';\n\t\t\t\ttarget.fileName = fileName;\n\t\t\t\tif (!ref.file.startsWith('http://') && !ref.file.startsWith('https://'))\n\t\t\t\t\tref.file = this.data.canvasBaseDir + fileName;\n\t\t\t}\n\t\t});\n\t\tthis.data.canvasData.edges.forEach(edge => {\n\t\t\tthis.data.canvasMap[edge.id] = {\n\t\t\t\ttype: 'edge',\n\t\t\t\tref: edge,\n\t\t\t};\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","canvasMap","canvasBaseDir","processBaseDir","attachmentDir","nodeBounds","calculateNodeBounds","offsetX","offsetY","id","type","ref","target","fileName","file","split","pop","startsWith","edge","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
- "use strict";const i=require("@needle-di/core"),t=require("./controller-CnUlrkdp.cjs"),o=require("./renderer-Bzv3aLXp.cjs");exports.JSONCanvasViewer=class{options;allModules;IO=null;onStart=t.utilities.makeHook();onDispose=t.utilities.makeHook(!0);container;constructor(e,s){this.container=new i.Container,this.options=e;this.allModules=[t.DataManager,t.Controller,o.OverlayManager,o.InteractionHandler,o.Renderer,...s||[]],this.allModules.forEach(i=>{this.container.bind({provide:i,useFactory:()=>new i(this.container,this.options,this.onStart,this.onDispose)})}),this.options.lazyLoading?(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container)):this.load()}load=()=>{this.allModules.forEach(i=>{this.container.get(i)}),this.onStart()};onVisibilityCheck=i=>{i.forEach(i=>{if(i.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};dispose=()=>{this.IO?.disconnect(),this.IO=null;const i=this.options.container;for(;i.firstChild;)i.firstChild.remove();this.onDispose(),this.container.unbindAll()}};
2
- //# sourceMappingURL=index-RXeXyAu0.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-RXeXyAu0.cjs","sources":["../src/core/index.ts"],"sourcesContent":["import { Container } from '@needle-di/core';\nimport type { GeneralModuleCtor } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport type { ModuleInputCtor, UserOptions } from '$/declarations';\nimport InteractionHandler from '$/interactionHandler';\nimport OverlayManager from '$/overlayManager';\nimport Renderer from '$/renderer';\nimport utilities from '$/utilities';\n\nexport default class JSONCanvasViewer<M extends ModuleInputCtor = []> {\n\tprivate options: UserOptions<M>;\n\tprivate allModules: ModuleInputCtor;\n\tprivate IO: IntersectionObserver | null = null;\n\tprivate onStart = utilities.makeHook();\n\tprivate onDispose = utilities.makeHook(true);\n\tcontainer: Container;\n\n\tconstructor(options: UserOptions<M>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () => new Class(this.container, this.options, this.onStart, this.onDispose),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [\n\t\t\tDataManager,\n\t\t\tController,\n\t\t\tOverlayManager,\n\t\t\tInteractionHandler,\n\t\t\tRenderer,\n\t\t\t...(modules || []),\n\t\t];\n\n\t\tthis.allModules.forEach(bind);\n\t\tif (this.options.lazyLoading) {\n\t\t\tthis.IO = new IntersectionObserver(this.onVisibilityCheck, {\n\t\t\t\troot: null,\n\t\t\t\trootMargin: '50px',\n\t\t\t\tthreshold: 0,\n\t\t\t});\n\t\t\tthis.IO.observe(this.options.container);\n\t\t} else this.load();\n\t}\n\n\tprivate load = () => {\n\t\tthis.allModules.forEach(Module => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\t\tthis.onStart();\n\t};\n\n\tprivate onVisibilityCheck = (entries: Array<IntersectionObserverEntry>) => {\n\t\tentries.forEach(entry => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tthis.load();\n\t\t\t\tthis.IO?.disconnect();\n\t\t\t\tthis.IO = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t});\n\t};\n\n\tdispose = () => {\n\t\tthis.IO?.disconnect();\n\t\tthis.IO = null;\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.onDispose();\n\t\tthis.container.unbindAll();\n\t};\n}\n"],"names":["options","allModules","IO","onStart","utilities","makeHook","onDispose","container","constructor","modules","this","Container","DataManager","Controller","OverlayManager","InteractionHandler","Renderer","forEach","Class","bind","provide","useFactory","lazyLoading","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","observe","load","Module","get","entries","entry","isIntersecting","disconnect","dispose","firstChild","remove","unbindAll"],"mappings":"qJAUA,MACSA,QACAC,WACAC,GAAkC,KAClCC,QAAUC,EAAAA,UAAUC,WACpBC,UAAYF,EAAAA,UAAUC,UAAS,GACvCE,UAEA,WAAAC,CAAYR,EAAyBS,GACpCC,KAAKH,UAAY,IAAII,YACrBD,KAAKV,QAAUA,EAOfU,KAAKT,WAAa,CACjBW,EAAAA,YACAC,EAAAA,WACAC,EAAAA,eACAC,EAAAA,mBACAC,EAAAA,YACIP,GAAW,IAGhBC,KAAKT,WAAWgB,QAfFC,IACbR,KAAKH,UAAUY,KAAK,CACnBC,QAASF,EACTG,WAAY,IAAM,IAAIH,EAAMR,KAAKH,UAAWG,KAAKV,QAASU,KAAKP,QAASO,KAAKJ,eAa3EI,KAAKV,QAAQsB,aAChBZ,KAAKR,GAAK,IAAIqB,qBAAqBb,KAAKc,kBAAmB,CAC1DC,KAAM,KACNC,WAAY,OACZC,UAAW,IAEZjB,KAAKR,GAAG0B,QAAQlB,KAAKV,QAAQO,iBAClBsB,MACb,CAEQA,KAAO,KACdnB,KAAKT,WAAWgB,QAAQa,IACvBpB,KAAKH,UAAUwB,IAAID,KAEpBpB,KAAKP,WAGEqB,kBAAqBQ,IAC5BA,EAAQf,QAAQgB,IACf,GAAIA,EAAMC,eAIT,OAHAxB,KAAKmB,OACLnB,KAAKR,IAAIiC,kBACTzB,KAAKR,GAAK,SAMbkC,QAAU,KACT1B,KAAKR,IAAIiC,aACTzB,KAAKR,GAAK,KACV,MAAMK,EAAYG,KAAKV,QAAQO,UAC/B,KAAOA,EAAU8B,YAAY9B,EAAU8B,WAAWC,SAClD5B,KAAKJ,YACLI,KAAKH,UAAUgC"}
@@ -1,2 +0,0 @@
1
- import{Container as o}from"@needle-di/core";import{u as i,D as s,C as t}from"./controller-UN-hOZ_r.js";import{O as n,I as e,R as r}from"./renderer-NPxavnke.js";class a{options;allModules;IO=null;onStart=i.makeHook();onDispose=i.makeHook(!0);container;constructor(i,a){this.container=new o,this.options=i;this.allModules=[s,t,n,e,r,...a||[]],this.allModules.forEach(o=>{this.container.bind({provide:o,useFactory:()=>new o(this.container,this.options,this.onStart,this.onDispose)})}),this.options.lazyLoading?(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container)):this.load()}load=()=>{this.allModules.forEach(o=>{this.container.get(o)}),this.onStart()};onVisibilityCheck=o=>{o.forEach(o=>{if(o.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};dispose=()=>{this.IO?.disconnect(),this.IO=null;const o=this.options.container;for(;o.firstChild;)o.firstChild.remove();this.onDispose(),this.container.unbindAll()}}export{a as J};
2
- //# sourceMappingURL=index-ujiv9m9Y.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-ujiv9m9Y.js","sources":["../src/core/index.ts"],"sourcesContent":["import { Container } from '@needle-di/core';\nimport type { GeneralModuleCtor } from '$/baseModule';\nimport Controller from '$/controller';\nimport DataManager from '$/dataManager';\nimport type { ModuleInputCtor, UserOptions } from '$/declarations';\nimport InteractionHandler from '$/interactionHandler';\nimport OverlayManager from '$/overlayManager';\nimport Renderer from '$/renderer';\nimport utilities from '$/utilities';\n\nexport default class JSONCanvasViewer<M extends ModuleInputCtor = []> {\n\tprivate options: UserOptions<M>;\n\tprivate allModules: ModuleInputCtor;\n\tprivate IO: IntersectionObserver | null = null;\n\tprivate onStart = utilities.makeHook();\n\tprivate onDispose = utilities.makeHook(true);\n\tcontainer: Container;\n\n\tconstructor(options: UserOptions<M>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () => new Class(this.container, this.options, this.onStart, this.onDispose),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [\n\t\t\tDataManager,\n\t\t\tController,\n\t\t\tOverlayManager,\n\t\t\tInteractionHandler,\n\t\t\tRenderer,\n\t\t\t...(modules || []),\n\t\t];\n\n\t\tthis.allModules.forEach(bind);\n\t\tif (this.options.lazyLoading) {\n\t\t\tthis.IO = new IntersectionObserver(this.onVisibilityCheck, {\n\t\t\t\troot: null,\n\t\t\t\trootMargin: '50px',\n\t\t\t\tthreshold: 0,\n\t\t\t});\n\t\t\tthis.IO.observe(this.options.container);\n\t\t} else this.load();\n\t}\n\n\tprivate load = () => {\n\t\tthis.allModules.forEach(Module => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\t\tthis.onStart();\n\t};\n\n\tprivate onVisibilityCheck = (entries: Array<IntersectionObserverEntry>) => {\n\t\tentries.forEach(entry => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tthis.load();\n\t\t\t\tthis.IO?.disconnect();\n\t\t\t\tthis.IO = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t});\n\t};\n\n\tdispose = () => {\n\t\tthis.IO?.disconnect();\n\t\tthis.IO = null;\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.onDispose();\n\t\tthis.container.unbindAll();\n\t};\n}\n"],"names":["JSONCanvasViewer","options","allModules","IO","onStart","utilities","makeHook","onDispose","container","constructor","modules","this","Container","DataManager","Controller","OverlayManager","InteractionHandler","Renderer","forEach","Class","bind","provide","useFactory","lazyLoading","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","observe","load","Module","get","entries","entry","isIntersecting","disconnect","dispose","firstChild","remove","unbindAll"],"mappings":"gKAUA,MAAqBA,EACZC,QACAC,WACAC,GAAkC,KAClCC,QAAUC,EAAUC,WACpBC,UAAYF,EAAUC,UAAS,GACvCE,UAEA,WAAAC,CAAYR,EAAyBS,GACpCC,KAAKH,UAAY,IAAII,EACrBD,KAAKV,QAAUA,EAOfU,KAAKT,WAAa,CACjBW,EACAC,EACAC,EACAC,EACAC,KACIP,GAAW,IAGhBC,KAAKT,WAAWgB,QAfFC,IACbR,KAAKH,UAAUY,KAAK,CACnBC,QAASF,EACTG,WAAY,IAAM,IAAIH,EAAMR,KAAKH,UAAWG,KAAKV,QAASU,KAAKP,QAASO,KAAKJ,eAa3EI,KAAKV,QAAQsB,aAChBZ,KAAKR,GAAK,IAAIqB,qBAAqBb,KAAKc,kBAAmB,CAC1DC,KAAM,KACNC,WAAY,OACZC,UAAW,IAEZjB,KAAKR,GAAG0B,QAAQlB,KAAKV,QAAQO,iBAClBsB,MACb,CAEQA,KAAO,KACdnB,KAAKT,WAAWgB,QAAQa,IACvBpB,KAAKH,UAAUwB,IAAID,KAEpBpB,KAAKP,WAGEqB,kBAAqBQ,IAC5BA,EAAQf,QAAQgB,IACf,GAAIA,EAAMC,eAIT,OAHAxB,KAAKmB,OACLnB,KAAKR,IAAIiC,kBACTzB,KAAKR,GAAK,SAMbkC,QAAU,KACT1B,KAAKR,IAAIiC,aACTzB,KAAKR,GAAK,KACV,MAAMK,EAAYG,KAAKV,QAAQO,UAC/B,KAAOA,EAAU8B,YAAY9B,EAAU8B,WAAWC,SAClD5B,KAAKJ,YACLI,KAAKH,UAAUgC"}
@@ -1,2 +0,0 @@
1
- "use strict";const t=require("pointeract"),e=require("./controller-CnUlrkdp.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=async t=>{switch(t.type){case"text":this.updateOverlay(t,t.text,"text");break;case"file":t.file.match(/\.md$/i)?this.loadMarkdownForNode(t):t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(t,t.file,"image"):t.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(t,t.file,"audio");break;case"link":this.updateOverlay(t,t.url,"link")}};Object.values(this.DM.data.canvasMap).forEach(e=>{"node"===e.type&&t(e.ref)})};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(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),Object.values(this.DM.data.canvasMap).forEach(t=>{if("edge"===t.type)this.drawEdge(t);else{const e=t.ref;"file"===e.type?this.drawFile(t):"group"===e.type&&this.drawGroup(e,i)}}),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)};drawFile=t=>{this.ctx.fillStyle=a;const e=t.ref;this.ctx.font="16px sans-serif",this.ctx.fillText(t.fileName||"",e.x+5,e.y-10)};drawEdge=t=>{const i=t.ref,s=this.DM.data.canvasMap[i.fromNode].ref,a=this.DM.data.canvasMap[i.toNode].ref,o=e.utilities.getAnchorCoord,[r,n]=o(s,i.fromSide),[c,l]=o(a,i.toSide),{active:h}=e.utilities.getColor(i.color);let[d,p,m,u]=[0,0,0,0];if(t.controlPoints?[d,p,m,u]=t.controlPoints:([d,p,m,u]=this.getControlPoints(r,n,c,l,i.fromSide,i.toSide),t.controlPoints=[d,p,m,u]),this.drawCurvedPath(r,n,c,l,d,p,m,u,h),this.drawArrowhead(c,l,m,u,h),i.label){const t=.5,s=(1-t)**3*r+3*(1-t)**2*t*d+3*(1-t)*t*t*m+t**3*c,a=(1-t)**3*n+3*(1-t)**2*t*p+3*(1-t)*t*t*u+t**3*l;this.ctx.font="18px sans-serif";const o=8,h=this.ctx.measureText(i.label).width+2*o,v=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),e.utilities.drawRoundRect(this.ctx,s-h/2,a-v/2-2,h,v,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(i.label,s,a-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};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-Bzv3aLXp.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer-Bzv3aLXp.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 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, node.file, 'image');\n\t\t\t\t\telse if (node.file.match(/\\.(mp3|wav)$/i)) this.updateOverlay(node, 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.canvasMap).forEach(node => {\n\t\t\tif (node.type === 'node') createOverlay(node.ref);\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(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, { type MapEdgeItem, type MapNodeItem } from '$/dataManager';\nimport utilities, { destroyError } from '$/utilities';\n\ninterface viewport {\n\tleft: number;\n\tright: number;\n\ttop: number;\n\tbottom: 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\tObject.values(this.DM.data.canvasMap).forEach(item => {\n\t\t\tif (item.type === 'edge') this.drawEdge(item);\n\t\t\telse {\n\t\t\t\tconst node = item.ref;\n\t\t\t\tif (node.type === 'file') this.drawFile(item);\n\t\t\t\telse if (node.type === 'group') this.drawGroup(node, scale);\n\t\t\t}\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 drawFile = (item: MapNodeItem) => {\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tconst node = item.ref;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(item.fileName || '', node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (item: MapEdgeItem) => {\n\t\tconst edge = item.ref;\n\t\tconst fromNode = this.DM.data.canvasMap[edge.fromNode].ref as JSONCanvasNode;\n\t\tconst toNode = this.DM.data.canvasMap[edge.toNode].ref as JSONCanvasNode;\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 (!item.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\titem.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = item.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\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 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","createOverlay","async","node","type","updateOverlay","text","file","match","loadMarkdownForNode","url","Object","values","canvasMap","forEach","ref","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","item","drawEdge","drawFile","drawGroup","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","fileName","edge","fromNode","toNode","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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"}
@@ -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 l,C as h}from"./controller-UN-hOZ_r.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(l),this.IH=this.container.get(p,{lazy:!0});this.container.get(h).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=async t=>{switch(t.type){case"text":this.updateOverlay(t,t.text,"text");break;case"file":t.file.match(/\.md$/i)?this.loadMarkdownForNode(t):t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)?this.updateOverlay(t,t.file,"image"):t.file.match(/\.(mp3|wav)$/i)&&this.updateOverlay(t,t.file,"audio");break;case"link":this.updateOverlay(t,t.url,"link")}};Object.values(this.DM.data.canvasMap).forEach(e=>{"node"===e.type&&t(e.ref)})};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(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(l);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(h);e.hooks.onRefresh.subscribe(this.redraw),e.hooks.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(l),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),Object.values(this.DM.data.canvasMap).forEach(t=>{if("edge"===t.type)this.drawEdge(t);else{const e=t.ref;"file"===e.type?this.drawFile(t):"group"===e.type&&this.drawGroup(e,s)}}),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,l=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 h=this.ctx.measureText(s).width+2*l;this.ctx.translate(0,-o-r),this.ctx.fillStyle=i,this.ctx.beginPath(),this.ctx.moveTo(n,0),this.ctx.lineTo(h-n,0),this.ctx.quadraticCurveTo(h,0,h,n),this.ctx.lineTo(h,o-n),this.ctx.quadraticCurveTo(h,o,h-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,l,.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)};drawFile=t=>{this.ctx.fillStyle=m;const e=t.ref;this.ctx.font="16px sans-serif",this.ctx.fillText(t.fileName||"",e.x+5,e.y-10)};drawEdge=t=>{const e=t.ref,s=this.DM.data.canvasMap[e.fromNode].ref,i=this.DM.data.canvasMap[e.toNode].ref,a=c.getAnchorCoord,[o,n]=a(s,e.fromSide),[r,l]=a(i,e.toSide),{active:h}=c.getColor(e.color);let[d,p,m,u]=[0,0,0,0];if(t.controlPoints?[d,p,m,u]=t.controlPoints:([d,p,m,u]=this.getControlPoints(o,n,r,l,e.fromSide,e.toSide),t.controlPoints=[d,p,m,u]),this.drawCurvedPath(o,n,r,l,d,p,m,u,h),this.drawArrowhead(r,l,m,u,h),e.label){const t=.5,s=(1-t)**3*o+3*(1-t)**2*t*d+3*(1-t)*t*t*m+t**3*r,i=(1-t)**3*n+3*(1-t)**2*t*p+3*(1-t)*t*t*u+t**3*l;this.ctx.font="18px sans-serif";const a=8,h=this.ctx.measureText(e.label).width+2*a,v=20;this.ctx.fillStyle="#222",this.ctx.beginPath(),c.drawRoundRect(this.ctx,s-h/2,i-v/2-2,h,v,4),this.ctx.fill(),this.ctx.fillStyle="#ccc",this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(e.label,s,i-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};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)),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=s,x=i;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=i-l;break;case"bottom":x=i+l;break;case"left":v=s-l;break;case"right":v=s+l}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,l=n/r,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}}export{p as I,d as O,u as R};
2
- //# sourceMappingURL=renderer-NPxavnke.js.map