json-canvas-viewer 4.0.0 → 4.1.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.
- package/dist/index.d.ts +18 -8
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kernel/BaseModule.js +2 -0
- package/dist/kernel/BaseModule.js.map +1 -0
- package/dist/kernel/Controller.js +2 -0
- package/dist/kernel/Controller.js.map +1 -0
- package/dist/kernel/DataManager.js +2 -0
- package/dist/kernel/DataManager.js.map +1 -0
- package/dist/kernel/InteractionHandler.js +2 -0
- package/dist/kernel/InteractionHandler.js.map +1 -0
- package/dist/kernel/OverlayManager.js +2 -0
- package/dist/kernel/OverlayManager.js.map +1 -0
- package/dist/kernel/Renderer.js +2 -0
- package/dist/kernel/Renderer.js.map +1 -0
- package/dist/kernel/StyleManager.js +2 -0
- package/dist/kernel/StyleManager.js.map +1 -0
- package/dist/kernel/index.js +2 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/kernel/styles.scss.js +2 -0
- package/dist/kernel/styles.scss.js.map +1 -0
- package/dist/kernel/utilities.js +2 -0
- package/dist/kernel/utilities.js.map +1 -0
- package/dist/modules/Controls/index.js +2 -0
- package/dist/modules/Controls/index.js.map +1 -0
- package/dist/modules/Controls/styles.scss.js +2 -0
- package/dist/modules/Controls/styles.scss.js.map +1 -0
- package/dist/modules/DebugPanel/index.js +2 -0
- package/dist/modules/DebugPanel/index.js.map +1 -0
- package/dist/modules/DebugPanel/styles.scss.js +2 -0
- package/dist/modules/DebugPanel/styles.scss.js.map +1 -0
- package/dist/modules/Minimap/index.js +2 -0
- package/dist/modules/Minimap/index.js.map +1 -0
- package/dist/modules/Minimap/styles.scss.js +2 -0
- package/dist/modules/Minimap/styles.scss.js.map +1 -0
- package/dist/modules/MistouchPreventer/index.js +2 -0
- package/dist/modules/MistouchPreventer/index.js.map +1 -0
- package/dist/modules/MistouchPreventer/styles.scss.js +2 -0
- package/dist/modules/MistouchPreventer/styles.scss.js.map +1 -0
- package/dist/utilities/fetchCanvas.js +2 -0
- package/dist/utilities/fetchCanvas.js.map +1 -0
- package/dist/utilities/parser.js +2 -0
- package/dist/utilities/parser.js.map +1 -0
- package/dist/utilities/renderToString.js +2 -0
- package/dist/utilities/renderToString.js.map +1 -0
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -126,7 +126,7 @@ interface Augmentation$1 {
|
|
|
126
126
|
onRefresh: Controller["onRefresh"];
|
|
127
127
|
onResize: Controller["onResize"];
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
declare class Controller extends BaseModule<BaseOptions, Augmentation$1> {
|
|
130
130
|
private animationId;
|
|
131
131
|
private resizeAnimationId;
|
|
132
132
|
private DM;
|
|
@@ -175,7 +175,7 @@ interface EdgeItem {
|
|
|
175
175
|
}
|
|
176
176
|
type NodeMap = Record<string, NodeItem>;
|
|
177
177
|
type EdgeMap = Record<string, EdgeItem>;
|
|
178
|
-
|
|
178
|
+
declare class DataManager extends BaseModule<Options$1, Augmentation$2> {
|
|
179
179
|
onToggleFullscreen: Hook<[
|
|
180
180
|
"enter" | "exit"
|
|
181
181
|
], false>;
|
|
@@ -223,7 +223,7 @@ interface Augmentation$3 {
|
|
|
223
223
|
zoom: InteractionHandler["zoom"];
|
|
224
224
|
zoomToScale: InteractionHandler["zoomToScale"];
|
|
225
225
|
}
|
|
226
|
-
|
|
226
|
+
declare class InteractionHandler extends BaseModule<Options$2, Augmentation$3> {
|
|
227
227
|
pointeract: PointeractInterface<LoadedModules>;
|
|
228
228
|
private DM;
|
|
229
229
|
onClick: Hook<[
|
|
@@ -267,7 +267,7 @@ type ComponentNodeMap = {
|
|
|
267
267
|
type ComponentDict = {
|
|
268
268
|
[K in keyof ComponentNodeMap]: NodeComponentHook<ComponentNodeMap[K]>;
|
|
269
269
|
};
|
|
270
|
-
|
|
270
|
+
declare class OverlayManager extends BaseModule<Options$3, Augmentation$4> {
|
|
271
271
|
private _overlaysLayer;
|
|
272
272
|
private overlays;
|
|
273
273
|
private selectedId;
|
|
@@ -304,7 +304,7 @@ export declare class OverlayManager extends BaseModule<Options$3, Augmentation$4
|
|
|
304
304
|
interface Options$4 extends BaseOptions {
|
|
305
305
|
zoomInOptimization?: boolean;
|
|
306
306
|
}
|
|
307
|
-
|
|
307
|
+
declare class Renderer extends BaseModule<Options$4> {
|
|
308
308
|
private _canvas;
|
|
309
309
|
private ctx;
|
|
310
310
|
private DM;
|
|
@@ -351,7 +351,7 @@ interface Augmentation$5 {
|
|
|
351
351
|
changeTheme: StyleManager["changeTheme"];
|
|
352
352
|
onChangeTheme: StyleManager["onChangeTheme"];
|
|
353
353
|
}
|
|
354
|
-
|
|
354
|
+
declare class StyleManager extends BaseModule<Options$5, Augmentation$5> {
|
|
355
355
|
theme: "dark" | "light";
|
|
356
356
|
onChangeTheme: Hook<[
|
|
357
357
|
"light" | "dark"
|
|
@@ -596,14 +596,24 @@ export declare class MistouchPreventer extends BaseModule<Options$8, Augmentatio
|
|
|
596
596
|
endPrevention: () => void;
|
|
597
597
|
private dispose;
|
|
598
598
|
}
|
|
599
|
-
|
|
600
|
-
|
|
599
|
+
declare function _default$3(path: `${string}.canvas` | `${string}.json`): Promise<JSONCanvas>;
|
|
600
|
+
declare function _default$4(markdown: string): Promise<string>;
|
|
601
|
+
export declare const internal: {
|
|
602
|
+
Controller: typeof Controller;
|
|
603
|
+
DataManager: typeof DataManager;
|
|
604
|
+
InteractionHandler: typeof InteractionHandler;
|
|
605
|
+
OverlayManager: typeof OverlayManager;
|
|
606
|
+
Renderer: typeof Renderer;
|
|
607
|
+
StyleManager: typeof StyleManager;
|
|
608
|
+
};
|
|
601
609
|
|
|
602
610
|
export {
|
|
603
611
|
AllOptions as Options,
|
|
604
612
|
_default as canvasUtils,
|
|
605
613
|
_default$1 as JSONCanvasViewer,
|
|
606
614
|
_default$2 as renderToString,
|
|
615
|
+
_default$3 as fetchCanvas,
|
|
616
|
+
_default$4 as parser,
|
|
607
617
|
};
|
|
608
618
|
|
|
609
619
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{toHslString as t,rgbToHsl as e,parseRgb as i,parseHex as n,parseHsl as s}from"@ahmedsemih/color-fns";import{dragPreset as o,zoomPreset as a,panPreset as r,Pointeract as l,Click as h,Drag as c,WheelPanZoom as d,PreventDefault as p,MultitouchPanZoom as m,Lubricator as u}from"pointeract";import{Container as v}from"@needle-di/core";import C from"dompurify";import{marked as g}from"marked";class f{constructor(t,e,i,n,s,o){this.container=t,this.augment=o,this.options=e,this.onStart=i.subscribe,this.onDispose=n.subscribe,this.onRestart=s.subscribe}onStart;onRestart;onDispose;options}const w={round:function(t,e){const i=10**e;return Math.round(t*i)/i},resizeCanvasForDPR:function(t,e,i){const n=window.devicePixelRatio??1,s=t.getContext("2d");if(!s)throw new Error("[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.");t.width=Math.round(e*n),t.height=Math.round(i*n),s.setTransform(1,0,0,1,0,0),s.scale(n,n)},applyStyles:function(t,e){const i=document.createElement("style");i.innerHTML=e,t.appendChild(i)},drawRoundRect:function(t,e,i,n,s,o){t.beginPath(),t.moveTo(e+o,i),t.lineTo(e+n-o,i),t.quadraticCurveTo(e+n,i,e+n,i+o),t.lineTo(e+n,i+s-o),t.quadraticCurveTo(e+n,i+s,e+n-o,i+s),t.lineTo(e+o,i+s),t.quadraticCurveTo(e,i+s,e,i+s-o),t.lineTo(e,i+o),t.quadraticCurveTo(e,i,e+o,i),t.closePath()},getAnchorCoord:function(t,e){const i=t.x+t.width/2,n=t.y+t.height/2;switch(e){case"top":return{x:i,y:t.y};case"bottom":return{x:i,y:t.y+t.height};case"left":return{x:t.x,y:n};case"right":return{x:t.x+t.width,y:n};default:return{x:i,y:n}}},makeHook:function(t=!1,e=!1){const i=e?async(...e)=>{if(t){const t=Array.from(i.subs).reverse();for(const i of t)await i(...e)}else for(const t of i.subs)await t(...e)}:(...e)=>{if(t){const t=Array.from(i.subs).reverse();for(const i of t)i(...e)}else for(const t of i.subs)t(...e)};return i.subs=/* @__PURE__ */new Set,i.subscribe=t=>{i.subs.add(t)},i.unsubscribe=t=>{i.subs.delete(t)},i}},V=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");class x extends f{onToggleFullscreen=w.makeHook();data={canvasData:{nodes:[],edges:[]},nodeMap:{},edgeMap:{},canvasBaseDir:"./",nodeBounds:{maxX:0,maxY:0,minX:0,minY:0,width:0,height:0,centerX:0,centerY:0},offsetX:0,offsetY:0,scale:1,container:document.createElement("div")};constructor(...t){super(...t);const e=this.options.container;for(;e.firstElementChild;)e.firstElementChild.remove();e.innerHTML="";const i=this.options.shadowed?e.attachShadow({mode:"open"}):e;w.applyStyles(i,".JSON-Canvas-Viewer{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:var(--text);fill:var(--text);stroke:var(--text);background-color:var(--background);position:relative;width:100%;height:100%;overflow:hidden}.JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-full,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{top:0;left:0;width:100%;height:100%;position:absolute}.JSON-Canvas-Viewer .JCV-flex-center,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{display:flex;justify-content:center;align-items:center}.JSON-Canvas-Viewer .JCV-border-shadow-bg{background:var(--background-secondary);border:1px solid var(--border)!important;box-shadow:var(--shadow)}.JSON-Canvas-Viewer .JCV-button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);background-color:var(--background-secondary);text-align:center;width:32px;padding:5px 0}.JSON-Canvas-Viewer .JCV-button svg{width:100%;height:100%}.JSON-Canvas-Viewer .JCV-button:hover{background-color:var(--border)}.JSON-Canvas-Viewer .JCV-button.JCV-collapse-button{border-radius:8px;transition:transform .2s,background-color .2s}.JSON-Canvas-Viewer .JCV-collapsed .JCV-collapse-button{transform:rotate(180deg)}.JSON-Canvas-Viewer .JCV-main-canvas{width:100%;height:100%;transform-origin:top left}.JSON-Canvas-Viewer .JCV-overlays{position:absolute;transform-origin:top left;will-change:transform}.JSON-Canvas-Viewer .JCV-overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto;background-color:var(--overlay-card);transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;color:var(--overlay-border);top:0;left:0;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{overflow:hidden}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{position:absolute;padding:0 7px}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content.rtl{direction:rtl;text-align:right}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active{-webkit-user-select:auto;user-select:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-overlay-border{border:4px solid var(--overlay-active)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video{border:none;background:transparent}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer{background:transparent;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-click-layer{pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-img{width:100%;height:100%;object-fit:cover;pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-img{pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.JSON-Canvas-Viewer .JCV-overlay-container .JCV-parsed-content-wrapper{padding:10px}}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-parsed-content-wrapper{overflow:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar{width:4px}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-track{background-color:transparent}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}.JSON-Canvas-Viewer .JCV-markdown-content p{font-size:16px;line-height:21px}.JSON-Canvas-Viewer .JCV-markdown-content img{width:100%;border-radius:8px}.JSON-Canvas-Viewer .JCV-markdown-content h1{font-size:25px}.JSON-Canvas-Viewer .JCV-markdown-content h2{font-size:23px}.JSON-Canvas-Viewer .JCV-markdown-content h3{font-size:22px}.JSON-Canvas-Viewer .JCV-markdown-content h4{font-size:20px}.JSON-Canvas-Viewer .JCV-markdown-content h5{font-size:19px}.JSON-Canvas-Viewer .JCV-markdown-content h6{font-size:17px}.JSON-Canvas-Viewer .JCV-markdown-content p,.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2,.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4,.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6,.JSON-Canvas-Viewer .JCV-markdown-content ol,.JSON-Canvas-Viewer .JCV-markdown-content ul{margin:0}.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2{font-weight:800}.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4{font-weight:700}.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6{font-weight:600}.JSON-Canvas-Viewer .JCV-markdown-content code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre .JSON-Canvas-Viewer .JCV-markdown-content code{display:block;box-sizing:border-box;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content pre:has(code),.JSON-Canvas-Viewer .JCV-markdown-content table{margin:6px 0}.JSON-Canvas-Viewer .JCV-markdown-content strong{color:#fe8e7c}.JSON-Canvas-Viewer .JCV-markdown-content em{color:#5affb2}.JSON-Canvas-Viewer .JCV-markdown-content a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}.JSON-Canvas-Viewer .JCV-markdown-content a:hover{color:#86d3fd}.JSON-Canvas-Viewer .JCV-markdown-content hr{height:1px;width:100%;background-color:#fff3;border:none}.JSON-Canvas-Viewer .JCV-markdown-content li{margin:5px 0}.JSON-Canvas-Viewer .JCV-markdown-content ul{padding-left:16px}.JSON-Canvas-Viewer .JCV-markdown-content ol{padding-left:15px;padding-right:7.5px}.JSON-Canvas-Viewer .JCV-markdown-content table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content table th,.JSON-Canvas-Viewer .JCV-markdown-content table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}.JSON-Canvas-Viewer .JCV-markdown-content table th{background:#ffffff1f;font-weight:700}"+this.options.extraCSS),this.data.container.classList.add("JSON-Canvas-Viewer"),i.appendChild(this.data.container),this.augment({resetView:this.resetView,toggleFullscreen:this.toggleFullscreen,onToggleFullscreen:this.onToggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{const t=Object.assign({nodes:[],edges:[]},this.options.canvas);Object.assign(this.data,{canvasData:t,nodeMap:{},edgeMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(t),offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(t=>{const e={ref:t,box:this.getNodeBox(t)};if(this.data.nodeMap[t.id]=e,"file"===t.type){const i=t.file.split("/").pop()??"";if(e.fileName=i,!t.file.startsWith("http://")&&!t.file.startsWith("https://")){const e=this.options.attachments?.[i];e?t.file=e:this.options.noAttachmentRelocation||(t.file=this.data.canvasBaseDir+i)}}}),this.data.canvasData.edges.forEach(t=>{this.data.edgeMap[t.id]={ref:t,box:this.getEdgeBox(t)}}),this.resetView()};processBaseDir=t=>{if(!t)return"./";const e=t?.slice(-1);return"/"===e?t:`${t}/`};getNodeBox=t=>({left:t.x,top:"file"===t.type||"group"===t.type?t.y-40:t.y,right:t.width+t.x,bottom:t.y+t.height});getEdgeBox=t=>{const e=this.data.nodeMap,i=e[t.fromNode].ref,n=e[t.toNode].ref,s=w.getAnchorCoord(i,t.fromSide),o=w.getAnchorCoord(n,t.toSide),a=Math.min(s.x,o.x),r=Math.min(s.y,o.y),l=Math.max(s.x,o.x),h=Math.max(s.y,o.y),c=l-a,d=h-r,p=Math.min(c,d),m=0===p?1:p,u=Math.max(c,d),v=10*Math.log2(u/m);return{left:a-v,top:r-v,right:l+v,bottom:h+v}};calculateNodeBounds(t){let e=1/0,i=1/0,n=-1/0,s=-1/0;t.nodes.forEach(t=>{e=Math.min(e,t.x),i=Math.min(i,t.y),n=Math.max(n,t.x+t.width),s=Math.max(s,t.y+t.height)});const o=n-e,a=s-i;return{minX:e,minY:i,maxX:n,maxY:s,width:o,height:a,centerX:e+o/2,centerY:i+a/2}}toggleFullscreen=async t=>{document.fullscreenElement||t&&"enter"!==t?!document.fullscreenElement||t&&"exit"!==t||(await document.exitFullscreen(),this.onToggleFullscreen("exit")):(await this.data.container.requestFullscreen(),this.onToggleFullscreen("enter"))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const i=t.width+200,n=t.height+200,s=e.clientWidth,o=e.clientHeight,a=s/i,r=o/n,l=Math.round(1e3*Math.min(a,r))/1e3,h={scale:l,offsetX:s/2-t.centerX*l,offsetY:o/2-t.centerY*l};this.data.offsetX=h.offsetX,this.data.offsetY=h.offsetY,this.data.scale=h.scale};middleViewer=()=>{const t=this.data.container;return{x:t.clientWidth/2,y:t.clientHeight/2,width:t.clientWidth,height:t.clientHeight}};dispose=()=>{this.data.container.remove()}}class b extends f{theme="light";onChangeTheme=w.makeHook();definedColors={light:{0:{hue:0,saturation:0,lightness:72},1:{hue:358,saturation:81,lightness:55},2:{hue:19,saturation:87,lightness:58},3:{hue:41,saturation:79,lightness:52},4:{hue:150,saturation:100,lightness:37},5:{hue:221,saturation:100,lightness:59},6:{hue:257,saturation:81,lightness:62}},dark:{0:{hue:0,saturation:0,lightness:40},1:{hue:358,saturation:100,lightness:65},2:{hue:23,saturation:86,lightness:63},3:{hue:39,saturation:91,lightness:70},4:{hue:153,saturation:80,lightness:45},5:{hue:217,saturation:100,lightness:62},6:{hue:259,saturation:100,lightness:75}}};namedColors={light:{dots:"hsla(0, 0%, 72%, 0.4)",text:"rgb(30, 30, 30)",background:"rgb(250, 250, 250)","background-secondary":"rgb(255, 255, 255)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.1)",border:"hsla(0, 0%, 82%, 0.7)"},dark:{dots:"hsla(0, 0%, 40%, 0.3)",text:"rgb(242, 242, 242)",background:"rgb(30, 30, 30)","background-secondary":"rgb(37, 37, 40)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.2)",border:"hsla(0, 0%, 30%, 0.7)"}};colorCache={dark:{},light:{}};constructor(...t){super(...t);const e=this.options.colors;if(e){["light","dark"].forEach(t=>{if(!(t in e))return;const i=e[t];i&&Object.entries(i).forEach(([e,i])=>{if(!i)return;const n=this.namedColors[t],s=this.definedColors[t];if(e in n)n[e]=i;else if(e in s){const t=this.parseColor(i);if(!t)return void console.warn(`[JSON Canvas Viewer] Color ${i} unsupported.`);s[e]=t}})})}this.changeTheme(this.options.theme??"light"),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=e=>{const{hue:i,saturation:n,lightness:s}=e;let o;return o="dark"===this.theme?{active:e,card:{hue:i,saturation:n/3,lightness:s/3},border:{...e,alpha:.7},background:{...e,alpha:.1},text:e.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"}:{active:e,card:0===i?{hue:i,saturation:n,lightness:100}:{hue:i,saturation:.4*n,lightness:90},border:{...e,alpha:.7},background:{...e,alpha:.1},text:e.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"},{active:t(o.active),card:t(o.card),border:t(o.border),background:t(o.background),text:o.text}};parseColor=t=>t.startsWith("rgb")?e(i(t)):t.startsWith("#")?e(n(t)):t.startsWith("hsl")?s(t):void 0;getColor=(t="0")=>{const i=this.theme;let s;return this.colorCache[i][t]?this.colorCache[i][t]:(s=t in this.definedColors[i]?this.hslProcessor(this.definedColors[i][t]):this.hslProcessor(e(n(t))),this.colorCache[i][t]=s,s)};getNamedColor=t=>this.namedColors[this.theme][t];changeTheme=t=>{this.theme=t||("dark"===this.theme?"light":"dark");const e=this.container.get(x).data.container;Object.entries(this.namedColors[this.theme]).forEach(([t,i])=>{e.style.setProperty(`--${t}`,i)}),this.onChangeTheme(this.theme)}}class J extends f{animationId=null;resizeAnimationId=null;DM;SM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};onResize=w.makeHook();onRefresh=w.makeHook();constructor(...t){super(...t),this.DM=this.container.get(x),this.SM=this.container.get(b),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({refresh:this.refresh,onRefresh:this.onRefresh,onResize:this.onResize}),this.onStart(this.start),this.onRestart(this.refresh),this.onDispose(this.dispose)}start=()=>{this.resizeObserver.observe(this.DM.data.container),this.animationId=requestAnimationFrame(this.draw)};draw=()=>{this.perFrame.lastScale===this.DM.data.scale&&this.perFrame.lastOffsets.x===this.DM.data.offsetX&&this.perFrame.lastOffsets.y===this.DM.data.offsetY||this.refresh(),this.animationId=requestAnimationFrame(this.draw)};refresh=()=>{this.perFrame={lastScale:this.DM.data.scale,lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY}},this.onRefresh()};onResizeCallback=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const t=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+t.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+t.y-this.lastResizeCenter.y),this.lastResizeCenter.x=t.x,this.lastResizeCenter.y=t.y,this.onResize(t.width,t.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}const M={markdown:/\.(md|mdx|markdown|txt)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},y=["markdown","image","audio","video"];class S extends f{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;aborted=!1;eventListeners={};DM;SM;parse;componentDict={text:(t,e)=>{t.classList.add("JCV-markdown-content");const i=document.createElement("div");i.innerHTML=e,i.classList.add("JCV-parsed-content-wrapper"),t.appendChild(i)},markdown:async(t,e)=>{t.classList.add("JCV-markdown-content");const i=document.createElement("div");let n;i.textContent="Loading...",i.classList.add("JCV-parsed-content-wrapper"),t.appendChild(i);try{const t=await fetch(e),i=await t.text(),s=i.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);n=s?await this.parse(s[2]):await this.parse(i)}catch(s){console.error("[JSON Canvas Viewer] Failed to load markdown:",s),n="Failed to load content."}i.innerHTML=n},link:(t,e)=>{const i=document.createElement("iframe");i.src=e,i.sandbox="allow-scripts allow-same-origin",i.className="JCV-link-iframe",i.loading="lazy",t.appendChild(i)},audio:(t,e)=>{const i=document.createElement("audio");i.className="JCV-audio",i.src=e,i.controls=!0,t.appendChild(i)},image:(t,e)=>{const i=document.createElement("img");i.className="JCV-img",i.src=e,i.loading="lazy",t.appendChild(i)},video:(t,e)=>{const i=document.createElement("video");i.className="JCV-video",i.src=e,i.controls=!0,t.appendChild(i)}};get overlaysLayer(){if(!this._overlaysLayer)throw V;return this._overlaysLayer}onInteractionStart=w.makeHook();onInteractionEnd=w.makeHook();onNodeActive=w.makeHook();onNodeLosesActive=w.makeHook();constructor(...t){super(...t),this.parse=this.options.parser||(t=>t),this.DM=this.container.get(x),this.SM=this.container.get(b);this.container.get(J).onRefresh.subscribe(this.updateOverlays),this.SM.onChangeTheme.subscribe(this.themeChanged),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="JCV-overlays",this._overlaysLayer.id="overlays",this.DM.data.container.appendChild(this.overlaysLayer);const e=this.options.nodeComponents;e&&Object.assign(this.componentDict,e),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(k).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{const t=async t=>{switch(t.type){case"text":this.createOverlay(t,await this.parse(t.text),"text");break;case"file":for(const e of y)if(t.file.match(M[e])){this.createOverlay(t,t.file,e);break}break;case"link":this.createOverlay(t,t.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(async e=>{await t(e.ref)})};themeChanged=()=>{Object.values(this.overlays).forEach(t=>{const e=this.DM.data.nodeMap[t.id].ref,i=this.SM.getColor(e.color);this.setOverlayColor(t,i)})};select=t=>{const e=this.selectedId,i=e?this.overlays[e]:null,n=t?this.overlays[t]:null;if(i&&e){i.classList.remove("JCV-active");const t=this.DM.data.nodeMap[e];this.onNodeLosesActive(t.ref),t.onLoseActive?.()}if(n&&t){n.classList.add("JCV-active"),this.onInteractionStart();const e=this.DM.data.nodeMap[t];this.onNodeActive(e.ref),e.onActive?.()}else this.onInteractionEnd();this.selectedId=t};updateOverlays=()=>{const t=this.DM.data;this.overlaysLayer.style.transform=`translate(${t.offsetX}px, ${t.offsetY}px) scale(${t.scale})`};createOverlay=(...t)=>{if(this.aborted)return;const e=t[0];let i=this.overlays[e.id];if(!i){if(i=this.constructOverlay(...t),this.aborted)return;this.overlaysLayer.appendChild(i),this.overlays[e.id]=i,i.style.left=`${e.x}px`,i.style.top=`${e.y}px`,i.style.width=`${e.width}px`,i.style.height=`${e.height}px`}};constructOverlay=(...t)=>{const e=t[0],i=document.createElement("div");i.classList.add("JCV-overlay-container"),i.id=e.id,this.setOverlayColor(i,this.SM.getColor(e.color));const n=document.createElement("div");n.classList.add("JCV-content"),i.appendChild(n);const s=document.createElement("div");s.className="JCV-click-layer",i.appendChild(s);const o=document.createElement("div");o.className="JCV-overlay-border",i.appendChild(o);const a=this.DM.data.nodeMap[e.id];a.onActive=w.makeHook(),a.onLoseActive=w.makeHook(),a.onBeforeUnmount=w.makeHook(),this.componentDict[t[2]](n,t[1],t[0],a.onBeforeUnmount,a.onActive,a.onLoseActive);const r=()=>{e.id===this.selectedId&&this.onInteractionStart()},l=()=>{e.id===this.selectedId&&this.onInteractionEnd()};return i.addEventListener("pointerenter",r),i.addEventListener("pointerleave",l),i.addEventListener("touchstart",r),i.addEventListener("touchend",l),this.eventListeners[e.id]=[r,l],i};setOverlayColor=(t,e)=>{Object.entries(e).forEach(([e,i])=>{t.style.setProperty(`--overlay-${e}`,i)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([t,e])=>{if(this.DM.data.nodeMap[t].onBeforeUnmount?.(),this.eventListeners[t]){const i=this.eventListeners[t][0],n=this.eventListeners[t][1];if(!i||!n)throw V;e.removeEventListener("pointerenter",i),e.removeEventListener("pointerleave",n),e.removeEventListener("touchstart",i),e.removeEventListener("touchend",n),this.eventListeners[t][0]=null,this.eventListeners[t][1]=null}e.remove(),delete this.overlays[t]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=null}}class k extends f{pointeract;DM;onClick=w.makeHook();constructor(...t){super(...t),this.DM=this.container.get(x);const e=Object.assign(this.options.pointeract??{},{coordinateOutput:"relative",element:this.DM.data.container,lubricator:{pan:r,zoom:a,drag:o}});this.pointeract=new l(e,[h,c,d,p,m,u]);const i=this.container.get(S);i.onInteractionStart.subscribe(this.stopInteract),i.onInteractionEnd.subscribe(this.startInteract),this.augment({pan:this.pan,panToCoords:this.panToCoords,zoom:this.zoom,zoomToScale:this.zoomToScale}),this.onStart(this.start),this.onDispose(this.dispose)}start=()=>{this.pointeract.on("pan",this.onPan).on("drag",this.onPan).on("zoom",this.onZoom).on("trueClick",this.onTrueClick).start()};startInteract=()=>{this.pointeract.start()};stopInteract=()=>{this.pointeract.stop()};onPan=t=>{this.truePan({x:t.deltaX,y:t.deltaY})};onZoom=t=>{this.trueZoom(t.factor,t)};trueZoom=(t,e)=>{const i=Math.max(Math.min(this.DM.data.scale*t,20),.05);if(i===this.DM.data.scale)return;const n=i/this.DM.data.scale,s=this.C2C(e);this.DM.data.offsetX=e.x-s.x*n,this.DM.data.offsetY=e.y-s.y*n,this.DM.data.scale=i};truePan=({x:t,y:e})=>{this.DM.data.offsetX=this.DM.data.offsetX+t,this.DM.data.offsetY=this.DM.data.offsetY+e};zoom=(t,e)=>{this.pointeract.dispatch("zoom",{factor:t,...e})};pan=({x:t,y:e})=>{this.pointeract.dispatch("pan",{deltaX:t,deltaY:e})};zoomToScale=(t,e)=>{const i=t/this.DM.data.scale;this.pointeract.dispatch("zoom",{factor:i,...e})};panToCoords=({x:t,y:e})=>{this.pointeract.dispatch("pan",{deltaX:t-this.DM.data.offsetX,deltaY:e-this.DM.data.offsetY})};C2C=({x:t,y:e})=>({x:t-this.DM.data.offsetX,y:e-this.DM.data.offsetY});onTrueClick=t=>{const e=t.target;if(this.isUIControl(e))return;const i=this.findNodeId(e);this.onClick(i)};isUIControl=t=>!!t&&(t.closest(".controls")||t.closest("button")||t.closest("input"));findNodeId=t=>{if(!t)return null;let e=t;for(;(!e.id||""===e.id)&&e.parentElement;)e=e.parentElement;return"overlays"!==e.id&&e.id&&""!==e.id?e.id:null};dispose=()=>this.pointeract.dispose()}class O extends f{_canvas;ctx;DM;SM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(!this._canvas)throw V;return this._canvas}constructor(...t){super(...t);const e=this.container.get(J);this.SM=this.container.get(b),e.onRefresh.subscribe(this.redraw),e.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(x),this._canvas=document.createElement("canvas"),this._canvas.className="JCV-main-canvas",this.ctx=this._canvas.getContext("2d"),this.DM.data.container.appendChild(this._canvas),this.onDispose(this.dispose)}optimizeDPR=()=>{const t=this.DM.data.container;w.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{const t=this.DM.data.offsetX,e=this.DM.data.offsetY,i=this.DM.data.scale,n=this.getCurrentViewport(t,e,i);if(!this.options.zoomInOptimization)return void this.trueRedraw(t,e,i,n);this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const s=Date.now();if(this.isInside(n,this.zoomInOptimize.lastDrawnViewport)&&i!==this.zoomInOptimize.lastDrawnScale){if(s-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(t,e,i,n),this.zoomInOptimize.lastCallTime=s,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(n,i)}this.zoomInOptimize.lastCallTime=s,this.trueRedraw(t,e,i,n)};trueRedraw(t,e,i,n){this.zoomInOptimize.lastDrawnViewport=n,this.zoomInOptimize.lastDrawnScale=i,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.drawGridDots(i,t,e),this.ctx.translate(t,e),this.ctx.scale(i,i),Object.values(this.DM.data.nodeMap).forEach(t=>{if(this.isOutside(t.box,n))return;const e=t.ref;"file"===e.type?this.drawFile(t):"group"===e.type&&this.drawGroup(e,i)}),Object.values(this.DM.data.edgeMap).forEach(t=>{this.isOutside(t.box,n)||this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,e){const i=e/this.zoomInOptimize.lastDrawnScale,n=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*e,s=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*e;this.canvas.style.transform=`translate(${n}px, ${s}px) scale(${i})`}isInside=(t,e)=>t.left>e.left&&t.top>e.top&&t.right<e.right&&t.bottom<e.bottom;isOutside=(t,e)=>t.right<e.left||t.bottom<e.top||t.left>e.right||t.top>e.bottom;getCurrentViewport=(t,e,i)=>{const n=-t/i,s=-e/i,o=this.DM.data.container;return{left:n,top:s,right:n+o.clientWidth/i,bottom:s+o.clientHeight/i}};drawLabelBar=(t,e,i,n,s,o)=>{const a=30*o,r=6*o,l=8*o,h=16*o,c=6*o;this.ctx.save(),this.ctx.translate(t,e),this.ctx.scale(1/o,1/o),this.ctx.font=`${h}px 'Inter', sans-serif`;const d=this.ctx.measureText(i).width+2*c;this.ctx.translate(0,-a-l),this.ctx.fillStyle=n,this.ctx.beginPath(),this.ctx.moveTo(r,0),this.ctx.lineTo(d-r,0),this.ctx.quadraticCurveTo(d,0,d,r),this.ctx.lineTo(d,a-r),this.ctx.quadraticCurveTo(d,a,d-r,a),this.ctx.lineTo(r,a),this.ctx.quadraticCurveTo(0,a,0,a-r),this.ctx.lineTo(0,r),this.ctx.quadraticCurveTo(0,0,r,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=s,this.ctx.fillText(i,c,.65*a),this.ctx.restore()};drawNodeBackground=t=>{const e=this.SM.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=e.background,w.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=e.border,this.ctx.lineWidth=2,w.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,e)=>{if(this.drawNodeBackground(t),t.label){const i=this.SM.getColor(t.color);this.drawLabelBar(t.x,t.y,t.label,i.active,i.text,e)}};drawFile=t=>{this.ctx.fillStyle=this.SM.getColor().text;const e=t.ref;this.ctx.font="16px sans-serif",this.ctx.fillText(t.fileName??"",e.x+5,e.y-10)};drawEdge=t=>{const e=t.ref,i=this.DM.data.nodeMap[e.fromNode].ref,n=this.DM.data.nodeMap[e.toNode].ref,s=w.getAnchorCoord,{x:o,y:a}=s(i,e.fromSide),{x:r,y:l}=s(n,e.toSide),h=this.SM.getColor(e.color);let[c,d,p,m]=[0,0,0,0];if(t.controlPoints?[c,d,p,m]=t.controlPoints:([c,d,p,m]=this.getControlPoints(o,a,r,l,e.fromSide,e.toSide),t.controlPoints=[c,d,p,m]),this.drawCurvedPath(o,a,r,l,c,d,p,m,h.active),this.drawArrowhead(r,l,p,m,h.active),e.label){const t=.5,i=(1-t)**3*o+3*(1-t)**2*t*c+3*(1-t)*t*t*p+t**3*r,n=(1-t)**3*a+3*(1-t)**2*t*d+3*(1-t)*t*t*m+t**3*l;this.ctx.font="18px sans-serif";const s=8,u=this.ctx.measureText(e.label).width+2*s,v=20;this.ctx.fillStyle=h.active,this.ctx.beginPath(),w.drawRoundRect(this.ctx,i-u/2,n-v/2-2,u,v,4),this.ctx.fill(),this.ctx.fillStyle=h.text,this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(e.label,i,n-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getControlPoints=(t,e,i,n,s,o)=>{const a=i-t,r=n-e,l=Math.min(Math.abs(a),Math.abs(r))+.3*Math.max(Math.abs(a),Math.abs(r)),h=(c=.5*l,d=60,p=300,Math.max(d,Math.min(p,c)));var c,d,p;let m=t,u=e,v=i,C=n;switch(s){case"top":u=e-h;break;case"bottom":u=e+h;break;case"left":m=t-h;break;case"right":m=t+h}switch(o){case"top":C=n-h;break;case"bottom":C=n+h;break;case"left":v=i-h;break;case"right":v=i+h}return[m,u,v,C]};drawGridDots=(t,e,i)=>{const n=10*2**-Math.floor(Math.log2(t))*t,s=this.canvas.width,o=this.canvas.height,a=e%n,r=i%n;this.ctx.fillStyle=this.SM.getNamedColor("dots");for(let l=a;l<=s;l+=n)for(let t=r;t<=o;t+=n)this.ctx.beginPath(),this.ctx.arc(l,t,1,0,2*Math.PI),this.ctx.fill()};drawCurvedPath=(t,e,i,n,s,o,a,r,l)=>{this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.bezierCurveTo(s,o,a,r,i,n),this.ctx.strokeStyle=l,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,e,i,n,s)=>{const o=t-i,a=e-n,r=Math.sqrt(o*o+a*a);if(0===r)return;const l=o/r,h=a/r,c=t-12*l-4*h,d=e-12*h+4*l,p=t-12*l+4*h,m=e-12*h-4*l;this.ctx.beginPath(),this.ctx.fillStyle=s,this.ctx.moveTo(t,e),this.ctx.lineTo(c,d),this.ctx.lineTo(p,m),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null),this.canvas.remove(),this._canvas=null}}const N=[x,b,J,S,k,O];class z{allModules;IO=null;started=!1;disposed=!1;options;container;onDispose=w.makeHook(!0);onStart=w.makeHook();onRestart=w.makeHook();constructor(t,e){this.container=new v,this.options=t;this.allModules=[...N,...e??[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})}),this.allModules.forEach(t=>{this.container.get(t)});const i=this.options.loading??"normal";"normal"===i?this.load():"lazy"===i&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};augment=t=>{const e=Object.getOwnPropertyDescriptors(t);Object.defineProperties(this,e)};load=t=>{this.disposed||(t&&Object.assign(this.options,t),this.started?this.onRestart():(this.onStart(),this.started=!0))};dispose=()=>{if(!this.started||this.disposed)return;this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.onDispose(),this.container.unbindAll(),this.disposed=!0}}async function _(t){const e=async e=>await async function(t,e){switch(t.type){case"text":return await e(t.text);case"file":return await async function(t,e){if(t.file.match(/\.md$/i))return await async function(t,e){let i;try{const n=await fetch(t),s=await n.text(),o=s.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);i=o?await e(o[2]):await e(s)}catch{i="Failed to load content."}return i}(t.file,e);if(t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i))return`<img src="${t.file}" alt="${t.file.split("/").pop()}">`;if(t.file.match(/\.(mp3|wav)$/i))return`<audio src="${t.file}" controls></audio>`;return""}(t,e);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow">${t.url}</a>`;default:return""}}(e,t.parser??(t=>t)),i=t.canvas.nodes??[],n=t.attachmentDir??"./";i.forEach(e=>{if("file"===e.type&&!e.file.startsWith("http")){const i=e.file.split("/").pop()??"";t.attachments?.[i]?e.file=t.attachments[i]:e.file=n+i}});const s=[];return await Promise.all(i.map(async t=>s.push(await e(t)))),s.join("")}const D='<svg viewBox="-5.28 -5.28 34.56 34.56" fill="none"><path d="M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15" stroke-width="2.4" stroke-linecap="round"/></svg>';class B extends f{_controlsPanel=null;_toggleCollapseBtn=null;_toggleFullscreenBtn=null;_zoomOutBtn=null;_zoomSlider=null;_zoomInBtn=null;_resetViewBtn=null;DM;IH;collapsed;get controlsPanel(){if(null===this._controlsPanel)throw V;return this._controlsPanel}get toggleCollapseBtn(){if(null===this._toggleCollapseBtn)throw V;return this._toggleCollapseBtn}get toggleFullscreenBtn(){if(null===this._toggleFullscreenBtn)throw V;return this._toggleFullscreenBtn}get zoomOutBtn(){if(null===this._zoomOutBtn)throw V;return this._zoomOutBtn}get zoomSlider(){if(null===this._zoomSlider)throw V;return this._zoomSlider}get zoomInBtn(){if(null===this._zoomInBtn)throw V;return this._zoomInBtn}get resetViewBtn(){if(null===this._resetViewBtn)throw V;return this._resetViewBtn}constructor(...t){super(...t),this.collapsed=this.options.controlsCollapsed??!1,this.DM=this.container.get(x),this.IH=this.container.get(k),this.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn),this.container.get(J).onRefresh.subscribe(this.updateSlider),this._controlsPanel=document.createElement("div"),this._controlsPanel.className="JCV-controls",this._controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),w.applyStyles(this._controlsPanel,".JSON-Canvas-Viewer>.JCV-controls{position:absolute;top:10px;right:10px;display:flex;align-items:center;transition:transform .2s;border-radius:8px;gap:10px}.JSON-Canvas-Viewer>.JCV-controls.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-controls .JCV-controls-content{display:flex;gap:1px;align-items:center;border-radius:8px;overflow:hidden;background:var(--border);box-shadow:var(--shadow);outline:1px solid var(--border)}.JSON-Canvas-Viewer>.JCV-controls .JCV-zoom-slider{width:100px;margin:0 10px}"),this._toggleCollapseBtn=document.createElement("button"),this._toggleCollapseBtn.className="JCV-button JCV-collapse-button JCV-border-shadow-bg",this._toggleCollapseBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._controlsPanel.appendChild(this._toggleCollapseBtn);const e=document.createElement("div");e.className="JCV-controls-content",this._toggleFullscreenBtn=document.createElement("button"),this._toggleFullscreenBtn.className="JCV-button",this._toggleFullscreenBtn.innerHTML=D,e.appendChild(this._toggleFullscreenBtn),this._zoomOutBtn=document.createElement("button"),this.zoomOutBtn.className="JCV-button",this._zoomOutBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomOutBtn),this._zoomSlider=document.createElement("input"),this._zoomSlider.type="range",this._zoomSlider.className="JCV-zoom-slider",this._zoomSlider.min="-30",this._zoomSlider.max="30",this._zoomSlider.value="0",e.appendChild(this._zoomSlider),this._zoomInBtn=document.createElement("button"),this._zoomInBtn.className="JCV-button",this._zoomInBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12m-6-6v12" stroke-width="2" stroke-linecap="round" /></svg>',e.appendChild(this._zoomInBtn),this._resetViewBtn=document.createElement("button"),this._resetViewBtn.className="JCV-button",this._resetViewBtn.innerHTML='<svg viewBox="-6 -6 30 30" stroke-width=".08"><path d="m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z" /></svg>',e.appendChild(this._resetViewBtn),this._controlsPanel.appendChild(e),this.DM.data.container.appendChild(this._controlsPanel),this._toggleCollapseBtn.addEventListener("click",this.toggleCollapse),this._zoomInBtn.addEventListener("click",this.zoomIn),this._zoomOutBtn.addEventListener("click",this.zoomOut),this._zoomSlider.addEventListener("input",this.slide),this._resetViewBtn.addEventListener("click",this.DM.resetView),this._toggleFullscreenBtn.addEventListener("click",this.toggleFullscreen),this.augment({toggleControlsCollapse:this.toggleCollapse}),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateSlider()};zoomIn=()=>this.IH.zoom(1.3,this.DM.middleViewer());zoomOut=()=>this.IH.zoom(1/1.3,this.DM.middleViewer());slide=()=>this.IH.trueZoom(1.1**Number(this.zoomSlider.value)/this.DM.data.scale,this.DM.middleViewer());updateFullscreenBtn=t=>{this.toggleFullscreenBtn.innerHTML="enter"===t?'<svg viewBox="-40.32 -40.32 176.64 176.64"><path d="M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z"/></svg>':D};toggleFullscreen=()=>this.DM.toggleFullscreen();updateSlider=()=>{this.collapsed||(this.zoomSlider.value=String(this.scaleToSlider(this.DM.data.scale)))};scaleToSlider=t=>Math.log(t)/Math.log(1.1);dispose=()=>{this.toggleCollapseBtn.removeEventListener("click",this.toggleCollapse),this.zoomInBtn.removeEventListener("click",this.zoomIn),this.zoomOutBtn.removeEventListener("click",this.zoomOut),this.zoomSlider.removeEventListener("input",this.slide),this.resetViewBtn.removeEventListener("click",this.DM.resetView),this.toggleFullscreenBtn.removeEventListener("click",this.toggleFullscreen),this.controlsPanel.remove(),this._controlsPanel=null,this._toggleCollapseBtn=null,this._zoomInBtn=null,this._zoomOutBtn=null,this._zoomSlider=null,this._resetViewBtn=null,this._toggleFullscreenBtn=null}}class E extends f{_debugPanel=null;DM;get debugPanel(){if(!this._debugPanel)throw V;return this._debugPanel}constructor(...t){super(...t),this.DM=this.container.get(x),this.container.get(J).onRefresh.subscribe(this.update),this._debugPanel=document.createElement("div"),this._debugPanel.className="JCV-debug-panel JCV-border-shadow-bg";const e=this.DM.data.container;w.applyStyles(e,".JSON-Canvas-Viewer>.JCV-debug-panel{position:absolute;bottom:12px;left:12px;border-radius:12px;padding:12px;color:var(--text);font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);pointer-events:none}"),e.appendChild(this._debugPanel),this.onDispose(this.dispose)}update=()=>{const t=w.round,e=this.DM.data;this.debugPanel.innerHTML=`<p>Scale: ${t(e.scale,3)}</p><p>Offset: ${t(e.offsetX,1)}, ${t(e.offsetY,1)}</p>`};dispose=()=>{this.debugPanel.remove(),this._debugPanel=null}}class L extends f{_minimapCtx=null;_viewportRectangle=null;_minimap=null;_minimapContainer=null;_toggleMinimapBtn=null;minimapCache={scale:1,centerX:0,centerY:0};DM;SM;collapsed;get minimap(){if(null===this._minimap)throw V;return this._minimap}get minimapCtx(){if(null===this._minimapCtx)throw V;return this._minimapCtx}get viewportRectangle(){if(null===this._viewportRectangle)throw V;return this._viewportRectangle}get minimapContainer(){if(null===this._minimapContainer)throw V;return this._minimapContainer}get toggleMinimapBtn(){if(null===this._toggleMinimapBtn)throw V;return this._toggleMinimapBtn}constructor(...t){super(...t),this.collapsed=this.options.minimapCollapsed??!1,this.container.get(J).onRefresh.subscribe(this.updateViewportRectangle),this.DM=this.container.get(x),this.SM=this.container.get(b),this._minimapContainer=document.createElement("div"),this._minimapContainer.className="JCV-minimap-container",w.applyStyles(this._minimapContainer,".JSON-Canvas-Viewer>.JCV-minimap-container{position:absolute;bottom:10px;right:10px;display:flex;pointer-events:none;transition:transform .2s}.JSON-Canvas-Viewer>.JCV-minimap-container.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-toggle-minimap{margin:auto 10px 0 0;pointer-events:auto}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap{position:relative;pointer-events:none;width:200px;height:150px;overflow:hidden;border-radius:12px;transform-origin:0 0}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-minimap-canvas{width:100%;height:100%}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-viewport-rectangle{position:absolute;top:0;left:0;pointer-events:none;border-radius:6px;box-sizing:border-box;border:2px dashed var(--text)}@container (max-width: 768px){.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap{transform:scale(.6)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px)}.collapsed .JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px) rotate(180deg)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container{transform:translateY(60px) translate(80px)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container.JCV-collapsed{transform:translateY(60px) translate(calc(100% - 32px))}}"),this._toggleMinimapBtn=document.createElement("button"),this._toggleMinimapBtn.className="JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg",this._toggleMinimapBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._minimapContainer.appendChild(this._toggleMinimapBtn),this._minimap=document.createElement("div"),this._minimap.className="JCV-minimap JCV-border-shadow-bg";const e=document.createElement("canvas");e.className="JCV-minimap-canvas",e.width=200,e.height=150,this._minimap.appendChild(e),this._minimapCtx=e.getContext("2d"),this._viewportRectangle=document.createElement("div"),this._viewportRectangle.className="JCV-viewport-rectangle",this._minimap.appendChild(this._viewportRectangle),this._minimapContainer.appendChild(this._minimap),this.DM.data.container.appendChild(this._minimapContainer),this._minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this._toggleMinimapBtn.addEventListener("click",this.toggleCollapse),w.resizeCanvasForDPR(e,e.width,e.height),this.augment({toggleMinimapCollapse:this.toggleCollapse}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateViewportRectangle()};start=()=>{const t=this.DM.data.nodeBounds;if(!t)return;const e=this.minimap.clientWidth,i=this.minimap.clientHeight,n=e/t.width,s=i/t.height;this.minimapCache.scale=.9*Math.min(n,s),this.minimapCache.centerX=e/2,this.minimapCache.centerY=i/2,this.minimapCtx.clearRect(0,0,e,i),this.minimapCtx.save(),this.minimapCtx.translate(this.minimapCache.centerX,this.minimapCache.centerY),this.minimapCtx.scale(this.minimapCache.scale,this.minimapCache.scale),this.minimapCtx.translate(-t.centerX,-t.centerY);const o=this.DM.data.canvasData;for(const a of o.edges)this.drawMinimapEdge(a);for(const a of o.nodes)this.drawMinimapNode(a);this.minimapCtx.restore()};drawMinimapNode=t=>{const e=this.SM.getColor(t.color);this.minimapCtx.fillStyle=e.border,w.drawRoundRect(this.minimapCtx,t.x,t.y,t.width,t.height,25),this.minimapCtx.fill()};drawMinimapEdge=t=>{const e=this.DM.data.nodeMap,i=e[t.fromNode].ref,n=e[t.toNode].ref;if(!i||!n)return;const{x:s,y:o}=w.getAnchorCoord(i,t.fromSide),{x:a,y:r}=w.getAnchorCoord(n,t.toSide);this.minimapCtx.beginPath(),this.minimapCtx.moveTo(s,o),this.minimapCtx.lineTo(a,r),this.minimapCtx.strokeStyle=this.SM.getColor(t.color).active,this.minimapCtx.lineWidth=10,this.minimapCtx.stroke()};updateViewportRectangle=()=>{if(this.collapsed)return;const t=this.DM.data.nodeBounds,e=this.DM.data.container,i=this.DM.data.scale;if(!t)return;const n=e.clientWidth/i,s=e.clientHeight/i,o=-this.DM.data.offsetX/i+e.clientWidth/(2*i),a=-this.DM.data.offsetY/i+e.clientHeight/(2*i),r=this.minimapCache.centerX+(o-n/2-t.centerX)*this.minimapCache.scale,l=this.minimapCache.centerY+(a-s/2-t.centerY)*this.minimapCache.scale,h=n*this.minimapCache.scale,c=s*this.minimapCache.scale;this.viewportRectangle.style.left=`${r}px`,this.viewportRectangle.style.top=`${l}px`,this.viewportRectangle.style.width=`${h}px`,this.viewportRectangle.style.height=`${c}px`};dispose=()=>{this.toggleMinimapBtn.removeEventListener("click",this.toggleCollapse),this.minimapCtx.clearRect(0,0,this.minimap.clientWidth,this.minimap.clientHeight),this.minimapContainer.remove(),this._minimapContainer=null,this._toggleMinimapBtn=null,this._viewportRectangle=null,this._minimap=null}}class T extends f{_preventionContainer=null;preventMt=!1;DM;preventMistouch={record:!1,lastX:0,lastY:0,initialX:0,initialY:0};get preventionContainer(){if(null===this._preventionContainer)throw V;return this._preventionContainer}constructor(...t){super(...t);const e=document.createElement("div");e.className="JCV-prevention-banner JCV-border-shadow-bg",e.textContent=this.options.mistouchPreventerBannerText??"Click on to unlock.",this.DM=this.container.get(x),this._preventionContainer=document.createElement("div"),this._preventionContainer.className="JCV-prevention-container JCV-hidden JCV-full JCV-flex-center",w.applyStyles(this._preventionContainer,".JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-prevention-container{overflow:visible;transition:background .2s,opacity .2s,box-shadow .2s,border .2s,filter .2s,backdrop-filter .2s}.JSON-Canvas-Viewer .JCV-prevention-container.JCV-hidden{pointer-events:none;opacity:0}.JSON-Canvas-Viewer .JCV-prevention-container .JCV-prevention-banner{border-radius:12px;padding:12px;margin:12px;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);text-align:center}"),this._preventionContainer.appendChild(e),this.DM.data.container.appendChild(this._preventionContainer),this.options.preventMistouchAtStart&&this.startPrevention(),window.addEventListener("pointerdown",this.onPointerDown),window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp),this.augment({startMistouchPrevention:this.startPrevention,endMistouchPrevention:this.endPrevention}),this.onDispose(this.dispose)}onPointerDown=t=>{const e=this.DM.data.container.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=t.clientX,this.preventMistouch.initialY=t.clientY,this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY,this.preventMistouch.record=!0)};onPointerMove=t=>{this.preventMistouch.record&&(this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY)};onPointerUp=()=>{this.preventMistouch.record&&(this.preventMistouch.record=!1,Math.abs(this.preventMistouch.lastX-this.preventMistouch.initialX)+Math.abs(this.preventMistouch.lastY-this.preventMistouch.initialY)<5&&this.endPrevention())};startPrevention=()=>{this.preventionContainer.classList.remove("JCV-hidden"),this.DM.data.container.classList.add("JCV-numb"),this.preventMt=!0};endPrevention=()=>{this.preventMt=!1,this.preventionContainer.classList.add("JCV-hidden"),setTimeout(()=>this.DM.data.container.classList.remove("JCV-numb"),50)};dispose=()=>{window.removeEventListener("pointerdown",this.onPointerDown),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),this.preventionContainer.remove(),this._preventionContainer=null}}async function I(t){return C.sanitize(await g(t))}async function P(t){return await fetch(t).then(t=>t.json())}export{f as BaseModule,J as Controller,B as Controls,x as DataManager,E as DebugPanel,k as InteractionHandler,z as JSONCanvasViewer,L as Minimap,T as MistouchPreventer,S as OverlayManager,O as Renderer,b as StyleManager,w as canvasUtils,P as fetchCanvas,I as parser,_ as renderToString};
|
|
1
|
+
import{default as e}from"./kernel/index.js";import{default as r}from"./utilities/renderToString.js";import{BaseModule as a}from"./kernel/BaseModule.js";import{default as t}from"./modules/Controls/index.js";import{default as s}from"./modules/DebugPanel/index.js";import{default as o}from"./modules/Minimap/index.js";import{default as n}from"./modules/MistouchPreventer/index.js";import{default as i}from"./kernel/utilities.js";import{default as l}from"./utilities/fetchCanvas.js";import{default as m}from"./utilities/parser.js";import f from"./kernel/Controller.js";import d from"./kernel/DataManager.js";import u from"./kernel/InteractionHandler.js";import p from"./kernel/OverlayManager.js";import j from"./kernel/Renderer.js";import M from"./kernel/StyleManager.js";const g={Controller:f,DataManager:d,InteractionHandler:u,OverlayManager:p,Renderer:j,StyleManager:M};export{a as BaseModule,t as Controls,s as DebugPanel,e as JSONCanvasViewer,o as Minimap,n as MistouchPreventer,i as canvasUtils,l as fetchCanvas,g as internal,m as parser,r as renderToString};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/kernel/BaseModule.ts","../src/kernel/utilities.ts","../src/kernel/DataManager.ts","../src/kernel/StyleManager.ts","../src/kernel/Controller.ts","../src/kernel/OverlayManager.ts","../src/kernel/InteractionHandler.ts","../src/kernel/Renderer.ts","../src/kernel/index.ts","../src/renderToString.ts","../src/modules/Controls/index.ts","../src/modules/DebugPanel/index.ts","../src/modules/Minimap/index.ts","../src/modules/MistouchPreventer/index.ts","../src/chimp.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { General, GeneralObject, ModuleInput as MI, Orchestratable } from '$/types';\nimport type utilities from '$/utilities';\nimport type { Container } from '@needle-di/core';\n\ntype Hook = ReturnType<typeof utilities.makeHook>;\n\nexport type GeneralModuleCtor = typeof BaseModule<General, General>;\nexport type GeneralModule = BaseModule<General, General>;\n\nexport type ModuleInputCtor = Array<GeneralModuleCtor>;\nexport type ModuleInput = MI<GeneralModuleCtor>;\nexport type Options<M extends ModuleInput> = Orchestratable<M, 'options'>;\nexport type Augmentation<M extends ModuleInput> = Orchestratable<M, '_Augmentation'>;\n\nexport type BaseArgs = ConstructorParameters<GeneralModuleCtor>;\n\nexport class BaseModule<O extends BaseOptions = BaseOptions, A extends GeneralObject = {}> {\n\t// https://github.com/timocov/dts-bundle-generator/issues/360\n\tdeclare private static readonly _BaseModuleBrand: unique symbol; // Nominal marker\n\tdeclare _Augmentation: A;\n\tonStart: Hook['subscribe'];\n\tonRestart: Hook['subscribe'];\n\tonDispose: Hook['subscribe'];\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tonStart: Hook,\n\t\tonDispose: Hook,\n\t\tonRestart: Hook,\n\t\tprotected augment: (aug: A) => void,\n\t) {\n\t\tthis.options = options as O;\n\t\tthis.onStart = onStart.subscribe;\n\t\tthis.onDispose = onDispose.subscribe;\n\t\tthis.onRestart = onRestart.subscribe;\n\t}\n\toptions: O;\n}\n","import type { GeneralArray } from '$/types';\nimport type { JSONCanvasNode } from '@repo/shared';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\n\t\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\",\n);\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn { x: midX, y: node.y };\n\t\tcase 'bottom':\n\t\t\treturn { x: midX, y: node.y + node.height };\n\t\tcase 'left':\n\t\t\treturn { x: node.x, y: midY };\n\t\tcase 'right':\n\t\t\treturn { x: node.x + node.width, y: midY };\n\t\tdefault:\n\t\t\treturn { x: midX, y: midY };\n\t}\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio ?? 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx)\n\t\tthrow new Error(\n\t\t\t'[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.',\n\t\t);\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n\ntype MatchingFunc<Args extends GeneralArray> = (...args: Args) => void | Promise<void>;\nexport type Hook<Args extends GeneralArray = [], Async extends boolean = false> = {\n\t(...args: Args): Async extends true ? Promise<void> : void;\n\tsubs: Set<MatchingFunc<Args>>;\n\tsubscribe(callback: MatchingFunc<Args>): void;\n\tunsubscribe(callback: MatchingFunc<Args>): void;\n};\n\n/**\n * A quick function to create a hook that can be subscribed to and unsubscribed from.\n * Pass your arguments as the type parameter\n *\n * @param reverse - Whether the hook should reverse the execution order or not\n * @param async - Whether the hook is async or not\n * @example const hook = makeHook(true);\n */\nexport function makeHook<Args extends GeneralArray = [], Async extends boolean = false>(\n\treverse: boolean = false,\n\tasync: Async = false as Async,\n) {\n\tconst result = (\n\t\tasync\n\t\t\t? async (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) await callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) await callback(...args);\n\t\t\t\t}\n\t\t\t: (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) void callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) void callback(...args);\n\t\t\t\t}\n\t) as Hook<Args, Async>;\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import type { BaseOptions } from '$';\nimport type { Box, NodeBounds } from '$/types';\nimport type { JSONCanvas, JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport style from '$/styles.scss?inline';\nimport utilities, { type Hook } from '$/utilities';\n\nconst INITIAL_VIEWPORT_PADDING = 100;\nconst NODE_LABEL_MARGIN = 40;\nconst EDGE_BOX_HEURISTICS_BASE_MARGIN = 10;\n\ninterface Options extends BaseOptions {\n\tshadowed?: boolean;\n\tcanvas?: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n\tattachments?: Record<string, string>;\n\tnoAttachmentRelocation?: boolean;\n}\n\ninterface Augmentation {\n\tresetView: DataManager['resetView'];\n\ttoggleFullscreen: DataManager['toggleFullscreen'];\n\tonToggleFullscreen: DataManager['onToggleFullscreen'];\n}\n\nexport interface NodeItem {\n\tref: JSONCanvasNode;\n\tbox: Box;\n\tfileName?: string;\n\tonBeforeUnmount?: Hook;\n\tonActive?: Hook;\n\tonLoseActive?: Hook;\n}\n\nexport interface EdgeItem {\n\tref: JSONCanvasEdge;\n\tbox: Box;\n\tcontrolPoints?: Array<number>;\n}\n\ntype NodeMap = Record<string, NodeItem>;\ntype EdgeMap = Record<string, EdgeItem>;\n\nexport default class DataManager extends BaseModule<Options, Augmentation> {\n\tonToggleFullscreen = utilities.makeHook<['enter' | 'exit']>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: NodeMap;\n\t\tedgeMap: EdgeMap;\n\t\tcanvasBaseDir: string;\n\t\tnodeBounds: NodeBounds;\n\t\toffsetX: number;\n\t\toffsetY: number;\n\t\tscale: number;\n\t\tcontainer: HTMLDivElement;\n\t} = {\n\t\tcanvasData: {\n\t\t\tnodes: [],\n\t\t\tedges: [],\n\t\t},\n\t\tnodeMap: {},\n\t\tedgeMap: {},\n\t\tcanvasBaseDir: './',\n\t\tnodeBounds: {\n\t\t\tmaxX: 0,\n\t\t\tmaxY: 0,\n\t\t\tminX: 0,\n\t\t\tminY: 0,\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\tcenterX: 0,\n\t\t\tcenterY: 0,\n\t\t},\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\n\t\tcontainer: document.createElement('div'),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst viewerContainer = this.options.container;\n\t\twhile (viewerContainer.firstElementChild) viewerContainer.firstElementChild.remove();\n\t\tviewerContainer.innerHTML = '';\n\n\t\tconst realContainer = this.options.shadowed\n\t\t\t? viewerContainer.attachShadow({ mode: 'open' })\n\t\t\t: viewerContainer;\n\n\t\tutilities.applyStyles(realContainer, style + this.options.extraCSS);\n\n\t\tthis.data.container.classList.add('JSON-Canvas-Viewer');\n\t\trealContainer.appendChild(this.data.container);\n\n\t\tthis.augment({\n\t\t\tresetView: this.resetView,\n\t\t\ttoggleFullscreen: this.toggleFullscreen,\n\t\t\tonToggleFullscreen: this.onToggleFullscreen,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tconst canvasData = Object.assign(\n\t\t\t{\n\t\t\t\tnodes: [],\n\t\t\t\tedges: [],\n\t\t\t},\n\t\t\tthis.options.canvas,\n\t\t);\n\n\t\tObject.assign(this.data, {\n\t\t\tcanvasData: canvasData,\n\t\t\tnodeMap: {},\n\t\t\tedgeMap: {},\n\t\t\tcanvasBaseDir: this.processBaseDir(this.options.attachmentDir),\n\t\t\tnodeBounds: this.calculateNodeBounds(canvasData),\n\t\t\toffsetX: 0,\n\t\t\toffsetY: 0,\n\t\t\tscale: 1,\n\t\t});\n\n\t\tthis.data.canvasData.nodes.forEach((node) => {\n\t\t\tconst item: NodeItem = {\n\t\t\t\tref: node,\n\t\t\t\tbox: this.getNodeBox(node),\n\t\t\t};\n\t\t\tthis.data.nodeMap[node.id] = item;\n\n\t\t\t// re-process attachments\n\t\t\tif (node.type === 'file') {\n\t\t\t\tconst path = node.file.split('/');\n\t\t\t\tconst fileName = path.pop() ?? '';\n\t\t\t\titem.fileName = fileName;\n\t\t\t\tif (!node.file.startsWith('http://') && !node.file.startsWith('https://')) {\n\t\t\t\t\tconst userDefinedAttachment = this.options.attachments?.[fileName];\n\t\t\t\t\tif (userDefinedAttachment) node.file = userDefinedAttachment;\n\t\t\t\t\telse if (!this.options.noAttachmentRelocation)\n\t\t\t\t\t\tnode.file = this.data.canvasBaseDir + fileName;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.data.canvasData.edges.forEach((edge) => {\n\t\t\tthis.data.edgeMap[edge.id] = {\n\t\t\t\tref: edge,\n\t\t\t\tbox: this.getEdgeBox(edge),\n\t\t\t};\n\t\t});\n\t\tthis.resetView();\n\t};\n\n\tprivate processBaseDir = (baseDir: string | undefined) => {\n\t\tif (!baseDir) return './';\n\t\tconst lastChar = baseDir?.slice(-1);\n\t\tif (lastChar === '/') return baseDir;\n\t\treturn `${baseDir}/`;\n\t};\n\n\tprivate getNodeBox = (node: JSONCanvasNode) => {\n\t\treturn {\n\t\t\tleft: node.x,\n\t\t\ttop:\n\t\t\t\tnode.type === 'file' || node.type === 'group' ? node.y - NODE_LABEL_MARGIN : node.y,\n\t\t\tright: node.width + node.x,\n\t\t\tbottom: node.y + node.height,\n\t\t};\n\t};\n\n\tprivate getEdgeBox = (edge: JSONCanvasEdge) => {\n\t\tconst nodes = this.data.nodeMap;\n\t\tconst from = nodes[edge.fromNode].ref;\n\t\tconst to = nodes[edge.toNode].ref;\n\t\tconst fromAnchor = utilities.getAnchorCoord(from, edge.fromSide);\n\t\tconst toAnchor = utilities.getAnchorCoord(to, edge.toSide);\n\t\tconst strictBox = {\n\t\t\tleft: Math.min(fromAnchor.x, toAnchor.x),\n\t\t\ttop: Math.min(fromAnchor.y, toAnchor.y),\n\t\t\tright: Math.max(fromAnchor.x, toAnchor.x),\n\t\t\tbottom: Math.max(fromAnchor.y, toAnchor.y),\n\t\t};\n\t\t// edge size heuristics\n\t\tconst width = strictBox.right - strictBox.left;\n\t\tconst height = strictBox.bottom - strictBox.top;\n\t\tconst _min = Math.min(width, height);\n\t\tconst min = _min === 0 ? 1 : _min;\n\t\tconst max = Math.max(width, height);\n\t\tconst edgeFactor = Math.log2(max / min);\n\t\tconst margin = edgeFactor * EDGE_BOX_HEURISTICS_BASE_MARGIN;\n\t\treturn {\n\t\t\tleft: strictBox.left - margin,\n\t\t\ttop: strictBox.top - margin,\n\t\t\tright: strictBox.right + margin,\n\t\t\tbottom: strictBox.bottom + margin,\n\t\t};\n\t};\n\n\tprivate calculateNodeBounds(canvasData: Required<JSONCanvas>) {\n\t\tlet minX = Infinity,\n\t\t\tminY = Infinity,\n\t\t\tmaxX = -Infinity,\n\t\t\tmaxY = -Infinity;\n\t\tcanvasData.nodes.forEach((node) => {\n\t\t\tminX = Math.min(minX, node.x);\n\t\t\tminY = Math.min(minY, node.y);\n\t\t\tmaxX = Math.max(maxX, node.x + node.width);\n\t\t\tmaxY = Math.max(maxY, node.y + node.height);\n\t\t});\n\t\tconst width = maxX - minX;\n\t\tconst height = maxY - minY;\n\t\tconst centerX = minX + width / 2;\n\t\tconst centerY = minY + height / 2;\n\t\treturn { minX, minY, maxX, maxY, width, height, centerX, centerY };\n\t}\n\ttoggleFullscreen = async (option?: 'enter' | 'exit') => {\n\t\tif (!document.fullscreenElement && (!option || option === 'enter')) {\n\t\t\tawait this.data.container.requestFullscreen();\n\t\t\tthis.onToggleFullscreen('enter');\n\t\t} else if (document.fullscreenElement && (!option || option === 'exit')) {\n\t\t\tawait document.exitFullscreen();\n\t\t\tthis.onToggleFullscreen('exit');\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n","import type { BaseOptions } from '$';\nimport { BaseModule, type BaseArgs } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities from '$/utilities';\nimport {\n\tparseHex,\n\ttoHslString,\n\ttype HslColor,\n\trgbToHsl,\n\tparseHsl,\n\tparseRgb,\n} from '@ahmedsemih/color-fns';\n\nexport type Color = {\n\tborder: string;\n\tbackground: string;\n\tactive: string;\n\ttext: string;\n\tcard: string;\n};\n\ntype ColorOptions = {\n\t[K in keyof (StyleManager['definedColors']['light'] &\n\t\tStyleManager['namedColors']['light'])]?: string;\n};\n\ninterface Options extends BaseOptions {\n\ttheme?: 'dark' | 'light';\n\tcolors?: {\n\t\tlight?: ColorOptions;\n\t\tdark?: ColorOptions;\n\t};\n}\n\ninterface Augmentation {\n\tchangeTheme: StyleManager['changeTheme'];\n\tonChangeTheme: StyleManager['onChangeTheme'];\n}\n\nexport default class StyleManager extends BaseModule<Options, Augmentation> {\n\ttheme: 'dark' | 'light' = 'light';\n\tonChangeTheme = utilities.makeHook<['light' | 'dark']>();\n\tdefinedColors = {\n\t\tlight: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 72 },\n\t\t\t'1': { hue: 358, saturation: 81, lightness: 55 },\n\t\t\t'2': { hue: 19, saturation: 87, lightness: 58 },\n\t\t\t'3': { hue: 41, saturation: 79, lightness: 52 },\n\t\t\t'4': { hue: 150, saturation: 100, lightness: 37 },\n\t\t\t'5': { hue: 221, saturation: 100, lightness: 59 },\n\t\t\t'6': { hue: 257, saturation: 81, lightness: 62 },\n\t\t},\n\t\tdark: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 40 },\n\t\t\t'1': { hue: 358, saturation: 100, lightness: 65 },\n\t\t\t'2': { hue: 23, saturation: 86, lightness: 63 },\n\t\t\t'3': { hue: 39, saturation: 91, lightness: 70 },\n\t\t\t'4': { hue: 153, saturation: 80, lightness: 45 },\n\t\t\t'5': { hue: 217, saturation: 100, lightness: 62 },\n\t\t\t'6': { hue: 259, saturation: 100, lightness: 75 },\n\t\t},\n\t};\n\n\tnamedColors = {\n\t\tlight: {\n\t\t\tdots: 'hsla(0, 0%, 72%, 0.4)',\n\t\t\ttext: 'rgb(30, 30, 30)',\n\t\t\tbackground: 'rgb(250, 250, 250)',\n\t\t\t'background-secondary': 'rgb(255, 255, 255)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.1)',\n\t\t\tborder: 'hsla(0, 0%, 82%, 0.7)',\n\t\t},\n\t\tdark: {\n\t\t\tdots: 'hsla(0, 0%, 40%, 0.3)',\n\t\t\ttext: 'rgb(242, 242, 242)',\n\t\t\tbackground: 'rgb(30, 30, 30)',\n\t\t\t'background-secondary': 'rgb(37, 37, 40)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.2)',\n\t\t\tborder: 'hsla(0, 0%, 30%, 0.7)',\n\t\t},\n\t};\n\n\tprivate colorCache: {\n\t\tdark: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t\tlight: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t} = {\n\t\tdark: {},\n\t\tlight: {},\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\n\t\t// user-defined color merging\n\t\tconst colors = this.options.colors;\n\t\tif (colors) {\n\t\t\tconst themes = ['light', 'dark'] as const;\n\t\t\tthemes.forEach((theme) => {\n\t\t\t\tif (!(theme in colors)) return;\n\t\t\t\tconst colorObject = colors[theme];\n\t\t\t\tif (!colorObject) return;\n\t\t\t\tObject.entries(colorObject).forEach(([key, value]) => {\n\t\t\t\t\tif (!value) return;\n\t\t\t\t\tconst namedColorsDict = this.namedColors[theme];\n\t\t\t\t\tconst definedColorsDict = this.definedColors[theme];\n\t\t\t\t\tif (key in namedColorsDict)\n\t\t\t\t\t\tnamedColorsDict[key as keyof typeof namedColorsDict] = value;\n\t\t\t\t\telse if (key in definedColorsDict) {\n\t\t\t\t\t\tconst color = this.parseColor(value);\n\t\t\t\t\t\tif (!color) {\n\t\t\t\t\t\t\tconsole.warn(`[JSON Canvas Viewer] Color ${value} unsupported.`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefinedColorsDict[key as keyof typeof definedColorsDict] = color;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tthis.changeTheme(this.options.theme ?? 'light');\n\t\tthis.augment({\n\t\t\tchangeTheme: this.changeTheme,\n\t\t\tonChangeTheme: this.onChangeTheme,\n\t\t});\n\t}\n\n\tprivate hslProcessor = (color: HslColor) => {\n\t\tconst { hue, saturation, lightness } = color;\n\t\tlet result;\n\t\tif (this.theme === 'dark') {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard: { hue, saturation: saturation / 3, lightness: lightness / 3 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t} else {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard:\n\t\t\t\t\thue === 0\n\t\t\t\t\t\t? { hue, saturation, lightness: 100 }\n\t\t\t\t\t\t: { hue, saturation: saturation * 0.4, lightness: 90 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tactive: toHslString(result.active),\n\t\t\tcard: toHslString(result.card),\n\t\t\tborder: toHslString(result.border),\n\t\t\tbackground: toHslString(result.background),\n\t\t\ttext: result.text,\n\t\t};\n\t};\n\n\tprivate parseColor = (color: string) => {\n\t\tif (color.startsWith('rgb')) return rgbToHsl(parseRgb(color));\n\t\tif (color.startsWith('#')) return rgbToHsl(parseHex(color));\n\t\tif (color.startsWith('hsl')) return parseHsl(color);\n\t};\n\n\tgetColor = (colorIndex: string = '0') => {\n\t\tconst theme = this.theme;\n\t\tlet color: Color;\n\t\tif (this.colorCache[theme][colorIndex]) return this.colorCache[theme][colorIndex];\n\t\telse if (colorIndex in this.definedColors[theme])\n\t\t\tcolor = this.hslProcessor(\n\t\t\t\tthis.definedColors[theme][colorIndex as keyof typeof this.definedColors.dark],\n\t\t\t);\n\t\telse color = this.hslProcessor(rgbToHsl(parseHex(colorIndex)));\n\t\tthis.colorCache[theme][colorIndex] = color;\n\t\treturn color;\n\t};\n\n\tgetNamedColor = (name: keyof typeof this.namedColors.light) =>\n\t\tthis.namedColors[this.theme][name];\n\n\tchangeTheme = (theme?: 'dark' | 'light') => {\n\t\tthis.theme = theme ? theme : this.theme === 'dark' ? 'light' : 'dark';\n\t\tconst container = this.container.get(DataManager).data.container;\n\t\tObject.entries(this.namedColors[this.theme]).forEach(([key, value]) => {\n\t\t\tcontainer.style.setProperty(`--${key}`, value);\n\t\t});\n\t\tthis.onChangeTheme(this.theme);\n\t};\n}\n","import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\n\ninterface Augmentation {\n\trefresh: Controller['refresh'];\n\tonRefresh: Controller['onRefresh'];\n\tonResize: Controller['onResize'];\n}\n\nexport default class Controller extends BaseModule<BaseOptions, Augmentation> {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame: {\n\t\tlastScale: number;\n\t\tlastOffsets: { x: number; y: number };\n\t} = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\tonResize = utilities.makeHook<[number, number]>();\n\tonRefresh = utilities.makeHook();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResizeCallback);\n\t\tthis.SM.onChangeTheme.subscribe(this.refresh);\n\t\tthis.augment({\n\t\t\trefresh: this.refresh,\n\t\t\tonRefresh: this.onRefresh,\n\t\t\tonResize: this.onResize,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.refresh);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.resizeObserver.observe(this.DM.data.container);\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate draw = () => {\n\t\tif (\n\t\t\tthis.perFrame.lastScale !== this.DM.data.scale ||\n\t\t\tthis.perFrame.lastOffsets.x !== this.DM.data.offsetX ||\n\t\t\tthis.perFrame.lastOffsets.y !== this.DM.data.offsetY\n\t\t)\n\t\t\tthis.refresh();\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\trefresh = () => {\n\t\tthis.perFrame = {\n\t\t\tlastScale: this.DM.data.scale,\n\t\t\tlastOffsets: { x: this.DM.data.offsetX, y: this.DM.data.offsetY },\n\t\t};\n\t\tthis.onRefresh();\n\t};\n\n\tprivate onResizeCallback = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\tprivate dispose = () => {\n\t\tif (this.animationId) cancelAnimationFrame(this.animationId);\n\t\tif (this.resizeAnimationId) cancelAnimationFrame(this.resizeAnimationId);\n\t\tthis.resizeObserver.disconnect();\n\t};\n}\n","import type { BaseOptions } from '$';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager, { type Color } from '$/StyleManager';\nimport utilities, { destroyError, type Hook } from '$/utilities';\n\ninterface Options extends BaseOptions {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n}\n\ninterface Augmentation {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n}\n\n// TODO: add more formats\nconst fileRegex = {\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (\n\tcontainer: HTMLDivElement,\n\tcontent: string,\n\tnode: N,\n\tonBeforeUnmount: Hook,\n\tonActive: Hook,\n\tonLoseActive: Hook,\n) => void | Promise<void>;\n\ntype CreateOverlayArgs =\n\t| [ComponentNodeMap['text'], string, 'text']\n\t| [ComponentNodeMap['markdown'], string, 'markdown']\n\t| [ComponentNodeMap['image'], string, 'image']\n\t| [ComponentNodeMap['audio'], string, 'audio']\n\t| [ComponentNodeMap['video'], string, 'video']\n\t| [ComponentNodeMap['link'], string, 'link'];\n\ntype ComponentNodeMap = {\n\ttext: JSONCanvasTextNode;\n\tmarkdown: JSONCanvasFileNode;\n\timage: JSONCanvasFileNode;\n\taudio: JSONCanvasFileNode;\n\tvideo: JSONCanvasFileNode;\n\tlink: JSONCanvasLinkNode;\n};\n\ntype ComponentDict = {\n\t[K in keyof ComponentNodeMap]: NodeComponentHook<ComponentNodeMap[K]>;\n};\n\nconst supportedTypes = ['markdown', 'image', 'audio', 'video'] as const;\n\nexport default class OverlayManager extends BaseModule<Options, Augmentation> {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate parse: Parser;\n\tprivate componentDict: ComponentDict = {\n\t\ttext: (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.innerHTML = content;\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t},\n\t\tmarkdown: async (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.textContent = 'Loading...';\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t\tlet parsedContent: string;\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(content);\n\t\t\t\tconst result = await response.text();\n\t\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\t\tif (frontmatterMatch) parsedContent = await this.parse(frontmatterMatch[2]);\n\t\t\t\telse parsedContent = await this.parse(result);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', err);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\n\t\tlink: (container, content) => {\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.src = content;\n\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\tiframe.className = 'JCV-link-iframe';\n\t\t\tiframe.loading = 'lazy';\n\t\t\tcontainer.appendChild(iframe);\n\t\t},\n\t\taudio: (container, content) => {\n\t\t\tconst audio = document.createElement('audio');\n\t\t\taudio.className = 'JCV-audio';\n\t\t\taudio.src = content;\n\t\t\taudio.controls = true;\n\t\t\tcontainer.appendChild(audio);\n\t\t},\n\t\timage: (container, content) => {\n\t\t\tconst img = document.createElement('img');\n\t\t\timg.className = 'JCV-img';\n\t\t\timg.src = content;\n\t\t\timg.loading = 'lazy';\n\t\t\tcontainer.appendChild(img);\n\t\t},\n\t\tvideo: (container, content) => {\n\t\t\tconst video = document.createElement('video');\n\t\t\tvideo.className = 'JCV-video';\n\t\t\tvideo.src = content;\n\t\t\tvideo.controls = true;\n\t\t\tcontainer.appendChild(video);\n\t\t},\n\t};\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\tonInteractionStart = utilities.makeHook();\n\tonInteractionEnd = utilities.makeHook();\n\tonNodeActive = utilities.makeHook<[JSONCanvasNode]>();\n\tonNodeLosesActive = utilities.makeHook<[JSONCanvasNode]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.parser || ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.onRefresh.subscribe(this.updateOverlays);\n\t\tthis.SM.onChangeTheme.subscribe(this.themeChanged);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'JCV-overlays';\n\t\tthis._overlaysLayer.id = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tconst components = this.options.nodeComponents;\n\t\tif (components) Object.assign(this.componentDict, components);\n\n\t\tthis.augment({\n\t\t\tonNodeActive: this.onNodeActive,\n\t\t\tonNodeLosesActive: this.onNodeLosesActive,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.restart);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate renderOverlays = () => {\n\t\tconst overlayMatcher = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.createOverlay(node, await this.parse(node.text), 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tfor (const type of supportedTypes) {\n\t\t\t\t\t\tif (!node.file.match(fileRegex[type])) continue;\n\t\t\t\t\t\tthis.createOverlay(node, node.file, type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.createOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(async (node) => {\n\t\t\tawait overlayMatcher(node.ref);\n\t\t});\n\t};\n\n\tprivate themeChanged = () => {\n\t\tObject.values(this.overlays).forEach((overlay) => {\n\t\t\tconst node = this.DM.data.nodeMap[overlay.id].ref;\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.setOverlayColor(overlay, color);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = !previousId ? null : this.overlays[previousId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous && previousId) {\n\t\t\tprevious.classList.remove('JCV-active');\n\t\t\tconst nodeItem = this.DM.data.nodeMap[previousId];\n\t\t\tthis.onNodeLosesActive(nodeItem.ref);\n\t\t\tnodeItem.onLoseActive?.();\n\t\t}\n\t\tif (current && id) {\n\t\t\tcurrent.classList.add('JCV-active');\n\t\t\tthis.onInteractionStart();\n\t\t\tconst nodeItem = this.DM.data.nodeMap[id];\n\t\t\tthis.onNodeActive(nodeItem.ref);\n\t\t\tnodeItem.onActive?.();\n\t\t} else this.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate createOverlay = (...args: CreateOverlayArgs) => {\n\t\tif (this.aborted) return;\n\t\tconst node = args[0];\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = this.constructOverlay(...args);\n\t\t\tif (this.aborted) return;\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t}\n\t};\n\n\tprivate constructOverlay = (...args: CreateOverlayArgs) => {\n\t\tconst node = args[0];\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('JCV-overlay-container');\n\t\toverlay.id = node.id;\n\t\tthis.setOverlayColor(overlay, this.SM.getColor(node.color));\n\t\tconst contentWrapper = document.createElement('div');\n\t\tcontentWrapper.classList.add('JCV-content');\n\t\toverlay.appendChild(contentWrapper);\n\t\tconst clickLayer = document.createElement('div');\n\t\tclickLayer.className = 'JCV-click-layer';\n\t\toverlay.appendChild(clickLayer);\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'JCV-overlay-border';\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst nodeItem = this.DM.data.nodeMap[node.id];\n\n\t\tnodeItem.onActive = utilities.makeHook();\n\t\tnodeItem.onLoseActive = utilities.makeHook();\n\t\tnodeItem.onBeforeUnmount = utilities.makeHook();\n\n\t\tvoid this.componentDict[args[2]](\n\t\t\tcontentWrapper,\n\t\t\targs[1],\n\t\t\targs[0] as never,\n\t\t\tnodeItem.onBeforeUnmount,\n\t\t\tnodeItem.onActive,\n\t\t\tnodeItem.onLoseActive,\n\t\t);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t};\n\n\tprivate setOverlayColor = (overlay: HTMLDivElement, color: Color) => {\n\t\tObject.entries(color).forEach(([key, value]) => {\n\t\t\toverlay.style.setProperty(`--overlay-${key}`, value);\n\t\t});\n\t};\n\n\tprivate clearOverlays = () => {\n\t\tObject.entries(this.overlays).forEach(([id, overlay]) => {\n\t\t\tthis.DM.data.nodeMap[id].onBeforeUnmount?.();\n\t\t\tif (this.eventListeners[id]) {\n\t\t\t\tconst onStart = this.eventListeners[id][0];\n\t\t\t\tconst onEnd = this.eventListeners[id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\toverlay.removeEventListener('pointerenter', onStart);\n\t\t\t\toverlay.removeEventListener('pointerleave', onEnd);\n\t\t\t\toverlay.removeEventListener('touchstart', onStart);\n\t\t\t\toverlay.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[id][0] = null;\n\t\t\t\tthis.eventListeners[id][1] = null;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import type { BaseOptions } from '$';\nimport type { Coordinates } from '$/types';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport OverlayManager from '$/OverlayManager';\nimport utilities from '$/utilities';\nimport {\n\tClick,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype Events,\n\tWheelPanZoom,\n\tLubricator,\n\tpanPreset as pan,\n\tzoomPreset as zoom,\n\tdragPreset as drag,\n\ttype PointeractInterface,\n} from 'pointeract';\n\ntype LoadedModules = [Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom, Lubricator];\n\ntype LoadedEvents = Events<LoadedModules>;\n\ninterface Options extends BaseOptions {\n\tpointeract?: PointeractOptions<LoadedModules>;\n}\n\ninterface Augmentation {\n\tpan: InteractionHandler['pan'];\n\tpanToCoords: InteractionHandler['panToCoords'];\n\tzoom: InteractionHandler['zoom'];\n\tzoomToScale: InteractionHandler['zoomToScale'];\n}\n\nexport default class InteractionHandler extends BaseModule<Options, Augmentation> {\n\tpointeract: PointeractInterface<LoadedModules>;\n\tprivate DM: DataManager;\n\tonClick = utilities.makeHook<[string | null]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tconst options = Object.assign(this.options.pointeract ?? {}, {\n\t\t\tcoordinateOutput: 'relative',\n\t\t\telement: this.DM.data.container,\n\t\t\tlubricator: { pan, zoom, drag },\n\t\t} satisfies PointeractOptions<LoadedModules>);\n\t\tthis.pointeract = new Pointeract(options, [\n\t\t\tClick,\n\t\t\tDrag,\n\t\t\tWheelPanZoom,\n\t\t\tPreventDefault,\n\t\t\tMultitouchPanZoom,\n\t\t\tLubricator,\n\t\t]);\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.onInteractionStart.subscribe(this.stopInteract);\n\t\tOM.onInteractionEnd.subscribe(this.startInteract);\n\n\t\tthis.augment({\n\t\t\tpan: this.pan,\n\t\t\tpanToCoords: this.panToCoords,\n\t\t\tzoom: this.zoom,\n\t\t\tzoomToScale: this.zoomToScale,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.pointeract\n\t\t\t.on('pan', this.onPan)\n\t\t\t.on('drag', this.onPan)\n\t\t\t.on('zoom', this.onZoom)\n\t\t\t.on('trueClick', this.onTrueClick)\n\t\t\t.start();\n\t};\n\n\tprivate startInteract = () => {\n\t\tthis.pointeract.start();\n\t};\n\tprivate stopInteract = () => {\n\t\tthis.pointeract.stop();\n\t};\n\n\tprivate onPan = (event: LoadedEvents['pan']) => {\n\t\tthis.truePan({\n\t\t\tx: event.deltaX,\n\t\t\ty: event.deltaY,\n\t\t});\n\t};\n\tprivate onZoom = (event: LoadedEvents['zoom']) => {\n\t\tthis.trueZoom(event.factor, event);\n\t};\n\n\ttrueZoom = (_factor: number, origin: Coordinates) => {\n\t\tconst newScale = Math.max(Math.min(this.DM.data.scale * _factor, 20), 0.05);\n\t\tconst scale = this.DM.data.scale;\n\t\tif (newScale === scale) return;\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.DM.data.offsetX = origin.x - canvasCoords.x * factor;\n\t\tthis.DM.data.offsetY = origin.y - canvasCoords.y * factor;\n\t\tthis.DM.data.scale = newScale;\n\t};\n\ttruePan = ({ x, y }: Coordinates) => {\n\t\tthis.DM.data.offsetX = this.DM.data.offsetX + x;\n\t\tthis.DM.data.offsetY = this.DM.data.offsetY + y;\n\t};\n\n\tzoom = (_factor: number, origin: Coordinates) => {\n\t\tthis.pointeract.dispatch('zoom', { factor: _factor, ...origin });\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', { deltaX: x, deltaY: y });\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tthis.pointeract.dispatch('zoom', { factor, ...origin });\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', {\n\t\t\tdeltaX: x - this.DM.data.offsetX,\n\t\t\tdeltaY: y - this.DM.data.offsetY,\n\t\t});\n\t};\n\n\t// Container Coords to Canvas Coords relative to the top-left corner of the scaled canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.DM.data.offsetX,\n\t\ty: containerY - this.DM.data.offsetY,\n\t});\n\n\tprivate onTrueClick = (e: LoadedEvents['trueClick']) => {\n\t\tconst element = e.target as HTMLElement | null;\n\t\tif (this.isUIControl(element)) return;\n\t\tconst node = this.findNodeId(element);\n\t\tthis.onClick(node);\n\t};\n\n\tprivate isUIControl = (target: HTMLElement | null) => {\n\t\tif (!target) return false;\n\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t};\n\n\tprivate findNodeId = (element: HTMLElement | null) => {\n\t\tif (!element) return null;\n\t\tlet ele = element;\n\t\twhile (!ele.id || ele.id === '') {\n\t\t\tif (!ele.parentElement) break;\n\t\t\tele = ele.parentElement;\n\t\t}\n\t\tif (ele.id === 'overlays' || !ele.id || ele.id === '') return null;\n\t\treturn ele.id;\n\t};\n\n\tprivate dispose = () => this.pointeract.dispose();\n}\n","import type { BaseOptions } from '$';\nimport type { Box } from '$/types';\nimport type { JSONCanvasGroupNode, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager, { type EdgeItem, type NodeItem } from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 4;\nconst NODE_RADIUS = 12;\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\nconst NODE_BORDER_WIDTH = 2;\nconst DOT_RADIUS = 1; // Dot radius in CSS pixels\nconst DOT_BASE_GAP = 10; // Base gap between dots in CSS pixels\n\nconst NODE_BORDER_HALF_WIDTH = NODE_BORDER_WIDTH / 2;\n\ninterface Options extends BaseOptions {\n\tzoomInOptimization?: boolean;\n}\n\nexport default class Renderer extends BaseModule<Options> {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: Box;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (!this._canvas) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tcontroller.onRefresh.subscribe(this.redraw);\n\t\tcontroller.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'JCV-main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate optimizeDPR = () => {\n\t\tconst container = this.DM.data.container;\n\t\tutilities.resizeCanvasForDPR(this.canvas, container.offsetWidth, container.offsetHeight);\n\t};\n\n\tprivate redraw = () => {\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (!this.options.zoomInOptimization) {\n\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\treturn;\n\t\t}\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tif (\n\t\t\tthis.isInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: Box) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.drawGridDots(scale, offsetX, offsetY);\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tObject.values(this.DM.data.nodeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tconst node = item.ref;\n\t\t\tif (node.type === 'file') this.drawFile(item);\n\t\t\telse if (node.type === 'group') this.drawGroup(node, scale);\n\t\t});\n\t\tObject.values(this.DM.data.edgeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tthis.drawEdge(item);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: Box, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX =\n\t\t\t(this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY =\n\t\t\t(this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isInside = (inner: Box, outer: Box) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate isOutside = (inner: Box, outer: Box) =>\n\t\tinner.right < outer.left ||\n\t\tinner.bottom < outer.top ||\n\t\tinner.left > outer.right ||\n\t\tinner.top > outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (\n\t\tx: number,\n\t\ty: number,\n\t\tlabel: string,\n\t\tcolor: string,\n\t\ttextColor: string,\n\t\tscale: number,\n\t) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = textColor;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = this.SM.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tutilities.drawRoundRect(\n\t\t\tthis.ctx,\n\t\t\tnode.x + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.y + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.width - NODE_BORDER_WIDTH,\n\t\t\tnode.height - NODE_BORDER_WIDTH,\n\t\t\tradius,\n\t\t);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = NODE_BORDER_WIDTH;\n\t\tutilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasGroupNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label) {\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, color.active, color.text, scale);\n\t\t}\n\t};\n\n\tprivate drawFile = (item: NodeItem) => {\n\t\tthis.ctx.fillStyle = this.SM.getColor().text;\n\t\tconst node = item.ref;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(item.fileName ?? '', node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (item: EdgeItem) => {\n\t\tconst edge = item.ref;\n\t\tconst fromNode = this.DM.data.nodeMap[edge.fromNode].ref;\n\t\tconst toNode = this.DM.data.nodeMap[edge.toNode].ref;\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst { x: startX, y: startY } = gac(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = gac(toNode, edge.toSide);\n\t\tconst color = this.SM.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!item.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\titem.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = item.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\tcolor.active,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, color.active);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = color.active;\n\t\t\tthis.ctx.beginPath();\n\t\t\tutilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = color.text;\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawGridDots = (scale: number, offsetX: number, offsetY: number) => {\n\t\tconst scaleLevel = -Math.floor(Math.log2(scale));\n\t\tconst actualGap = DOT_BASE_GAP * 2 ** scaleLevel * scale;\n\t\tconst width = this.canvas.width;\n\t\tconst height = this.canvas.height;\n\t\tconst startX = offsetX % actualGap;\n\t\tconst startY = offsetY % actualGap;\n\t\tthis.ctx.fillStyle = this.SM.getNamedColor('dots');\n\t\tfor (let x = startX; x <= width; x += actualGap) {\n\t\t\tfor (let y = startY; y <= height; y += actualGap) {\n\t\t\t\tthis.ctx.beginPath();\n\t\t\t\tthis.ctx.arc(x, y, DOT_RADIUS, 0, 2 * Math.PI);\n\t\t\t\tthis.ctx.fill();\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t\tcolor: string,\n\t) => {\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(startX, startY);\n\t\tthis.ctx.bezierCurveTo(c1x, c1y, c2x, c2y, endX, endY);\n\t\tthis.ctx.strokeStyle = color;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (\n\t\ttipX: number,\n\t\ttipY: number,\n\t\tfromX: number,\n\t\tfromY: number,\n\t\tcolor: string,\n\t) => {\n\t\tconst dx = tipX - fromX;\n\t\tconst dy = tipY - fromY;\n\t\tconst length = Math.sqrt(dx * dx + dy * dy);\n\t\tif (length === 0) return;\n\t\tconst unitX = dx / length;\n\t\tconst unitY = dy / length;\n\t\tconst leftX = tipX - unitX * ARROW_LENGTH - unitY * ARROW_WIDTH;\n\t\tconst leftY = tipY - unitY * ARROW_LENGTH + unitX * ARROW_WIDTH;\n\t\tconst rightX = tipX - unitX * ARROW_LENGTH + unitY * ARROW_WIDTH;\n\t\tconst rightY = tipY - unitY * ARROW_LENGTH - unitX * ARROW_WIDTH;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.moveTo(tipX, tipY);\n\t\tthis.ctx.lineTo(leftX, leftY);\n\t\tthis.ctx.lineTo(rightX, rightY);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t};\n\n\tprivate dispose = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tthis.canvas.remove();\n\t\tthis._canvas = null;\n\t};\n}\n","import type {\n\tModuleInputCtor,\n\tModuleInput,\n\tOptions,\n\tAugmentation,\n\tGeneralModuleCtor,\n} from '$/BaseModule';\nimport type { GeneralObject } from '$/types';\nimport type { JSONCanvas } from '@repo/shared';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\nimport { Container } from '@needle-di/core';\n\nexport interface BaseOptions {\n\tcontainer: HTMLElement;\n\tloading?: 'normal' | 'lazy' | 'none';\n}\n\nconst internalModules = [\n\tDataManager,\n\tStyleManager,\n\tController,\n\tOverlayManager,\n\tInteractionHandler,\n\tRenderer,\n];\n\ntype InternalModules = typeof internalModules;\n\nexport type AllOptions<M extends ModuleInput = []> = Options<M> & Options<InternalModules>;\ntype AllAugmentation<M extends ModuleInput = []> = Augmentation<M> & Augmentation<InternalModules>;\n\nclass JSONCanvasViewer<M extends ModuleInputCtor> {\n\tprivate allModules: ModuleInputCtor;\n\tprivate IO: IntersectionObserver | null = null;\n\tprivate started = false;\n\tprivate disposed = false;\n\toptions: AllOptions<M>;\n\tcontainer: Container;\n\tonDispose = utilities.makeHook(true);\n\tonStart = utilities.makeHook();\n\tonRestart = utilities.makeHook();\n\n\tconstructor(options: AllOptions<M>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () =>\n\t\t\t\t\tnew Class(\n\t\t\t\t\t\tthis.container,\n\t\t\t\t\t\tthis.options,\n\t\t\t\t\t\tthis.onStart,\n\t\t\t\t\t\tthis.onDispose,\n\t\t\t\t\t\tthis.onRestart,\n\t\t\t\t\t\tthis.augment,\n\t\t\t\t\t),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [...internalModules, ...(modules ?? [])];\n\t\tthis.allModules.forEach(bind);\n\t\tthis.allModules.forEach((Module) => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\n\t\tconst loading = this.options.loading ?? 'normal';\n\t\tif (loading === 'normal') this.load();\n\t\telse if (loading === 'lazy') {\n\t\t\tthis.IO = new IntersectionObserver(this.onVisibilityCheck, {\n\t\t\t\troot: null,\n\t\t\t\trootMargin: '50px',\n\t\t\t\tthreshold: 0,\n\t\t\t});\n\t\t\tthis.IO.observe(this.options.container);\n\t\t}\n\t}\n\n\tprivate onVisibilityCheck = (entries: Array<IntersectionObserverEntry>) => {\n\t\tentries.forEach((entry) => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tthis.load();\n\t\t\t\tthis.IO?.disconnect();\n\t\t\t\tthis.IO = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t});\n\t};\n\n\tprivate augment = (aug: GeneralObject) => {\n\t\tconst descriptors = Object.getOwnPropertyDescriptors(aug);\n\t\tObject.defineProperties(this, descriptors);\n\t};\n\n\tload = (options?: {\n\t\tcanvas?: JSONCanvas;\n\t\tattachmentDir?: string;\n\t\tattachments?: Record<string, string>;\n\t}) => {\n\t\tif (this.disposed) return;\n\t\tif (options) Object.assign(this.options, options);\n\t\tif (this.started) this.onRestart();\n\t\telse {\n\t\t\tthis.onStart();\n\t\t\tthis.started = true;\n\t\t}\n\t};\n\n\tdispose = () => {\n\t\tif (!this.started || this.disposed) return;\n\t\tthis.IO?.disconnect();\n\t\tthis.IO = null;\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.onDispose();\n\t\tthis.container.unbindAll();\n\t\tthis.disposed = true;\n\t};\n}\n\ntype JSONCanvasViewerType = new <M extends ModuleInputCtor = []>(\n\t...args: ConstructorParameters<typeof JSONCanvasViewer<M>>\n) => JSONCanvasViewer<M> & AllAugmentation<M>;\n\nexport type JSONCanvasViewerInterface<M extends ModuleInput = []> = JSONCanvasViewer<never> &\n\tAllAugmentation<M>;\n\nexport default JSONCanvasViewer as JSONCanvasViewerType;\n","import type { JSONCanvas, JSONCanvasFileNode, JSONCanvasNode, Parser } from '@repo/shared';\n\nexport default async function (options: {\n\tcanvas: JSONCanvas;\n\tattachments?: Record<string, string>;\n\tattachmentDir?: string;\n\tparser?: Parser;\n}) {\n\tconst render = async (node: JSONCanvasNode) =>\n\t\tawait renderer(node, options.parser ?? ((markdown: string) => markdown));\n\tconst nodes = options.canvas.nodes ?? [];\n\tconst basePath = options.attachmentDir ?? './';\n\tnodes.forEach((node) => {\n\t\tif (node.type === 'file' && !node.file.startsWith('http')) {\n\t\t\tconst file = node.file.split('/');\n\t\t\tconst name = file.pop() ?? '';\n\t\t\tif (options.attachments?.[name]) node.file = options.attachments[name];\n\t\t\telse node.file = basePath + name;\n\t\t}\n\t});\n\tconst renderedContent: Array<string> = [];\n\tawait Promise.all(nodes.map(async (node) => renderedContent.push(await render(node))));\n\treturn renderedContent.join('');\n}\n\nasync function renderer(node: JSONCanvasNode, parse: Parser) {\n\tswitch (node.type) {\n\t\tcase 'text':\n\t\t\treturn await parse(node.text);\n\t\tcase 'file':\n\t\t\treturn await fileProcessor(node, parse);\n\t\tcase 'link':\n\t\t\treturn `<a href=\"${node.url}\" target=\"_blank\" rel=\"nofollow\">${node.url}</a>`;\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n\nasync function fileProcessor(node: JSONCanvasFileNode, parse: Parser) {\n\tif (node.file.match(/\\.md$/i)) return await loadMarkdown(node.file, parse);\n\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\treturn `<img src=\"${node.file}\" alt=\"${node.file.split('/').pop()}\">`;\n\telse if (node.file.match(/\\.(mp3|wav)$/i)) return `<audio src=\"${node.file}\" controls></audio>`;\n\treturn '';\n}\n\nasync function loadMarkdown(path: string, parse: Parser) {\n\tlet parsedContent: string;\n\ttry {\n\t\tconst response = await fetch(path);\n\t\tconst result = await response.text();\n\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\tif (frontmatterMatch) parsedContent = await parse(frontmatterMatch[2]);\n\t\telse parsedContent = await parse(result);\n\t} catch {\n\t\tparsedContent = 'Failed to load content.';\n\t}\n\treturn parsedContent;\n}\n","import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tcontrolsCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleControlsCollapse: Controls['toggleCollapse'];\n}\n\nconst resetIcon =\n\t'<svg viewBox=\"-6 -6 30 30\" stroke-width=\".08\"><path d=\"m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z\" /></svg>';\nconst enterFullscreenIcon =\n\t'<svg viewBox=\"-5.28 -5.28 34.56 34.56\" fill=\"none\"><path d=\"M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15\" stroke-width=\"2.4\" stroke-linecap=\"round\"/></svg>';\nconst exitFullscreenIcon =\n\t'<svg viewBox=\"-40.32 -40.32 176.64 176.64\"><path d=\"M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z\"/></svg>';\nconst zoomInIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12m-6-6v12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst zoomOutIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Controls extends BaseModule<Options, Augmentation> {\n\tprivate _controlsPanel: HTMLDivElement | null = null;\n\tprivate _toggleCollapseBtn: HTMLButtonElement | null = null;\n\tprivate _toggleFullscreenBtn: HTMLButtonElement | null = null;\n\tprivate _zoomOutBtn: HTMLButtonElement | null = null;\n\tprivate _zoomSlider: HTMLInputElement | null = null;\n\tprivate _zoomInBtn: HTMLButtonElement | null = null;\n\tprivate _resetViewBtn: HTMLButtonElement | null = null;\n\tprivate DM: DataManager;\n\tprivate IH: InteractionHandler;\n\tprivate collapsed: boolean;\n\n\tprivate get controlsPanel() {\n\t\tif (this._controlsPanel === null) throw destroyError;\n\t\treturn this._controlsPanel;\n\t}\n\tprivate get toggleCollapseBtn() {\n\t\tif (this._toggleCollapseBtn === null) throw destroyError;\n\t\treturn this._toggleCollapseBtn;\n\t}\n\tprivate get toggleFullscreenBtn() {\n\t\tif (this._toggleFullscreenBtn === null) throw destroyError;\n\t\treturn this._toggleFullscreenBtn;\n\t}\n\tprivate get zoomOutBtn() {\n\t\tif (this._zoomOutBtn === null) throw destroyError;\n\t\treturn this._zoomOutBtn;\n\t}\n\tprivate get zoomSlider() {\n\t\tif (this._zoomSlider === null) throw destroyError;\n\t\treturn this._zoomSlider;\n\t}\n\tprivate get zoomInBtn() {\n\t\tif (this._zoomInBtn === null) throw destroyError;\n\t\treturn this._zoomInBtn;\n\t}\n\tprivate get resetViewBtn() {\n\t\tif (this._resetViewBtn === null) throw destroyError;\n\t\treturn this._resetViewBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.controlsCollapsed ?? false;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler);\n\t\tthis.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn);\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.updateSlider);\n\n\t\tthis._controlsPanel = document.createElement('div');\n\t\tthis._controlsPanel.className = 'JCV-controls';\n\t\tthis._controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\n\t\tutilities.applyStyles(this._controlsPanel, style);\n\n\t\tthis._toggleCollapseBtn = document.createElement('button');\n\t\tthis._toggleCollapseBtn.className = 'JCV-button JCV-collapse-button JCV-border-shadow-bg';\n\t\tthis._toggleCollapseBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._controlsPanel.appendChild(this._toggleCollapseBtn);\n\n\t\tconst controlsContent = document.createElement('div');\n\t\tcontrolsContent.className = 'JCV-controls-content';\n\n\t\tthis._toggleFullscreenBtn = document.createElement('button');\n\t\tthis._toggleFullscreenBtn.className = 'JCV-button';\n\t\tthis._toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t\tcontrolsContent.appendChild(this._toggleFullscreenBtn);\n\n\t\tthis._zoomOutBtn = document.createElement('button');\n\t\tthis.zoomOutBtn.className = 'JCV-button';\n\t\tthis._zoomOutBtn.innerHTML = zoomOutIcon;\n\t\tcontrolsContent.appendChild(this._zoomOutBtn);\n\n\t\tthis._zoomSlider = document.createElement('input');\n\t\tthis._zoomSlider.type = 'range';\n\t\tthis._zoomSlider.className = 'JCV-zoom-slider';\n\t\tthis._zoomSlider.min = '-30';\n\t\tthis._zoomSlider.max = '30';\n\t\tthis._zoomSlider.value = '0';\n\t\tcontrolsContent.appendChild(this._zoomSlider);\n\n\t\tthis._zoomInBtn = document.createElement('button');\n\t\tthis._zoomInBtn.className = 'JCV-button';\n\t\tthis._zoomInBtn.innerHTML = zoomInIcon;\n\t\tcontrolsContent.appendChild(this._zoomInBtn);\n\n\t\tthis._resetViewBtn = document.createElement('button');\n\t\tthis._resetViewBtn.className = 'JCV-button';\n\t\tthis._resetViewBtn.innerHTML = resetIcon;\n\t\tcontrolsContent.appendChild(this._resetViewBtn);\n\n\t\tthis._controlsPanel.appendChild(controlsContent);\n\n\t\tthis.DM.data.container.appendChild(this._controlsPanel);\n\n\t\tthis._toggleCollapseBtn.addEventListener('click', this.toggleCollapse);\n\t\tthis._zoomInBtn.addEventListener('click', this.zoomIn);\n\t\tthis._zoomOutBtn.addEventListener('click', this.zoomOut);\n\t\tthis._zoomSlider.addEventListener('input', this.slide);\n\t\tthis._resetViewBtn.addEventListener('click', this.DM.resetView);\n\t\tthis._toggleFullscreenBtn.addEventListener('click', this.toggleFullscreen);\n\n\t\tthis.augment({ toggleControlsCollapse: this.toggleCollapse });\n\t\tthis.onDispose(this.dispose);\n\t}\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateSlider();\n\t};\n\tprivate zoomIn = () => this.IH.zoom(1.3, this.DM.middleViewer());\n\tprivate zoomOut = () => this.IH.zoom(1 / 1.3, this.DM.middleViewer());\n\tprivate slide = () =>\n\t\tthis.IH.trueZoom(\n\t\t\t1.1 ** Number(this.zoomSlider.value) / this.DM.data.scale,\n\t\t\tthis.DM.middleViewer(),\n\t\t);\n\n\tprivate updateFullscreenBtn = (enter: 'enter' | 'exit') => {\n\t\tif (enter === 'enter') this.toggleFullscreenBtn.innerHTML = exitFullscreenIcon;\n\t\telse this.toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t};\n\tprivate toggleFullscreen = () => this.DM.toggleFullscreen();\n\n\tprivate updateSlider = () => {\n\t\tif (this.collapsed) return;\n\t\tthis.zoomSlider.value = String(this.scaleToSlider(this.DM.data.scale));\n\t};\n\tprivate scaleToSlider = (scale: number) => Math.log(scale) / Math.log(1.1);\n\n\tprivate dispose = () => {\n\t\tthis.toggleCollapseBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.zoomInBtn.removeEventListener('click', this.zoomIn);\n\t\tthis.zoomOutBtn.removeEventListener('click', this.zoomOut);\n\t\tthis.zoomSlider.removeEventListener('input', this.slide);\n\t\tthis.resetViewBtn.removeEventListener('click', this.DM.resetView);\n\t\tthis.toggleFullscreenBtn.removeEventListener('click', this.toggleFullscreen);\n\t\tthis.controlsPanel.remove();\n\t\tthis._controlsPanel = null;\n\t\tthis._toggleCollapseBtn = null;\n\t\tthis._zoomInBtn = null;\n\t\tthis._zoomOutBtn = null;\n\t\tthis._zoomSlider = null;\n\t\tthis._resetViewBtn = null;\n\t\tthis._toggleFullscreenBtn = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\nexport default class DebugPanel extends BaseModule {\n\tprivate _debugPanel: HTMLDivElement | null = null;\n\tprivate DM: DataManager;\n\n\tprivate get debugPanel() {\n\t\tif (!this._debugPanel) throw destroyError;\n\t\treturn this._debugPanel;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.update);\n\t\tthis._debugPanel = document.createElement('div');\n\t\tthis._debugPanel.className = 'JCV-debug-panel JCV-border-shadow-bg';\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tutilities.applyStyles(HTMLContainer, style);\n\t\tHTMLContainer.appendChild(this._debugPanel);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate update = () => {\n\t\tconst round = utilities.round;\n\t\tconst data = this.DM.data;\n\t\tthis.debugPanel.innerHTML = `<p>Scale: ${round(data.scale, 3)}</p><p>Offset: ${round(data.offsetX, 1)}, ${round(data.offsetY, 1)}</p>`;\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.debugPanel.remove();\n\t\tthis._debugPanel = null;\n\t};\n}\n","import type { BaseOptions } from '$';\nimport type { JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tminimapCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleMinimapCollapse: Minimap['toggleCollapse'];\n}\n\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Minimap extends BaseModule<Options, Augmentation> {\n\tprivate _minimapCtx: CanvasRenderingContext2D | null = null;\n\tprivate _viewportRectangle: HTMLDivElement | null = null;\n\tprivate _minimap: HTMLDivElement | null = null;\n\tprivate _minimapContainer: HTMLDivElement | null = null;\n\tprivate _toggleMinimapBtn: HTMLButtonElement | null = null;\n\tprivate minimapCache: { scale: number; centerX: number; centerY: number } = {\n\t\tscale: 1,\n\t\tcenterX: 0,\n\t\tcenterY: 0,\n\t};\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate collapsed: boolean;\n\n\tprivate get minimap() {\n\t\tif (this._minimap === null) throw destroyError;\n\t\treturn this._minimap;\n\t}\n\tprivate get minimapCtx() {\n\t\tif (this._minimapCtx === null) throw destroyError;\n\t\treturn this._minimapCtx;\n\t}\n\tprivate get viewportRectangle() {\n\t\tif (this._viewportRectangle === null) throw destroyError;\n\t\treturn this._viewportRectangle;\n\t}\n\tprivate get minimapContainer() {\n\t\tif (this._minimapContainer === null) throw destroyError;\n\t\treturn this._minimapContainer;\n\t}\n\tprivate get toggleMinimapBtn() {\n\t\tif (this._toggleMinimapBtn === null) throw destroyError;\n\t\treturn this._toggleMinimapBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.minimapCollapsed ?? false;\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.updateViewportRectangle);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\n\t\tthis._minimapContainer = document.createElement('div');\n\t\tthis._minimapContainer.className = 'JCV-minimap-container';\n\n\t\tutilities.applyStyles(this._minimapContainer, style);\n\n\t\tthis._toggleMinimapBtn = document.createElement('button');\n\t\tthis._toggleMinimapBtn.className =\n\t\t\t'JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg';\n\t\tthis._toggleMinimapBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._minimapContainer.appendChild(this._toggleMinimapBtn);\n\n\t\tthis._minimap = document.createElement('div');\n\t\tthis._minimap.className = 'JCV-minimap JCV-border-shadow-bg';\n\t\tconst minimapCanvas = document.createElement('canvas');\n\t\tminimapCanvas.className = 'JCV-minimap-canvas';\n\t\tminimapCanvas.width = 200;\n\t\tminimapCanvas.height = 150;\n\n\t\tthis._minimap.appendChild(minimapCanvas);\n\t\tthis._minimapCtx = minimapCanvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis._viewportRectangle = document.createElement('div');\n\t\tthis._viewportRectangle.className = 'JCV-viewport-rectangle';\n\t\tthis._minimap.appendChild(this._viewportRectangle);\n\t\tthis._minimapContainer.appendChild(this._minimap);\n\n\t\tthis.DM.data.container.appendChild(this._minimapContainer);\n\n\t\tthis._minimapContainer.classList.toggle('JCV-collapsed', this.collapsed);\n\n\t\tthis._toggleMinimapBtn.addEventListener('click', this.toggleCollapse);\n\t\tutilities.resizeCanvasForDPR(minimapCanvas, minimapCanvas.width, minimapCanvas.height);\n\n\t\tthis.augment({ toggleMinimapCollapse: this.toggleCollapse });\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.minimapContainer.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateViewportRectangle();\n\t};\n\n\tprivate start = () => {\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tif (!bounds) return;\n\t\tconst displayWidth = this.minimap.clientWidth;\n\t\tconst displayHeight = this.minimap.clientHeight;\n\t\tconst scaleX = displayWidth / bounds.width;\n\t\tconst scaleY = displayHeight / bounds.height;\n\t\tthis.minimapCache.scale = Math.min(scaleX, scaleY) * 0.9;\n\t\tthis.minimapCache.centerX = displayWidth / 2;\n\t\tthis.minimapCache.centerY = displayHeight / 2;\n\t\tthis.minimapCtx.clearRect(0, 0, displayWidth, displayHeight);\n\t\tthis.minimapCtx.save();\n\t\tthis.minimapCtx.translate(this.minimapCache.centerX, this.minimapCache.centerY);\n\t\tthis.minimapCtx.scale(this.minimapCache.scale, this.minimapCache.scale);\n\t\tthis.minimapCtx.translate(-bounds.centerX, -bounds.centerY);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tfor (const edge of canvasData.edges) this.drawMinimapEdge(edge);\n\t\tfor (const node of canvasData.nodes) this.drawMinimapNode(node);\n\t\tthis.minimapCtx.restore();\n\t};\n\n\tprivate drawMinimapNode = (node: JSONCanvasNode) => {\n\t\tconst colors = this.SM.getColor(node.color);\n\t\tconst radius = 25;\n\t\tthis.minimapCtx.fillStyle = colors.border;\n\t\tutilities.drawRoundRect(this.minimapCtx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.minimapCtx.fill();\n\t};\n\n\tprivate drawMinimapEdge = (edge: JSONCanvasEdge) => {\n\t\tconst canvasMap = this.DM.data.nodeMap;\n\t\tconst fromNode = canvasMap[edge.fromNode].ref;\n\t\tconst toNode = canvasMap[edge.toNode].ref;\n\t\tif (!fromNode || !toNode) return;\n\t\tconst { x: startX, y: startY } = utilities.getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = utilities.getAnchorCoord(toNode, edge.toSide);\n\t\tthis.minimapCtx.beginPath();\n\t\tthis.minimapCtx.moveTo(startX, startY);\n\t\tthis.minimapCtx.lineTo(endX, endY);\n\t\tthis.minimapCtx.strokeStyle = this.SM.getColor(edge.color).active;\n\t\tthis.minimapCtx.lineWidth = 10;\n\t\tthis.minimapCtx.stroke();\n\t};\n\n\tprivate updateViewportRectangle = () => {\n\t\tif (this.collapsed) return;\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tconst container = this.DM.data.container;\n\t\tconst scale = this.DM.data.scale;\n\t\tif (!bounds) return;\n\t\tconst viewWidth = container.clientWidth / scale;\n\t\tconst viewHeight = container.clientHeight / scale;\n\t\tconst viewportCenterX = -this.DM.data.offsetX / scale + container.clientWidth / (2 * scale);\n\t\tconst viewportCenterY =\n\t\t\t-this.DM.data.offsetY / scale + container.clientHeight / (2 * scale);\n\t\tconst viewRectX =\n\t\t\tthis.minimapCache.centerX +\n\t\t\t(viewportCenterX - viewWidth / 2 - bounds.centerX) * this.minimapCache.scale;\n\t\tconst viewRectY =\n\t\t\tthis.minimapCache.centerY +\n\t\t\t(viewportCenterY - viewHeight / 2 - bounds.centerY) * this.minimapCache.scale;\n\t\tconst viewRectWidth = viewWidth * this.minimapCache.scale;\n\t\tconst viewRectHeight = viewHeight * this.minimapCache.scale;\n\t\tthis.viewportRectangle.style.left = `${viewRectX}px`;\n\t\tthis.viewportRectangle.style.top = `${viewRectY}px`;\n\t\tthis.viewportRectangle.style.width = `${viewRectWidth}px`;\n\t\tthis.viewportRectangle.style.height = `${viewRectHeight}px`;\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.toggleMinimapBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.minimapCtx.clearRect(0, 0, this.minimap.clientWidth, this.minimap.clientHeight);\n\t\tthis.minimapContainer.remove();\n\t\tthis._minimapContainer = null;\n\t\tthis._toggleMinimapBtn = null;\n\t\tthis._viewportRectangle = null;\n\t\tthis._minimap = null;\n\t};\n}\n","import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tpreventMistouchAtStart?: boolean;\n\tmistouchPreventerBannerText?: string;\n}\n\ninterface Augmentation {\n\tstartMistouchPrevention: MistouchPreventer['startPrevention'];\n\tendMistouchPrevention: MistouchPreventer['endPrevention'];\n}\n\nexport default class MistouchPreventer extends BaseModule<Options, Augmentation> {\n\tprivate _preventionContainer: HTMLDivElement | null = null;\n\tprivate preventMt: boolean = false;\n\tprivate DM: DataManager;\n\tprivate preventMistouch: {\n\t\trecord: boolean;\n\t\tlastX: number;\n\t\tlastY: number;\n\t\tinitialX: number;\n\t\tinitialY: number;\n\t} = {\n\t\trecord: false,\n\t\tlastX: 0,\n\t\tlastY: 0,\n\t\tinitialX: 0,\n\t\tinitialY: 0,\n\t};\n\n\tprivate get preventionContainer() {\n\t\tif (this._preventionContainer === null) throw destroyError;\n\t\treturn this._preventionContainer;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\n\t\tconst preventionBanner = document.createElement('div');\n\t\tpreventionBanner.className = 'JCV-prevention-banner JCV-border-shadow-bg';\n\t\tpreventionBanner.textContent =\n\t\t\tthis.options.mistouchPreventerBannerText ?? 'Click on to unlock.';\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._preventionContainer = document.createElement('div');\n\t\tthis._preventionContainer.className =\n\t\t\t'JCV-prevention-container JCV-hidden JCV-full JCV-flex-center';\n\n\t\tutilities.applyStyles(this._preventionContainer, style);\n\t\tthis._preventionContainer.appendChild(preventionBanner);\n\t\tthis.DM.data.container.appendChild(this._preventionContainer);\n\n\t\tif (this.options.preventMistouchAtStart) this.startPrevention();\n\n\t\twindow.addEventListener('pointerdown', this.onPointerDown);\n\t\twindow.addEventListener('pointermove', this.onPointerMove);\n\t\twindow.addEventListener('pointerup', this.onPointerUp);\n\n\t\tthis.augment({\n\t\t\tstartMistouchPrevention: this.startPrevention,\n\t\t\tendMistouchPrevention: this.endPrevention,\n\t\t});\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate onPointerDown = (e: PointerEvent) => {\n\t\tconst bounds = this.DM.data.container.getBoundingClientRect();\n\t\tif (\n\t\t\te.clientX < bounds.left ||\n\t\t\te.clientX > bounds.right ||\n\t\t\te.clientY < bounds.top ||\n\t\t\te.clientY > bounds.bottom\n\t\t) {\n\t\t\tif (!this.preventMt) this.startPrevention();\n\t\t} else if (this.preventMt) {\n\t\t\tthis.preventMistouch.initialX = e.clientX;\n\t\t\tthis.preventMistouch.initialY = e.clientY;\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t\tthis.preventMistouch.record = true;\n\t\t}\n\t};\n\n\tprivate onPointerMove = (e: PointerEvent) => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t}\n\t};\n\n\tprivate onPointerUp = () => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.record = false;\n\t\t\tif (\n\t\t\t\tMath.abs(this.preventMistouch.lastX - this.preventMistouch.initialX) +\n\t\t\t\t\tMath.abs(this.preventMistouch.lastY - this.preventMistouch.initialY) <\n\t\t\t\t5\n\t\t\t)\n\t\t\t\tthis.endPrevention();\n\t\t}\n\t};\n\n\tstartPrevention = () => {\n\t\tthis.preventionContainer.classList.remove('JCV-hidden');\n\t\tthis.DM.data.container.classList.add('JCV-numb');\n\t\tthis.preventMt = true;\n\t};\n\n\tendPrevention = () => {\n\t\tthis.preventMt = false;\n\t\tthis.preventionContainer.classList.add('JCV-hidden');\n\t\tsetTimeout(() => this.DM.data.container.classList.remove('JCV-numb'), 50); // minimum delay to prevent triggering undesired button touch\n\t};\n\n\tprivate dispose = () => {\n\t\twindow.removeEventListener('pointerdown', this.onPointerDown);\n\t\twindow.removeEventListener('pointermove', this.onPointerMove);\n\t\twindow.removeEventListener('pointerup', this.onPointerUp);\n\t\tthis.preventionContainer.remove();\n\t\tthis._preventionContainer = null;\n\t};\n}\n","export { default as Controls } from '@/modules/Controls';\nexport { default as DebugPanel } from '@/modules/DebugPanel';\nexport { default as Minimap } from '@/modules/Minimap';\nexport { default as MistouchPreventer } from '@/modules/MistouchPreventer';\nexport { default as JSONCanvasViewer } from '$';\nimport type { JSONCanvas } from '@repo/shared';\nimport purify from 'dompurify';\nimport { marked } from 'marked';\n\nexport async function parser(markdown: string) {\n\treturn purify.sanitize(await marked(markdown));\n}\n\nexport async function fetchCanvas(path: `${string}.canvas` | `${string}.json`) {\n\treturn (await fetch(path).then((res) => res.json())) as JSONCanvas;\n}\n"],"names":["BaseModule","constructor","container","options","onStart","onDispose","onRestart","augment","this","subscribe","utilities","round","roundedNum","digits","factor","Math","resizeCanvasForDPR","canvas","width","height","dpr","window","devicePixelRatio","ctx","getContext","Error","setTransform","scale","applyStyles","styleString","style","document","createElement","innerHTML","appendChild","drawRoundRect","x","y","radius","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","getAnchorCoord","node","side","midX","midY","makeHook","reverse","async","result","args","items","Array","from","subs","callback","Set","add","unsubscribe","delete","destroyError","DataManager","onToggleFullscreen","data","canvasData","nodes","edges","nodeMap","edgeMap","canvasBaseDir","nodeBounds","maxX","maxY","minX","minY","centerX","centerY","offsetX","offsetY","super","viewerContainer","firstElementChild","remove","realContainer","shadowed","attachShadow","mode","extraCSS","classList","resetView","toggleFullscreen","start","dispose","Object","assign","processBaseDir","attachmentDir","calculateNodeBounds","forEach","item","ref","box","getNodeBox","id","type","fileName","file","split","pop","startsWith","userDefinedAttachment","attachments","noAttachmentRelocation","edge","getEdgeBox","baseDir","lastChar","slice","left","top","right","bottom","fromNode","to","toNode","fromAnchor","fromSide","toAnchor","toSide","strictBox","min","max","_min","margin","log2","Infinity","option","fullscreenElement","exitFullscreen","requestFullscreen","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","newScale","initialView","middleViewer","StyleManager","theme","onChangeTheme","definedColors","light","hue","saturation","lightness","dark","namedColors","dots","text","background","shadow","border","colorCache","colors","colorObject","entries","key","value","namedColorsDict","definedColorsDict","color","parseColor","console","warn","changeTheme","hslProcessor","active","card","alpha","toHslString","rgbToHsl","parseRgb","parseHex","parseHsl","getColor","colorIndex","getNamedColor","name","get","setProperty","Controller","animationId","resizeAnimationId","DM","SM","resizeObserver","perFrame","lastScale","lastOffsets","lastResizeCenter","onResize","onRefresh","ResizeObserver","onResizeCallback","refresh","observe","requestAnimationFrame","draw","center","cancelAnimationFrame","disconnect","fileRegex","markdown","image","audio","video","supportedTypes","OverlayManager","_overlaysLayer","overlays","selectedId","aborted","eventListeners","parse","componentDict","content","parsedContentWrapper","parsedContent","textContent","response","fetch","frontmatterMatch","match","err","error","link","iframe","src","sandbox","className","loading","controls","img","overlaysLayer","onInteractionStart","onInteractionEnd","onNodeActive","onNodeLosesActive","parser","updateOverlays","themeChanged","components","nodeComponents","restart","InteractionHandler","onClick","select","renderOverlays","clearOverlays","overlayMatcher","createOverlay","url","values","overlay","setOverlayColor","previousId","previous","current","nodeItem","onLoseActive","onActive","transform","element","constructOverlay","contentWrapper","clickLayer","overlayBorder","onBeforeUnmount","onEnd","addEventListener","removeEventListener","pointeract","coordinateOutput","lubricator","pan","zoom","drag","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","Lubricator","OM","stopInteract","startInteract","panToCoords","zoomToScale","on","onPan","onZoom","onTrueClick","stop","event","truePan","deltaX","deltaY","trueZoom","_factor","origin","canvasCoords","C2C","dispatch","containerX","containerY","e","target","isUIControl","findNodeId","closest","ele","parentElement","Renderer","_canvas","zoomInOptimize","lastDrawnScale","lastDrawnViewport","timeout","lastCallTime","controller","redraw","optimizeDPR","offsetWidth","offsetHeight","currentViewport","getCurrentViewport","zoomInOptimization","trueRedraw","clearTimeout","now","Date","isInside","setTimeout","fakeRedraw","clearRect","save","drawGridDots","translate","isOutside","drawFile","drawGroup","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","drawLabelBar","label","textColor","barHeight","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","fill","fillText","drawNodeBackground","globalAlpha","NODE_BORDER_WIDTH","strokeStyle","lineWidth","stroke","gac","startX","startY","endX","endY","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","abs","PADDING","val","actualGap","floor","arc","PI","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","length","sqrt","unitX","unitY","leftX","leftY","rightX","rightY","internalModules","JSONCanvasViewer","allModules","IO","started","disposed","modules","Container","Class","bind","provide","useFactory","Module","load","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","entry","isIntersecting","aug","descriptors","getOwnPropertyDescriptors","defineProperties","firstChild","unbindAll","renderToString","render","path","loadMarkdown","fileProcessor","renderer","basePath","renderedContent","Promise","all","map","push","join","enterFullscreenIcon","Controls","_controlsPanel","_toggleCollapseBtn","_toggleFullscreenBtn","_zoomOutBtn","_zoomSlider","_zoomInBtn","_resetViewBtn","IH","collapsed","controlsPanel","toggleCollapseBtn","toggleFullscreenBtn","zoomOutBtn","zoomSlider","zoomInBtn","resetViewBtn","controlsCollapsed","updateFullscreenBtn","updateSlider","toggle","controlsContent","toggleCollapse","zoomIn","zoomOut","slide","toggleControlsCollapse","Number","enter","String","scaleToSlider","log","DebugPanel","_debugPanel","debugPanel","update","HTMLContainer","Minimap","_minimapCtx","_viewportRectangle","_minimap","_minimapContainer","_toggleMinimapBtn","minimapCache","minimap","minimapCtx","viewportRectangle","minimapContainer","toggleMinimapBtn","minimapCollapsed","updateViewportRectangle","minimapCanvas","toggleMinimapCollapse","displayWidth","displayHeight","drawMinimapEdge","drawMinimapNode","canvasMap","viewportCenterX","viewportCenterY","viewRectX","viewRectY","viewRectWidth","viewRectHeight","MistouchPreventer","_preventionContainer","preventMt","preventMistouch","record","lastX","lastY","initialX","initialY","preventionContainer","preventionBanner","mistouchPreventerBannerText","preventMistouchAtStart","startPrevention","onPointerDown","onPointerMove","onPointerUp","startMistouchPrevention","endMistouchPrevention","endPrevention","getBoundingClientRect","clientX","clientY","purify","sanitize","marked","fetchCanvas","then","res","json"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["export {\n\tdefault as JSONCanvasViewer,\n\ttype JSONCanvasViewerInterface,\n\ttype AllOptions as Options,\n} from '$';\nexport { default as renderToString } from '@/utilities/renderToString.ts';\nexport {\n\ttype GeneralModule,\n\ttype GeneralModuleCtor,\n\ttype BaseArgs,\n\tBaseModule,\n} from '$/BaseModule';\nexport type { BaseOptions } from '$';\nexport { default as Controls } from '@/modules/Controls';\nexport { default as DebugPanel } from '@/modules/DebugPanel';\nexport { default as Minimap } from '@/modules/Minimap';\nexport { default as MistouchPreventer } from '@/modules/MistouchPreventer';\nexport { default as canvasUtils, type Hook } from '$/utilities';\nexport { default as fetchCanvas } from '@/utilities/fetchCanvas';\nexport { default as parser } from '@/utilities/parser';\nexport type * from '@repo/shared';\n\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\nexport const internal = {\n\tController,\n\tDataManager,\n\tInteractionHandler,\n\tOverlayManager,\n\tRenderer,\n\tStyleManager,\n};\n\n// must import env.d.ts, otherwise dts bundler will throw at '*.scss?inline'\nimport './env.d.ts';\n"],"names":["internal","Controller","DataManager","InteractionHandler","OverlayManager","Renderer","StyleManager"],"mappings":"gwBA4BO,MAAMA,EAAW,CACvBC,aACAC,cACAC,qBACAC,iBACAC,WACAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseModule.js","sources":["../../src/kernel/BaseModule.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { General, GeneralObject, ModuleInput as MI, Orchestratable } from '$/types';\nimport type utilities from '$/utilities';\nimport type { Container } from '@needle-di/core';\n\ntype Hook = ReturnType<typeof utilities.makeHook>;\n\nexport type GeneralModuleCtor = typeof BaseModule<General, General>;\nexport type GeneralModule = BaseModule<General, General>;\n\nexport type ModuleInputCtor = Array<GeneralModuleCtor>;\nexport type ModuleInput = MI<GeneralModuleCtor>;\nexport type Options<M extends ModuleInput> = Orchestratable<M, 'options'>;\nexport type Augmentation<M extends ModuleInput> = Orchestratable<M, '_Augmentation'>;\n\nexport type BaseArgs = ConstructorParameters<GeneralModuleCtor>;\n\nexport class BaseModule<O extends BaseOptions = BaseOptions, A extends GeneralObject = {}> {\n\t// https://github.com/timocov/dts-bundle-generator/issues/360\n\tdeclare private static readonly _BaseModuleBrand: unique symbol; // Nominal marker\n\tdeclare _Augmentation: A;\n\tonStart: Hook['subscribe'];\n\tonRestart: Hook['subscribe'];\n\tonDispose: Hook['subscribe'];\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tonStart: Hook,\n\t\tonDispose: Hook,\n\t\tonRestart: Hook,\n\t\tprotected augment: (aug: A) => void,\n\t) {\n\t\tthis.options = options as O;\n\t\tthis.onStart = onStart.subscribe;\n\t\tthis.onDispose = onDispose.subscribe;\n\t\tthis.onRestart = onRestart.subscribe;\n\t}\n\toptions: O;\n}\n"],"names":["BaseModule","constructor","container","options","onStart","onDispose","onRestart","augment","this","subscribe"],"mappings":"AAiBO,MAAMA,EAOZ,WAAAC,CACWC,EACVC,EACAC,EACAC,EACAC,EACUC,GALAC,KAAAN,UAAAA,EAKAM,KAAAD,QAAAA,EAEVC,KAAKL,QAAUA,EACfK,KAAKJ,QAAUA,EAAQK,UACvBD,KAAKH,UAAYA,EAAUI,UAC3BD,KAAKF,UAAYA,EAAUG,SAC5B,CAfAL,QACAE,UACAD,UAcAF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import s from"./DataManager.js";import t from"./StyleManager.js";import i from"./utilities.js";class a extends e{animationId=null;resizeAnimationId=null;DM;SM;resizeObserver;perFrame={lastScale:1,lastOffsets:{x:0,y:0}};lastResizeCenter={x:null,y:null};onResize=i.makeHook();onRefresh=i.makeHook();constructor(...e){super(...e),this.DM=this.container.get(s),this.SM=this.container.get(t),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({refresh:this.refresh,onRefresh:this.onRefresh,onResize:this.onResize}),this.onStart(this.start),this.onRestart(this.refresh),this.onDispose(this.dispose)}start=()=>{this.resizeObserver.observe(this.DM.data.container),this.animationId=requestAnimationFrame(this.draw)};draw=()=>{this.perFrame.lastScale===this.DM.data.scale&&this.perFrame.lastOffsets.x===this.DM.data.offsetX&&this.perFrame.lastOffsets.y===this.DM.data.offsetY||this.refresh(),this.animationId=requestAnimationFrame(this.draw)};refresh=()=>{this.perFrame={lastScale:this.DM.data.scale,lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY}},this.onRefresh()};onResizeCallback=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{const e=this.DM.middleViewer();this.lastResizeCenter.x&&this.lastResizeCenter.y&&(this.DM.data.offsetX=this.DM.data.offsetX+e.x-this.lastResizeCenter.x,this.DM.data.offsetY=this.DM.data.offsetY+e.y-this.lastResizeCenter.y),this.lastResizeCenter.x=e.x,this.lastResizeCenter.y=e.y,this.onResize(e.width,e.height),this.refresh()})};dispose=()=>{this.animationId&&cancelAnimationFrame(this.animationId),this.resizeAnimationId&&cancelAnimationFrame(this.resizeAnimationId),this.resizeObserver.disconnect()}}export{a as default};
|
|
2
|
+
//# sourceMappingURL=Controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Controller.js","sources":["../../src/kernel/Controller.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\n\ninterface Augmentation {\n\trefresh: Controller['refresh'];\n\tonRefresh: Controller['onRefresh'];\n\tonResize: Controller['onResize'];\n}\n\nexport default class Controller extends BaseModule<BaseOptions, Augmentation> {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate perFrame: {\n\t\tlastScale: number;\n\t\tlastOffsets: { x: number; y: number };\n\t} = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\tonResize = utilities.makeHook<[number, number]>();\n\tonRefresh = utilities.makeHook();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tthis.resizeObserver = new ResizeObserver(this.onResizeCallback);\n\t\tthis.SM.onChangeTheme.subscribe(this.refresh);\n\t\tthis.augment({\n\t\t\trefresh: this.refresh,\n\t\t\tonRefresh: this.onRefresh,\n\t\t\tonResize: this.onResize,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.refresh);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.resizeObserver.observe(this.DM.data.container);\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate draw = () => {\n\t\tif (\n\t\t\tthis.perFrame.lastScale !== this.DM.data.scale ||\n\t\t\tthis.perFrame.lastOffsets.x !== this.DM.data.offsetX ||\n\t\t\tthis.perFrame.lastOffsets.y !== this.DM.data.offsetY\n\t\t)\n\t\t\tthis.refresh();\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\trefresh = () => {\n\t\tthis.perFrame = {\n\t\t\tlastScale: this.DM.data.scale,\n\t\t\tlastOffsets: { x: this.DM.data.offsetX, y: this.DM.data.offsetY },\n\t\t};\n\t\tthis.onRefresh();\n\t};\n\n\tprivate onResizeCallback = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\n\tprivate dispose = () => {\n\t\tif (this.animationId) cancelAnimationFrame(this.animationId);\n\t\tif (this.resizeAnimationId) cancelAnimationFrame(this.resizeAnimationId);\n\t\tthis.resizeObserver.disconnect();\n\t};\n}\n"],"names":["Controller","BaseModule","animationId","resizeAnimationId","DM","SM","resizeObserver","perFrame","lastScale","lastOffsets","x","y","lastResizeCenter","onResize","utilities","makeHook","onRefresh","constructor","args","super","this","container","get","DataManager","StyleManager","ResizeObserver","onResizeCallback","onChangeTheme","subscribe","refresh","augment","onStart","start","onRestart","onDispose","dispose","observe","data","requestAnimationFrame","draw","scale","offsetX","offsetY","center","middleViewer","width","height","cancelAnimationFrame","disconnect"],"mappings":"4IAYA,MAAqBA,UAAmBC,EAC/BC,YAA6B,KAC7BC,kBAAmC,KACnCC,GACAC,GACAC,eACAC,SAGJ,CACHC,UAAW,EACXC,YAAa,CAAEC,EAAG,EAAGC,EAAG,IAEjBC,iBAGJ,CACHF,EAAG,KACHC,EAAG,MAGJE,SAAWC,EAAUC,WACrBC,UAAYF,EAAUC,WAEtB,WAAAE,IAAeC,GACdC,SAASD,GACTE,KAAKhB,GAAKgB,KAAKC,UAAUC,IAAIC,GAC7BH,KAAKf,GAAKe,KAAKC,UAAUC,IAAIE,GAC7BJ,KAAKd,eAAiB,IAAImB,eAAeL,KAAKM,kBAC9CN,KAAKf,GAAGsB,cAAcC,UAAUR,KAAKS,SACrCT,KAAKU,QAAQ,CACZD,QAAST,KAAKS,QACdb,UAAWI,KAAKJ,UAChBH,SAAUO,KAAKP,WAEhBO,KAAKW,QAAQX,KAAKY,OAClBZ,KAAKa,UAAUb,KAAKS,SACpBT,KAAKc,UAAUd,KAAKe,QACrB,CAEQH,MAAQ,KACfZ,KAAKd,eAAe8B,QAAQhB,KAAKhB,GAAGiC,KAAKhB,WACzCD,KAAKlB,YAAcoC,sBAAsBlB,KAAKmB,OAGvCA,KAAO,KAEbnB,KAAKb,SAASC,YAAcY,KAAKhB,GAAGiC,KAAKG,OACzCpB,KAAKb,SAASE,YAAYC,IAAMU,KAAKhB,GAAGiC,KAAKI,SAC7CrB,KAAKb,SAASE,YAAYE,IAAMS,KAAKhB,GAAGiC,KAAKK,SAE7CtB,KAAKS,UACNT,KAAKlB,YAAcoC,sBAAsBlB,KAAKmB,OAG/CV,QAAU,KACTT,KAAKb,SAAW,CACfC,UAAWY,KAAKhB,GAAGiC,KAAKG,MACxB/B,YAAa,CAAEC,EAAGU,KAAKhB,GAAGiC,KAAKI,QAAS9B,EAAGS,KAAKhB,GAAGiC,KAAKK,UAEzDtB,KAAKJ,aAGEU,iBAAmB,KAC1BN,KAAKjB,kBAAoBmC,sBAAsB,KAC9C,MAAMK,EAASvB,KAAKhB,GAAGwC,eACnBxB,KAAKR,iBAAiBF,GAAKU,KAAKR,iBAAiBD,IACpDS,KAAKhB,GAAGiC,KAAKI,QAAUrB,KAAKhB,GAAGiC,KAAKI,QAAUE,EAAOjC,EAAIU,KAAKR,iBAAiBF,EAC/EU,KAAKhB,GAAGiC,KAAKK,QAAUtB,KAAKhB,GAAGiC,KAAKK,QAAUC,EAAOhC,EAAIS,KAAKR,iBAAiBD,GAEhFS,KAAKR,iBAAiBF,EAAIiC,EAAOjC,EACjCU,KAAKR,iBAAiBD,EAAIgC,EAAOhC,EACjCS,KAAKP,SAAS8B,EAAOE,MAAOF,EAAOG,QACnC1B,KAAKS,aAICM,QAAU,KACbf,KAAKlB,aAAa6C,qBAAqB3B,KAAKlB,aAC5CkB,KAAKjB,mBAAmB4C,qBAAqB3B,KAAKjB,mBACtDiB,KAAKd,eAAe0C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"./BaseModule.js";import e from"./styles.scss.js";import s from"./utilities.js";class a extends t{onToggleFullscreen=s.makeHook();data={canvasData:{nodes:[],edges:[]},nodeMap:{},edgeMap:{},canvasBaseDir:"./",nodeBounds:{maxX:0,maxY:0,minX:0,minY:0,width:0,height:0,centerX:0,centerY:0},offsetX:0,offsetY:0,scale:1,container:document.createElement("div")};constructor(...t){super(...t);const a=this.options.container;for(;a.firstElementChild;)a.firstElementChild.remove();a.innerHTML="";const i=this.options.shadowed?a.attachShadow({mode:"open"}):a;s.applyStyles(i,e+this.options.extraCSS),this.data.container.classList.add("JSON-Canvas-Viewer"),i.appendChild(this.data.container),this.augment({resetView:this.resetView,toggleFullscreen:this.toggleFullscreen,onToggleFullscreen:this.onToggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{const t=Object.assign({nodes:[],edges:[]},this.options.canvas);Object.assign(this.data,{canvasData:t,nodeMap:{},edgeMap:{},canvasBaseDir:this.processBaseDir(this.options.attachmentDir),nodeBounds:this.calculateNodeBounds(t),offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(t=>{const e={ref:t,box:this.getNodeBox(t)};if(this.data.nodeMap[t.id]=e,"file"===t.type){const s=t.file.split("/").pop()??"";if(e.fileName=s,!t.file.startsWith("http://")&&!t.file.startsWith("https://")){const e=this.options.attachments?.[s];e?t.file=e:this.options.noAttachmentRelocation||(t.file=this.data.canvasBaseDir+s)}}}),this.data.canvasData.edges.forEach(t=>{this.data.edgeMap[t.id]={ref:t,box:this.getEdgeBox(t)}}),this.resetView()};processBaseDir=t=>{if(!t)return"./";const e=t?.slice(-1);return"/"===e?t:`${t}/`};getNodeBox=t=>({left:t.x,top:"file"===t.type||"group"===t.type?t.y-40:t.y,right:t.width+t.x,bottom:t.y+t.height});getEdgeBox=t=>{const e=this.data.nodeMap,a=e[t.fromNode].ref,i=e[t.toNode].ref,o=s.getAnchorCoord(a,t.fromSide),n=s.getAnchorCoord(i,t.toSide),h=Math.min(o.x,n.x),r=Math.min(o.y,n.y),c=Math.max(o.x,n.x),d=Math.max(o.y,n.y),l=c-h,f=d-r,m=Math.min(l,f),g=0===m?1:m,p=Math.max(l,f),u=10*Math.log2(p/g);return{left:h-u,top:r-u,right:c+u,bottom:d+u}};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,n=i-s;return{minX:e,minY:s,maxX:a,maxY:i,width:o,height:n,centerX:e+o/2,centerY:s+n/2}}toggleFullscreen=async t=>{document.fullscreenElement||t&&"enter"!==t?!document.fullscreenElement||t&&"exit"!==t||(await document.exitFullscreen(),this.onToggleFullscreen("exit")):(await this.data.container.requestFullscreen(),this.onToggleFullscreen("enter"))};resetView=()=>{const t=this.data.nodeBounds,e=this.data.container;if(!t||!e)return;const s=t.width+200,a=t.height+200,i=e.clientWidth,o=e.clientHeight,n=i/s,h=o/a,r=Math.round(1e3*Math.min(n,h))/1e3,c={scale:r,offsetX:i/2-t.centerX*r,offsetY:o/2-t.centerY*r};this.data.offsetX=c.offsetX,this.data.offsetY=c.offsetY,this.data.scale=c.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()}}export{a as default};
|
|
2
|
+
//# sourceMappingURL=DataManager.js.map
|