json-canvas-viewer 4.2.1 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chimp.js +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kernel/BaseModule.js +1 -1
- package/dist/kernel/BaseModule.js.map +1 -1
- package/dist/kernel/Controller.d.ts +2 -2
- package/dist/kernel/Controller.js +1 -1
- package/dist/kernel/Controller.js.map +1 -1
- package/dist/kernel/DataManager.d.ts +1 -5
- package/dist/kernel/DataManager.js +1 -1
- package/dist/kernel/DataManager.js.map +1 -1
- package/dist/kernel/InteractionHandler.d.ts +1 -1
- package/dist/kernel/InteractionHandler.js +1 -1
- package/dist/kernel/InteractionHandler.js.map +1 -1
- package/dist/kernel/OverlayManager.d.ts +4 -4
- package/dist/kernel/OverlayManager.js +1 -1
- package/dist/kernel/OverlayManager.js.map +1 -1
- package/dist/kernel/Renderer.d.ts +1 -8
- package/dist/kernel/Renderer.js +2 -2
- package/dist/kernel/Renderer.js.map +1 -1
- package/dist/kernel/StyleManager.d.ts +1 -1
- package/dist/kernel/StyleManager.js +1 -1
- package/dist/kernel/StyleManager.js.map +1 -1
- package/dist/kernel/index.d.ts +3 -4
- package/dist/kernel/index.js +1 -1
- package/dist/kernel/index.js.map +1 -1
- package/dist/kernel/types.d.ts +1 -1
- package/dist/kernel/utilities.d.ts +6 -6
- package/dist/kernel/utilities.js +1 -1
- package/dist/kernel/utilities.js.map +1 -1
- package/dist/modules/Controls/index.js.map +1 -1
- package/dist/modules/DebugPanel/index.js.map +1 -1
- package/dist/modules/Minimap/index.js.map +1 -1
- package/dist/modules/MistouchPreventer/index.js.map +1 -1
- package/dist/utilities/fetch-canvas.js.map +1 -1
- package/dist/utilities/parser.js.map +1 -1
- package/dist/utilities/render-to-string.d.ts +0 -1
- package/dist/utilities/render-to-string.js +1 -1
- package/dist/utilities/render-to-string.js.map +1 -1
- package/package.json +1 -1
package/dist/chimp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{parseHex as e,parseHsl as t,parseRgb as n,rgbToHsl as r,toHslString as i}from"@ahmedsemih/color-fns";import{Click as a,Drag as o,Lubricator as s,MultitouchPanZoom as c,Pointeract as l,PreventDefault as u,WheelPanZoom as d,lubricatorDragPreset as f,lubricatorPanPreset as p,lubricatorZoomPreset as m}from"pointeract";import{Container as h}from"@needle-di/core";import g from"dompurify";import{marked as _}from"marked";var v=class{onStart;onRestart;onDispose;constructor(e,t,n,r,i,a){this.container=e,this.augment=a,this.options=t,this.onStart=n.subscribe,this.onDispose=r.subscribe,this.onRestart=i.subscribe}options},y=`.JSON-Canvas-Viewer {
|
|
1
|
+
import{parseHex as e,parseHsl as t,parseRgb as n,rgbToHsl as r,toHslString as i}from"@ahmedsemih/color-fns";import{Click as a,Drag as o,Lubricator as s,MultitouchPanZoom as c,Pointeract as l,PreventDefault as u,WheelPanZoom as d,lubricatorDragPreset as f,lubricatorPanPreset as p,lubricatorZoomPreset as m}from"pointeract";import{Container as h}from"@needle-di/core";import g from"dompurify";import{marked as _}from"marked";var v=class{container;augment;onStart;onRestart;onDispose;constructor(e,t,n,r,i,a){this.container=e,this.augment=a,this.options=t,this.onStart=n.subscribe,this.onDispose=r.subscribe,this.onRestart=i.subscribe}options},y=`.JSON-Canvas-Viewer {
|
|
2
2
|
--contentTransition: color 200ms, opacity 200ms, text-shadow 200ms, fill 200ms;
|
|
3
3
|
--containerTransition:
|
|
4
4
|
background 200ms, opacity 200ms, box-shadow 200ms, border 200ms, filter 200ms,
|
|
@@ -281,7 +281,7 @@ pre .JSON-Canvas-Viewer .JCV-markdown-content code {
|
|
|
281
281
|
background: rgba(255, 255, 255, 0.12);
|
|
282
282
|
font-weight: bold;
|
|
283
283
|
}
|
|
284
|
-
`;const b=Error(`[JSONCanvasViewer] Resource hasn't been set up or has been disposed.`);function x(e,t){let n=document.createElement(`style`);n.innerHTML=t,e.appendChild(n)}function S(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.lineTo(t+r-a,n),e.quadraticCurveTo(t+r,n,t+r,n+a),e.lineTo(t+r,n+i-a),e.quadraticCurveTo(t+r,n+i,t+r-a,n+i),e.lineTo(t+a,n+i),e.quadraticCurveTo(t,n+i,t,n+i-a),e.lineTo(t,n+a),e.quadraticCurveTo(t,n,t+a,n),e.closePath()}function C(e,t){let n=e.x+e.width/2,r=e.y+e.height/2;switch(t){case`top`:return{x:n,y:e.y};case`bottom`:return{x:n,y:e.y+e.height};case`left`:return{x:e.x,y:r};case`right`:return{x:e.x+e.width,y:r};default:return{x:n,y:r}}}function w(e,t,n){let r=window.devicePixelRatio??1,i=e.getContext(`2d`);if(!i)throw Error(`[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.`);e.width=Math.round(t*r),e.height=Math.round(n*r),i.setTransform(1,0,0,1,0,0),i.scale(r,r)}function T(e,t){let n=10**t;return Math.round(e*n)/n}function E(e=!1,t=!1){let n=t?async(...t)=>{if(e){let e=[...n.subs].reverse();for(let n of e)await n(...t)}else for(let e of n.subs)await e(...t)}:(...t)=>{if(e){let e=[...n.subs].reverse();for(let n of e)n(...t)}else for(let e of n.subs)e(...t)};return n.subs=new Set,n.subscribe=e=>{n.subs.add(e)},n.unsubscribe=e=>{n.subs.delete(e)},n}var D=class extends v{onToggleFullscreen=E();data={canvasBaseDir:`./`,canvasData:{edges:[],nodes:[]},container:document.createElement(`div`),edgeMap:{},nodeBounds:{centerX:0,centerY:0,height:0,maxX:0,maxY:0,minX:0,minY:0,width:0},nodeMap:{},offsetX:0,offsetY:0,scale:1};constructor(...e){super(...e);let t=this.options.container;for(;t.firstElementChild;)t.firstElementChild.remove();t.innerHTML=``;let n=this.options.shadowed?t.attachShadow({mode:`open`}):t;x(n,y+this.options.extraCSS),this.data.container.classList.add(`JSON-Canvas-Viewer`),n.appendChild(this.data.container),this.augment({onToggleFullscreen:this.onToggleFullscreen,resetView:this.resetView,toggleFullscreen:this.toggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{let e={edges:[],nodes:[],...this.options.canvas};Object.assign(this.data,{canvasBaseDir:this.processBaseDir(this.options.attachmentDir),canvasData:e,edgeMap:{},nodeBounds:this.calculateNodeBounds(e),nodeMap:{},offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(e=>{let t={box:this.getNodeBox(e),ref:e};if(this.data.nodeMap[e.id]=t,e.type===`file`){let n=e.file.split(`/`).pop()??``;if(t.fileName=n,!e.file.startsWith(`http://`)&&!e.file.startsWith(`https://`)){let t=this.options.attachments?.[n];t?e.file=t:this.options.noAttachmentRelocation||(e.file=this.data.canvasBaseDir+n)}}}),this.data.canvasData.edges.forEach(e=>{this.data.edgeMap[e.id]={box:this.getEdgeBox(e),ref:e}}),this.resetView()};processBaseDir=e=>e?e?.slice(-1)===`/`?e:`${e}/`:`./`;getNodeBox=e=>({bottom:e.y+e.height,left:e.x,right:e.width+e.x,top:e.type===`file`||e.type===`group`?e.y-40:e.y});getEdgeBox=e=>{let t=this.data.nodeMap,n=t[e.fromNode].ref,r=t[e.toNode].ref,i=C(n,e.fromSide),a=C(r,e.toSide),o={bottom:Math.max(i.y,a.y),left:Math.min(i.x,a.x),right:Math.max(i.x,a.x),top:Math.min(i.y,a.y)},s=o.right-o.left,c=o.bottom-o.top,l=Math.min(s,c),u=Math.log2(Math.max(s,c)/(l===0?1:l))*10;return{bottom:o.bottom+u,left:o.left-u,right:o.right+u,top:o.top-u}};calculateNodeBounds(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;e.nodes.forEach(e=>{t=Math.min(t,e.x),n=Math.min(n,e.y),r=Math.max(r,e.x+e.width),i=Math.max(i,e.y+e.height)});let a=r-t,o=i-n;return{centerX:t+a/2,centerY:n+o/2,height:o,maxX:r,maxY:i,minX:t,minY:n,width:a}}toggleFullscreen=async e=>{!document.fullscreenElement&&(!e||e===`enter`)?(await this.data.container.requestFullscreen(),this.onToggleFullscreen(`enter`)):document.fullscreenElement&&(!e||e===`exit`)&&(await document.exitFullscreen(),this.onToggleFullscreen(`exit`))};resetView=()=>{let e=this.data.nodeBounds,t=this.data.container;if(!e||!t)return;let n=e.width+200,r=e.height+200,i=t.clientWidth,a=t.clientHeight,o=i/n,s=a/r,c=Math.round(Math.min(o,s)*1e3)/1e3,l=e.centerX,u=e.centerY,d={offsetX:i/2-l*c,offsetY:a/2-u*c,scale:c};this.data.offsetX=d.offsetX,this.data.offsetY=d.offsetY,this.data.scale=d.scale};middleViewer=()=>{let e=this.data.container;return{height:e.clientHeight,width:e.clientWidth,x:e.clientWidth/2,y:e.clientHeight/2}};dispose=()=>{this.data.container.remove()}},O=class extends v{theme=`light`;onChangeTheme=E();definedColors={dark:{0:{hue:0,lightness:40,saturation:0},1:{hue:358,lightness:65,saturation:100},2:{hue:23,lightness:63,saturation:86},3:{hue:39,lightness:70,saturation:91},4:{hue:153,lightness:45,saturation:80},5:{hue:217,lightness:62,saturation:100},6:{hue:259,lightness:75,saturation:100}},light:{0:{hue:0,lightness:72,saturation:0},1:{hue:358,lightness:55,saturation:81},2:{hue:19,lightness:58,saturation:87},3:{hue:41,lightness:52,saturation:79},4:{hue:150,lightness:37,saturation:100},5:{hue:221,lightness:59,saturation:100},6:{hue:257,lightness:62,saturation:81}}};namedColors={dark:{background:`rgb(30, 30, 30)`,"background-secondary":`rgb(37, 37, 40)`,border:`hsla(0, 0%, 30%, 0.7)`,dots:`hsla(0, 0%, 40%, 0.3)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.2)`,text:`rgb(242, 242, 242)`},light:{background:`rgb(250, 250, 250)`,"background-secondary":`rgb(255, 255, 255)`,border:`hsla(0, 0%, 82%, 0.7)`,dots:`hsla(0, 0%, 72%, 0.4)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.1)`,text:`rgb(30, 30, 30)`}};colorCache={dark:{},light:{}};constructor(...e){super(...e);let t=this.options.colors;t&&[`light`,`dark`].forEach(e=>{if(!(e in t))return;let n=t[e];n&&Object.entries(n).forEach(([t,n])=>{if(!n)return;let r=this.namedColors[e],i=this.definedColors[e];if(t in r)r[t]=n;else if(t in i){let e=this.parseColor(n);if(!e){console.warn(`[JSON Canvas Viewer] Color ${n} unsupported.`);return}i[t]=e}})}),this.changeTheme(this.options.theme??`light`),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=e=>{let{hue:t,saturation:n,lightness:r}=e,a=this.theme===`dark`?{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:{hue:t,lightness:r/3,saturation:n/3},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`}:{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:t===0?{hue:t,lightness:100,saturation:n}:{hue:t,lightness:90,saturation:n*.4},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`};return{active:i(a.active),background:i(a.background),border:i(a.border),card:i(a.card),text:a.text}};parseColor=i=>{if(i.startsWith(`rgb`))return r(n(i));if(i.startsWith(`#`))return r(e(i));if(i.startsWith(`hsl`))return t(i)};getColor=(t=`0`)=>{let n=this.theme,i;if(this.colorCache[n][t])return this.colorCache[n][t];i=t in this.definedColors[n]?this.hslProcessor(this.definedColors[n][t]):this.hslProcessor(r(e(t)));let a={...i,"border-width":t===`0`?`1px`:`2px`};return this.colorCache[n][t]=a,a};getNamedColor=e=>this.namedColors[this.theme][e];changeTheme=e=>{this.theme=e??(this.theme===`dark`?`light`:`dark`);let t=this.container.get(D).data.container;Object.entries(this.namedColors[this.theme]).forEach(([e,n])=>{t.style.setProperty(`--${e}`,n)}),this.onChangeTheme(this.theme)}},k=class extends v{animationId;resizeAnimationId;DM;SM;resizeObserver;perFrame={lastOffsets:{x:0,y:0},lastScale:1};lastResizeCenter={};onResize=E();onRefresh=E();constructor(...e){super(...e),this.DM=this.container.get(D),this.SM=this.container.get(O),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({onRefresh:this.onRefresh,onResize:this.onResize,refresh:this.refresh}),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={lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY},lastScale:this.DM.data.scale},this.onRefresh()};onResizeCallback=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{let 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()}};const A={audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,markdown:/\.(md|mdx|markdown|txt)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},j=[`markdown`,`image`,`audio`,`video`];var M=class extends v{_overlaysLayer=document.createElement(`div`);overlays={};selectedId;aborted=!1;eventListeners={};DM;SM;parse;componentDict={audio:({container:e,content:t})=>{let n=document.createElement(`audio`);n.className=`JCV-audio`,n.src=t,n.controls=!0,e.appendChild(n)},image:({container:e,content:t})=>{let n=document.createElement(`img`);n.className=`JCV-img`,n.src=t,n.loading=`lazy`,e.appendChild(n)},link:({container:e,content:t})=>{let n=document.createElement(`iframe`);n.src=t,n.sandbox=`allow-scripts allow-same-origin`,n.className=`JCV-link-iframe`,n.loading=`lazy`,e.appendChild(n)},markdown:async({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.textContent=`Loading...`,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n);let r;try{let e=await(await fetch(t)).text(),n=/^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(e);r=await this.parse(n?n[2]:e)}catch(e){console.error(`[JSON Canvas Viewer] Failed to load markdown:`,e),r=`Failed to load content.`}n.innerHTML=r},text:({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.innerHTML=t,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n)},video:({container:e,content:t})=>{let n=document.createElement(`video`);n.className=`JCV-video`,n.src=t,n.controls=!0,e.appendChild(n)}};get overlaysLayer(){if(!this._overlaysLayer)throw b;return this._overlaysLayer}onInteractionStart=E();onInteractionEnd=E();onNodeActive=E();onNodeLosesActive=E();constructor(...e){super(...e),this.parse=this.options.parser??(e=>e),this.DM=this.container.get(D),this.SM=this.container.get(O),this.container.get(k).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);let t=this.options.nodeComponents;t&&Object.assign(this.componentDict,t),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(N).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{let e=async e=>{switch(e.type){case`text`:this.createOverlay(e,await this.parse(e.text),`text`);break;case`file`:for(let t of j)if(e.file.match(A[t])){this.createOverlay(e,e.file,t);break}break;case`link`:this.createOverlay(e,e.url,`link`);break}};Object.values(this.DM.data.nodeMap).forEach(async t=>{await e(t.ref)})};themeChanged=()=>{Object.values(this.overlays).forEach(e=>{let t=this.DM.data.nodeMap[e.id].ref,n=this.SM.getColor(t.color);this.setOverlayColor(e,n)})};select=e=>{let t=this.selectedId,n=t?this.overlays[t]:void 0,r=e?this.overlays[e]:void 0;if(n&&t){n.classList.remove(`JCV-active`);let e=this.DM.data.nodeMap[t];this.onNodeLosesActive(e.ref),e.onLoseActive?.()}if(r&&e){r.classList.add(`JCV-active`),this.onInteractionStart();let t=this.DM.data.nodeMap[e];this.onNodeActive(t.ref),t.onActive?.()}else this.onInteractionEnd();this.selectedId=e};updateOverlays=()=>{let e=this.DM.data;this.overlaysLayer.style.transform=`translate(${e.offsetX}px, ${e.offsetY}px) scale(${e.scale})`};createOverlay=(...e)=>{if(this.aborted)return;let t=e[0],n=this.overlays[t.id];if(!n){if(n=this.constructOverlay(...e),this.aborted)return;this.overlaysLayer.appendChild(n),this.overlays[t.id]=n,n.style.left=`${t.x}px`,n.style.top=`${t.y}px`,n.style.width=`${t.width}px`,n.style.height=`${t.height}px`}};constructOverlay=(...e)=>{let t=e[0],n=document.createElement(`div`);n.classList.add(`JCV-overlay-container`),n.id=t.id,this.setOverlayColor(n,this.SM.getColor(t.color));let r=document.createElement(`div`);r.classList.add(`JCV-content`),n.appendChild(r);let i=document.createElement(`div`);i.className=`JCV-click-layer`,n.appendChild(i);let a=document.createElement(`div`);a.className=`JCV-overlay-border`,n.appendChild(a);let o=this.DM.data.nodeMap[t.id];o.onActive=E(),o.onLoseActive=E(),o.onBeforeUnmount=E(),this.componentDict[e[2]]({container:r,content:e[1],node:e[0],onActive:o.onActive,onBeforeUnmount:o.onBeforeUnmount,onLoseActive:o.onLoseActive});let s=()=>{t.id===this.selectedId&&this.onInteractionStart()},c=()=>{t.id===this.selectedId&&this.onInteractionEnd()};return n.addEventListener(`pointerenter`,s),n.addEventListener(`pointerleave`,c),n.addEventListener(`touchstart`,s),n.addEventListener(`touchend`,c),this.eventListeners[t.id]=[s,c],n};setOverlayColor=(e,t)=>{Object.entries(t).forEach(([t,n])=>{e.style.setProperty(`--overlay-${t}`,n)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([e,t])=>{if(this.DM.data.nodeMap[e].onBeforeUnmount?.(),this.eventListeners[e]){let n=this.eventListeners[e][0],r=this.eventListeners[e][1];if(!n||!r)throw b;t.removeEventListener(`pointerenter`,n),t.removeEventListener(`pointerleave`,r),t.removeEventListener(`touchstart`,n),t.removeEventListener(`touchend`,r),this.eventListeners[e][0]=void 0,this.eventListeners[e][1]=void 0}t.remove(),delete this.overlays[e]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=void 0}},N=class extends v{pointeract;DM;onClick=E();constructor(...e){super(...e),this.DM=this.container.get(D);let t=Object.assign(this.options.pointeract??{},{coordinateOutput:`relative`,element:this.DM.data.container,lubricator:{drag:f,pan:p,zoom:m}});this.pointeract=new l(t,[a,o,d,u,c,s]);let n=this.container.get(M);n.onInteractionStart.subscribe(this.stopInteract),n.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=e=>{this.truePan({x:e.deltaX,y:e.deltaY})};onZoom=e=>{this.trueZoom(e.factor,e)};trueZoom=(e,t)=>{let n=Math.max(Math.min(this.DM.data.scale*e,20),.05);if(n===this.DM.data.scale)return;let r=n/this.DM.data.scale,i=this.C2C(t);this.DM.data.offsetX=t.x-i.x*r,this.DM.data.offsetY=t.y-i.y*r,this.DM.data.scale=n};truePan=({x:e,y:t})=>{this.DM.data.offsetX+=e,this.DM.data.offsetY+=t};zoom=(e,t)=>{this.pointeract.dispatch(`zoom`,{factor:e,...t})};pan=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e,deltaY:t})};zoomToScale=(e,t)=>{let n=e/this.DM.data.scale;this.pointeract.dispatch(`zoom`,{factor:n,...t})};panToCoords=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e-this.DM.data.offsetX,deltaY:t-this.DM.data.offsetY})};C2C=({x:e,y:t})=>({x:e-this.DM.data.offsetX,y:t-this.DM.data.offsetY});onTrueClick=e=>{let t=e.target?e.target:void 0;if(this.isUIControl(t))return;let n=this.findNodeId(t);this.onClick(n)};isUIControl=e=>e?e.closest(`.controls`)||e.closest(`button`)||e.closest(`input`):!1;findNodeId=e=>{if(!e)return;let t=e;for(;(!t.id||t.id===``)&&t.parentElement;)t=t.parentElement;if(!(t.id===`overlays`||!t.id||t.id===``))return t.id};dispose=()=>this.pointeract.dispose()},P=`.JSON-Canvas-Viewer > .JCV-controls {
|
|
284
|
+
`;const b=Error(`[JSONCanvasViewer] Resource hasn't been set up or has been disposed.`);function x(e,t){let n=document.createElement(`style`);n.innerHTML=t,e.appendChild(n)}function S(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.lineTo(t+r-a,n),e.quadraticCurveTo(t+r,n,t+r,n+a),e.lineTo(t+r,n+i-a),e.quadraticCurveTo(t+r,n+i,t+r-a,n+i),e.lineTo(t+a,n+i),e.quadraticCurveTo(t,n+i,t,n+i-a),e.lineTo(t,n+a),e.quadraticCurveTo(t,n,t+a,n),e.closePath()}function C(e,t){let n=e.x+e.width/2,r=e.y+e.height/2;switch(t){case`top`:return{x:n,y:e.y};case`bottom`:return{x:n,y:e.y+e.height};case`left`:return{x:e.x,y:r};case`right`:return{x:e.x+e.width,y:r};default:return{x:n,y:r}}}function w(e,t,n){let r=window.devicePixelRatio??1,i=e.getContext(`2d`);if(!i)throw Error(`[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.`);e.width=Math.round(t*r),e.height=Math.round(n*r),i.setTransform(1,0,0,1,0,0),i.scale(r,r)}function T(e,t){let n=10**t;return Math.round(e*n)/n}function E(e=!1){let t=(...n)=>{let r=t.subs.values().toArray();for(let t of e?r:r.toReversed())t(...n)};return t.subs=new Set,t.subscribe=e=>(t.subs.add(e),()=>t.unsubscribe(e)),t.unsubscribe=e=>{t.subs.delete(e)},t}var D=class extends v{onToggleFullscreen=E();data={canvasData:{edges:[],nodes:[]},container:document.createElement(`div`),edgeMap:{},nodeBounds:{centerX:0,centerY:0,height:0,maxX:0,maxY:0,minX:0,minY:0,width:0},nodeMap:{},offsetX:0,offsetY:0,scale:1};constructor(...e){super(...e);let t=this.options.container;for(;t.firstElementChild;)t.firstElementChild.remove();t.innerHTML=``;let n=this.options.shadowed?t.attachShadow({mode:`open`}):t;x(n,y),this.data.container.classList.add(`JSON-Canvas-Viewer`),n.appendChild(this.data.container),this.augment({onToggleFullscreen:this.onToggleFullscreen,resetView:this.resetView,toggleFullscreen:this.toggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{let e={edges:[],nodes:[],...this.options.canvas};Object.assign(this.data,{canvasData:e,edgeMap:{},nodeBounds:this.calculateNodeBounds(e),nodeMap:{},offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(e=>{let t={box:this.getNodeBox(e),ref:e};if(this.data.nodeMap[e.id]=t,e.type===`file`){let n=e.file,r=n.split(`/`).pop()??``,i=r.lastIndexOf(`?`);if(t.fileName=i===-1?r:r.slice(0,i),!e.file.includes(`://`)){let t=this.options.attachments?.[n];t&&(e.file=t)}}}),this.data.canvasData.edges.forEach(e=>{this.data.edgeMap[e.id]={box:this.getEdgeBox(e),ref:e}}),this.resetView()};processBaseDir=e=>e?e?.slice(-1)===`/`?e:`${e}/`:`./`;getNodeBox=e=>({bottom:e.y+e.height,left:e.x,right:e.width+e.x,top:e.type===`file`||e.type===`group`?e.y-40:e.y});getEdgeBox=e=>{let t=this.data.nodeMap,n=t[e.fromNode].ref,r=t[e.toNode].ref,i=C(n,e.fromSide),a=C(r,e.toSide),o={bottom:Math.max(i.y,a.y),left:Math.min(i.x,a.x),right:Math.max(i.x,a.x),top:Math.min(i.y,a.y)},s=o.right-o.left,c=o.bottom-o.top,l=Math.min(s,c),u=Math.log2(Math.max(s,c)/(l===0?1:l))*10;return{bottom:o.bottom+u,left:o.left-u,right:o.right+u,top:o.top-u}};calculateNodeBounds(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;e.nodes.forEach(e=>{t=Math.min(t,e.x),n=Math.min(n,e.y),r=Math.max(r,e.x+e.width),i=Math.max(i,e.y+e.height)});let a=r-t,o=i-n;return{centerX:t+a/2,centerY:n+o/2,height:o,maxX:r,maxY:i,minX:t,minY:n,width:a}}toggleFullscreen=async e=>{!document.fullscreenElement&&(!e||e===`enter`)?(await this.data.container.requestFullscreen(),this.onToggleFullscreen(`enter`)):document.fullscreenElement&&(!e||e===`exit`)&&(await document.exitFullscreen(),this.onToggleFullscreen(`exit`))};resetView=()=>{let e=this.data.nodeBounds,t=this.data.container;if(!e||!t)return;let n=e.width+200,r=e.height+200,i=t.clientWidth,a=t.clientHeight,o=i/n,s=a/r,c=Math.round(Math.min(o,s)*1e3)/1e3,l=e.centerX,u=e.centerY,d={offsetX:i/2-l*c,offsetY:a/2-u*c,scale:c};this.data.offsetX=d.offsetX,this.data.offsetY=d.offsetY,this.data.scale=d.scale};middleViewer=()=>{let e=this.data.container;return{height:e.clientHeight,width:e.clientWidth,x:e.clientWidth/2,y:e.clientHeight/2}};dispose=()=>{this.data.container.remove()}},O=class extends v{theme=`light`;onChangeTheme=E();definedColors={dark:{0:{hue:0,lightness:40,saturation:0},1:{hue:358,lightness:65,saturation:100},2:{hue:23,lightness:63,saturation:86},3:{hue:39,lightness:70,saturation:91},4:{hue:153,lightness:45,saturation:80},5:{hue:217,lightness:62,saturation:100},6:{hue:259,lightness:75,saturation:100}},light:{0:{hue:0,lightness:72,saturation:0},1:{hue:358,lightness:55,saturation:81},2:{hue:19,lightness:58,saturation:87},3:{hue:41,lightness:52,saturation:79},4:{hue:150,lightness:37,saturation:100},5:{hue:221,lightness:59,saturation:100},6:{hue:257,lightness:62,saturation:81}}};namedColors={dark:{background:`rgb(30, 30, 30)`,"background-secondary":`rgb(37, 37, 40)`,border:`hsla(0, 0%, 30%, 0.7)`,dots:`hsla(0, 0%, 40%, 0.3)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.2)`,text:`rgb(242, 242, 242)`},light:{background:`rgb(250, 250, 250)`,"background-secondary":`rgb(255, 255, 255)`,border:`hsla(0, 0%, 82%, 0.7)`,dots:`hsla(0, 0%, 72%, 0.4)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.1)`,text:`rgb(30, 30, 30)`}};colorCache={dark:{},light:{}};constructor(...e){super(...e);let t=this.options.colors;t&&[`light`,`dark`].forEach(e=>{if(!(e in t))return;let n=t[e];n&&Object.entries(n).forEach(([t,n])=>{if(!n)return;let r=this.namedColors[e],i=this.definedColors[e];if(t in r)r[t]=n;else if(t in i){let e=this.parseColor(n);if(!e){console.warn(`[JSON Canvas Viewer] Color ${n} unsupported.`);return}i[t]=e}})}),this.changeTheme(this.options.theme??`light`),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=e=>{let{hue:t,saturation:n,lightness:r}=e,a=this.theme===`dark`?{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:{hue:t,lightness:r/3,saturation:n/3},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`}:{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:t===0?{hue:t,lightness:100,saturation:n}:{hue:t,lightness:90,saturation:n*.4},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`};return{active:i(a.active),background:i(a.background),border:i(a.border),card:i(a.card),text:a.text}};parseColor=i=>{if(i.startsWith(`rgb`))return r(n(i));if(i.startsWith(`#`))return r(e(i));if(i.startsWith(`hsl`))return t(i)};getColor=(t=`0`)=>{let n=this.theme,i;if(this.colorCache[n][t])return this.colorCache[n][t];i=t in this.definedColors[n]?this.hslProcessor(this.definedColors[n][t]):this.hslProcessor(r(e(t)));let a={...i,"border-width":t===`0`?`1px`:`2px`};return this.colorCache[n][t]=a,a};getNamedColor=e=>this.namedColors[this.theme][e];changeTheme=e=>{this.theme=e??(this.theme===`dark`?`light`:`dark`);let t=this.container.get(D).data.container;Object.entries(this.namedColors[this.theme]).forEach(([e,n])=>{t.style.setProperty(`--${e}`,n)}),this.onChangeTheme(this.theme)}},k=class extends v{animationId;resizeAnimationId;DM;SM;resizeObserver;perFrame={lastOffsets:{x:0,y:0},lastScale:1};lastResizeCenter={};onResize=E();onRefresh=E();constructor(...e){super(...e),this.DM=this.container.get(D),this.SM=this.container.get(O),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({onRefresh:this.onRefresh,onResize:this.onResize,refresh:this.refresh}),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={lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY},lastScale:this.DM.data.scale},this.onRefresh()};onResizeCallback=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{let 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()}};const A={audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,markdown:/\.(md|mdx|markdown|txt)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},j=[`markdown`,`image`,`audio`,`video`];var M=class extends v{_overlaysLayer=document.createElement(`div`);overlays={};selectedId;aborted=!1;eventListeners={};DM;SM;parse;componentDict={audio:({container:e,content:t})=>{let n=document.createElement(`audio`);n.className=`JCV-audio`,n.src=t,n.controls=!0,e.appendChild(n)},image:({container:e,content:t})=>{let n=document.createElement(`img`);n.className=`JCV-img`,n.src=t,n.loading=`lazy`,e.appendChild(n)},link:({container:e,content:t})=>{let n=document.createElement(`iframe`);n.src=t,n.sandbox=`allow-scripts allow-same-origin`,n.className=`JCV-link-iframe`,n.loading=`lazy`,e.appendChild(n)},markdown:async({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.textContent=`Loading...`,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n);let r;try{let e=await(await fetch(t)).text(),n=/^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(e);r=await this.parse(n?n[2]:e)}catch(e){console.error(`[JSON Canvas Viewer] Failed to load markdown:`,e),r=`Failed to load content.`}n.innerHTML=r},text:({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.innerHTML=t,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n)},video:({container:e,content:t})=>{let n=document.createElement(`video`);n.className=`JCV-video`,n.src=t,n.controls=!0,e.appendChild(n)}};get overlaysLayer(){if(!this._overlaysLayer)throw b;return this._overlaysLayer}onInteractionStart=E();onInteractionEnd=E();onNodeActive=E();onNodeLosesActive=E();constructor(...e){super(...e),this.parse=this.options.parser??(e=>e),this.DM=this.container.get(D),this.SM=this.container.get(O),this.container.get(k).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);let t=this.options.nodeComponents;t&&Object.assign(this.componentDict,t),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(N).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{let e=async({ref:e,fileName:t})=>{switch(e.type){case`text`:this.createOverlay(e,await this.parse(e.text),`text`);break;case`file`:for(let n of j)if(t?.match(A[n])){this.createOverlay(e,e.file,n);break}break;case`link`:this.createOverlay(e,e.url,`link`);break}};Object.values(this.DM.data.nodeMap).forEach(async t=>await e(t))};themeChanged=()=>{Object.values(this.overlays).forEach(e=>{let t=this.DM.data.nodeMap[e.id].ref,n=this.SM.getColor(t.color);this.setOverlayColor(e,n)})};select=e=>{let t=this.selectedId,n=t?this.overlays[t]:void 0,r=e?this.overlays[e]:void 0;if(n&&t){n.classList.remove(`JCV-active`);let e=this.DM.data.nodeMap[t];this.onNodeLosesActive(e.ref),e.onLoseActive?.()}if(r&&e){r.classList.add(`JCV-active`),this.onInteractionStart();let t=this.DM.data.nodeMap[e];this.onNodeActive(t.ref),t.onActive?.()}else this.onInteractionEnd();this.selectedId=e};updateOverlays=()=>{let e=this.DM.data;this.overlaysLayer.style.transform=`translate(${e.offsetX}px, ${e.offsetY}px) scale(${e.scale})`};createOverlay=(...e)=>{if(this.aborted)return;let t=e[0],n=this.overlays[t.id];if(!n){if(n=this.constructOverlay(...e),this.aborted)return;this.overlaysLayer.appendChild(n),this.overlays[t.id]=n,n.style.left=`${t.x}px`,n.style.top=`${t.y}px`,n.style.width=`${t.width}px`,n.style.height=`${t.height}px`}};constructOverlay=(...e)=>{let t=e[0],n=document.createElement(`div`);n.classList.add(`JCV-overlay-container`),n.id=t.id,this.setOverlayColor(n,this.SM.getColor(t.color));let r=document.createElement(`div`);r.classList.add(`JCV-content`),n.appendChild(r);let i=document.createElement(`div`);i.className=`JCV-click-layer`,n.appendChild(i);let a=document.createElement(`div`);a.className=`JCV-overlay-border`,n.appendChild(a);let o=this.DM.data.nodeMap[t.id];o.onActive=E(),o.onLoseActive=E(),o.onBeforeUnmount=E(),this.componentDict[e[2]]({container:r,content:e[1],node:e[0],onActive:o.onActive,onBeforeUnmount:o.onBeforeUnmount,onLoseActive:o.onLoseActive});let s=()=>{t.id===this.selectedId&&this.onInteractionStart()},c=()=>{t.id===this.selectedId&&this.onInteractionEnd()};return n.addEventListener(`pointerenter`,s),n.addEventListener(`pointerleave`,c),n.addEventListener(`touchstart`,s),n.addEventListener(`touchend`,c),this.eventListeners[t.id]=[s,c],n};setOverlayColor=(e,t)=>{Object.entries(t).forEach(([t,n])=>{e.style.setProperty(`--overlay-${t}`,n)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([e,t])=>{if(this.DM.data.nodeMap[e].onBeforeUnmount?.(),this.eventListeners[e]){let n=this.eventListeners[e][0],r=this.eventListeners[e][1];if(!n||!r)throw b;t.removeEventListener(`pointerenter`,n),t.removeEventListener(`pointerleave`,r),t.removeEventListener(`touchstart`,n),t.removeEventListener(`touchend`,r),this.eventListeners[e][0]=void 0,this.eventListeners[e][1]=void 0}t.remove(),delete this.overlays[e]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=void 0}},N=class extends v{pointeract;DM;onClick=E();constructor(...e){super(...e),this.DM=this.container.get(D);let t=Object.assign(this.options.pointeract??{},{coordinateOutput:`relative`,element:this.DM.data.container,lubricator:{drag:f,pan:p,zoom:m}});this.pointeract=new l(t,[a,o,d,u,c,s]);let n=this.container.get(M);n.onInteractionStart.subscribe(this.stopInteract),n.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=e=>{this.truePan({x:e.deltaX,y:e.deltaY})};onZoom=e=>{this.trueZoom(e.factor,e)};trueZoom=(e,t)=>{let n=Math.max(Math.min(this.DM.data.scale*e,20),.05);if(n===this.DM.data.scale)return;let r=n/this.DM.data.scale,i=this.C2C(t);this.DM.data.offsetX=t.x-i.x*r,this.DM.data.offsetY=t.y-i.y*r,this.DM.data.scale=n};truePan=({x:e,y:t})=>{this.DM.data.offsetX+=e,this.DM.data.offsetY+=t};zoom=(e,t)=>{this.pointeract.dispatch(`zoom`,{factor:e,...t})};pan=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e,deltaY:t})};zoomToScale=(e,t)=>{let n=e/this.DM.data.scale;this.pointeract.dispatch(`zoom`,{factor:n,...t})};panToCoords=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e-this.DM.data.offsetX,deltaY:t-this.DM.data.offsetY})};C2C=({x:e,y:t})=>({x:e-this.DM.data.offsetX,y:t-this.DM.data.offsetY});onTrueClick=e=>{let t=e.target?e.target:void 0;if(this.isUIControl(t))return;let n=this.findNodeId(t);this.onClick(n)};isUIControl=e=>e?e.closest(`.controls`)||e.closest(`button`)||e.closest(`input`):!1;findNodeId=e=>{if(!e)return;let t=e;for(;(!t.id||t.id===``)&&t.parentElement;)t=t.parentElement;if(!(t.id===`overlays`||!t.id||t.id===``))return t.id};dispose=()=>this.pointeract.dispose()},P=`.JSON-Canvas-Viewer > .JCV-controls {
|
|
285
285
|
position: absolute;
|
|
286
286
|
top: 10px;
|
|
287
287
|
right: 10px;
|
|
@@ -392,5 +392,5 @@ pre .JSON-Canvas-Viewer .JCV-markdown-content code {
|
|
|
392
392
|
line-height: calc(17px + 0.3vw);
|
|
393
393
|
text-align: center;
|
|
394
394
|
}
|
|
395
|
-
`,H=class extends v{_preventionContainer;preventMt=!1;DM;preventMistouch={initialX:0,initialY:0,lastX:0,lastY:0,record:!1};get preventionContainer(){if(!this._preventionContainer)throw b;return this._preventionContainer}constructor(...e){super(...e);let t=document.createElement(`div`);t.className=`JCV-prevention-banner JCV-border-shadow-bg`,t.textContent=this.options.mistouchPreventerBannerText??`Click on to unlock.`,this.DM=this.container.get(D),this._preventionContainer=document.createElement(`div`),this._preventionContainer.className=`JCV-prevention-container JCV-hidden JCV-full JCV-flex-center`,x(this._preventionContainer,V),this._preventionContainer.appendChild(t),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({endMistouchPrevention:this.endPrevention,startMistouchPrevention:this.startPrevention}),this.onDispose(this.dispose)}onPointerDown=e=>{let t=this.DM.data.container.getBoundingClientRect();e.clientX<t.left||e.clientX>t.right||e.clientY<t.top||e.clientY>t.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=e.clientX,this.preventMistouch.initialY=e.clientY,this.preventMistouch.lastX=e.clientX,this.preventMistouch.lastY=e.clientY,this.preventMistouch.record=!0)};onPointerMove=e=>{this.preventMistouch.record&&(this.preventMistouch.lastX=e.clientX,this.preventMistouch.lastY=e.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=void 0}};const U=[D,O,k,M,N,class extends v{_canvas;ctx;DM;SM;
|
|
396
|
-
`),h=0;for(let e of m){let t=this.ctx.measureText(e).width;t>h&&(h=t)}let g=h+16,_=m.length*17+6;this.ctx.fillStyle=l,this.ctx.beginPath(),S(this.ctx,f-g/2,p-_/2-2,g,_,4),this.ctx.fill(),this.ctx.fillStyle=u,this.ctx.textAlign=`center`,this.ctx.textBaseline=`middle`;for(let e=0;e<m.length;e++){let t=(e-(m.length-1)/2)*17;this.ctx.fillText(m[e],f,p-2+t)}this.ctx.textAlign=`left`,this.ctx.textBaseline=`alphabetic`};getControlPoints=(e,t,n,r,i,a)=>{let o=n-e,s=r-t,c=((e,t,n)=>Math.max(t,Math.min(n,e)))((Math.min(Math.abs(o),Math.abs(s))+.3*Math.max(Math.abs(o),Math.abs(s)))*.5,60,300),l=e,u=t,d=n,f=r;switch(i){case`top`:u=t-c;break;case`bottom`:u=t+c;break;case`left`:l=e-c;break;case`right`:l=e+c;break}switch(a){case`top`:f=r-c;break;case`bottom`:f=r+c;break;case`left`:d=n-c;break;case`right`:d=n+c;break}return[l,u,d,f]};drawGridDots=(e,t,n)=>{let r=10*2**-Math.floor(Math.log2(e))*e,i=this.canvas.width,a=this.canvas.height,o=t%r,s=n%r;this.ctx.fillStyle=this.SM.getNamedColor(`dots`);for(let e=o;e<=i;e+=r)for(let t=s;t<=a;t+=r)this.ctx.beginPath(),this.ctx.arc(e,t,1,0,2*Math.PI),this.ctx.fill()};drawCurvedPath=(e,t,n,r,i,a,o,s,c)=>{this.ctx.beginPath(),this.ctx.moveTo(e,t),this.ctx.bezierCurveTo(i,a,o,s,n,r),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(e,t,n,r,i)=>{let a=e-n,o=t-r,s=Math.sqrt(a*a+o*o);if(s===0)return;let c=a/s,l=o/s,u=e-c*12-l*4,d=t-l*12+c*4,f=e-c*12+l*4,p=t-l*12-c*4;this.ctx.beginPath(),this.ctx.fillStyle=i,this.ctx.moveTo(e,t),this.ctx.lineTo(u,d),this.ctx.lineTo(f,p),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.
|
|
395
|
+
`,H=class extends v{_preventionContainer;preventMt=!1;DM;preventMistouch={initialX:0,initialY:0,lastX:0,lastY:0,record:!1};get preventionContainer(){if(!this._preventionContainer)throw b;return this._preventionContainer}constructor(...e){super(...e);let t=document.createElement(`div`);t.className=`JCV-prevention-banner JCV-border-shadow-bg`,t.textContent=this.options.mistouchPreventerBannerText??`Click on to unlock.`,this.DM=this.container.get(D),this._preventionContainer=document.createElement(`div`),this._preventionContainer.className=`JCV-prevention-container JCV-hidden JCV-full JCV-flex-center`,x(this._preventionContainer,V),this._preventionContainer.appendChild(t),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({endMistouchPrevention:this.endPrevention,startMistouchPrevention:this.startPrevention}),this.onDispose(this.dispose)}onPointerDown=e=>{let t=this.DM.data.container.getBoundingClientRect();e.clientX<t.left||e.clientX>t.right||e.clientY<t.top||e.clientY>t.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=e.clientX,this.preventMistouch.initialY=e.clientY,this.preventMistouch.lastX=e.clientX,this.preventMistouch.lastY=e.clientY,this.preventMistouch.record=!0)};onPointerMove=e=>{this.preventMistouch.record&&(this.preventMistouch.lastX=e.clientX,this.preventMistouch.lastY=e.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=void 0}};const U=[D,O,k,M,N,class extends v{_canvas;ctx;DM;SM;get canvas(){if(!this._canvas)throw b;return this._canvas}constructor(...e){super(...e);let t=this.container.get(k);this.SM=this.container.get(O),t.onRefresh.subscribe(this.redraw),t.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(D),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=()=>{let e=this.DM.data.container;w(this.canvas,e.offsetWidth,e.offsetHeight)};redraw=()=>{let e=this.DM.data.offsetX,t=this.DM.data.offsetY,n=this.DM.data.scale,r=this.getCurrentViewport(e,t,n);this.canvas.style.transform=``,this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.drawGridDots(n,e,t),this.ctx.translate(e,t),this.ctx.scale(n,n),Object.values(this.DM.data.nodeMap).forEach(e=>{if(this.isOutside(e.box,r))return;let t=e.ref;t.type===`file`?this.drawFile(e):t.type===`group`&&this.drawGroup(t,n)}),Object.values(this.DM.data.edgeMap).forEach(e=>{this.isOutside(e.box,r)||this.drawEdge(e)}),this.ctx.restore()};isInside=(e,t)=>e.left>t.left&&e.top>t.top&&e.right<t.right&&e.bottom<t.bottom;isOutside=(e,t)=>e.right<t.left||e.bottom<t.top||e.left>t.right||e.top>t.bottom;getCurrentViewport=(e,t,n)=>{let r=-e/n,i=-t/n,a=this.DM.data.container,o=r+a.clientWidth/n;return{bottom:i+a.clientHeight/n,left:r,right:o,top:i}};drawLabelBar=(e,t,n,r,i,a)=>{let o=30*a,s=6*a,c=8*a,l=16*a,u=6*a;this.ctx.save(),this.ctx.translate(e,t),this.ctx.scale(1/a,1/a),this.ctx.font=`${l}px 'Inter', sans-serif`;let d=this.ctx.measureText(n).width+2*u;this.ctx.translate(0,-o-c),this.ctx.fillStyle=r,this.ctx.beginPath(),this.ctx.moveTo(s,0),this.ctx.lineTo(d-s,0),this.ctx.quadraticCurveTo(d,0,d,s),this.ctx.lineTo(d,o-s),this.ctx.quadraticCurveTo(d,o,d-s,o),this.ctx.lineTo(s,o),this.ctx.quadraticCurveTo(0,o,0,o-s),this.ctx.lineTo(0,s),this.ctx.quadraticCurveTo(0,0,s,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=i,this.ctx.fillText(n,u,o*.65),this.ctx.restore()};drawNodeBackground=e=>{let t=this.SM.getColor(e.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=t.background,S(this.ctx,e.x+1,e.y+1,e.width-2,e.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=t.border,this.ctx.lineWidth=2,S(this.ctx,e.x,e.y,e.width,e.height,12),this.ctx.stroke()};drawGroup=(e,t)=>{if(this.drawNodeBackground(e),e.label){let n=this.SM.getColor(e.color);this.drawLabelBar(e.x,e.y,e.label,n.active,n.text,t)}};drawFile=e=>{this.ctx.fillStyle=this.SM.getColor().text;let t=e.ref;this.ctx.font=`16px sans-serif`,this.ctx.fillText(e.fileName??``,t.x+5,t.y-10)};drawEdge=e=>{let t=e.ref,n=this.DM.data.nodeMap[t.fromNode].ref,r=this.DM.data.nodeMap[t.toNode].ref,{x:i,y:a}=C(n,t.fromSide),{x:o,y:s}=C(r,t.toSide),c=this.SM.getColor(t.color),l,u,d,f;e.controlPoints?[l,u,d,f]=e.controlPoints:([l,u,d,f]=this.getControlPoints(i,a,o,s,t.fromSide,t.toSide),e.controlPoints=[l,u,d,f]),this.drawCurvedPath(i,a,o,s,l,u,d,f,c.active),this.drawArrowhead(o,s,d,f,c.active),t.label&&this.drawEdgeLabel(i,a,o,s,l,u,d,f,t.label,c.active,c.text)};drawEdgeLabel=(e,t,n,r,i,a,o,s,c,l,u)=>{let d=.5,f=(1-d)**3*e+3*(1-d)**2*d*i+3*(1-d)*d*d*o+d**3*n,p=(1-d)**3*t+3*(1-d)**2*d*a+3*(1-d)*d*d*s+d**3*r;this.ctx.font=`18px sans-serif`;let m=c.split(`
|
|
396
|
+
`),h=0;for(let e of m){let t=this.ctx.measureText(e).width;t>h&&(h=t)}let g=h+16,_=m.length*17+6;this.ctx.fillStyle=l,this.ctx.beginPath(),S(this.ctx,f-g/2,p-_/2-2,g,_,4),this.ctx.fill(),this.ctx.fillStyle=u,this.ctx.textAlign=`center`,this.ctx.textBaseline=`middle`;for(let e=0;e<m.length;e++){let t=(e-(m.length-1)/2)*17;this.ctx.fillText(m[e],f,p-2+t)}this.ctx.textAlign=`left`,this.ctx.textBaseline=`alphabetic`};getControlPoints=(e,t,n,r,i,a)=>{let o=n-e,s=r-t,c=((e,t,n)=>Math.max(t,Math.min(n,e)))((Math.min(Math.abs(o),Math.abs(s))+.3*Math.max(Math.abs(o),Math.abs(s)))*.5,60,300),l=e,u=t,d=n,f=r;switch(i){case`top`:u=t-c;break;case`bottom`:u=t+c;break;case`left`:l=e-c;break;case`right`:l=e+c;break}switch(a){case`top`:f=r-c;break;case`bottom`:f=r+c;break;case`left`:d=n-c;break;case`right`:d=n+c;break}return[l,u,d,f]};drawGridDots=(e,t,n)=>{let r=10*2**-Math.floor(Math.log2(e))*e,i=this.canvas.width,a=this.canvas.height,o=t%r,s=n%r;this.ctx.fillStyle=this.SM.getNamedColor(`dots`);for(let e=o;e<=i;e+=r)for(let t=s;t<=a;t+=r)this.ctx.beginPath(),this.ctx.arc(e,t,1,0,2*Math.PI),this.ctx.fill()};drawCurvedPath=(e,t,n,r,i,a,o,s,c)=>{this.ctx.beginPath(),this.ctx.moveTo(e,t),this.ctx.bezierCurveTo(i,a,o,s,n,r),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(e,t,n,r,i)=>{let a=e-n,o=t-r,s=Math.sqrt(a*a+o*o);if(s===0)return;let c=a/s,l=o/s,u=e-c*12-l*4,d=t-l*12+c*4,f=e-c*12+l*4,p=t-l*12-c*4;this.ctx.beginPath(),this.ctx.fillStyle=i,this.ctx.moveTo(e,t),this.ctx.lineTo(u,d),this.ctx.lineTo(f,p),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.canvas.remove(),this._canvas=void 0}}];var W=class{allModules;IO;started=!1;disposed=!1;options;container;onDispose=E(!0);onStart=E();onRestart=E();constructor(e,t){this.container=new h,this.options=e;let n=e=>{this.container.bind({provide:e,useFactory:()=>new e(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})};this.allModules=[...U,...t??[]],this.allModules.forEach(n),this.allModules.forEach(e=>{this.container.get(e)});let r=this.options.loading??`normal`;r===`normal`?this.load():r===`lazy`&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{rootMargin:`50px`,threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=e=>{e.forEach(e=>{if(e.isIntersecting){this.load(),this.IO?.disconnect(),this.IO=void 0;return}})};augment=e=>{let t=Object.getOwnPropertyDescriptors(e);Object.defineProperties(this,t)};load=e=>{this.disposed||(e&&Object.assign(this.options,e),this.started?this.onRestart():(this.onStart(),this.started=!0))};dispose=()=>{if(!this.started||this.disposed)return;this.IO?.disconnect(),this.IO=void 0;let e=this.options.container;for(;e.firstChild;)e.firstChild.remove();this.onDispose(),this.container.unbindAll(),this.disposed=!0}};async function G(e){return g.sanitize(await _(e))}async function K(e){return await fetch(e).then(e=>e.json())}export{I as Controls,R as DebugPanel,W as JSONCanvasViewer,B as Minimap,H as MistouchPreventer,K as fetchCanvas,G as parser};
|
package/dist/index.d.ts
CHANGED
|
@@ -26,5 +26,5 @@ declare const internal: {
|
|
|
26
26
|
StyleManager: typeof StyleManager;
|
|
27
27
|
};
|
|
28
28
|
//#endregion
|
|
29
|
-
export { type BaseArgs, BaseModule, type BaseOptions, Controls, DebugPanel, type GeneralModule, type GeneralModuleCtor, type Hook, JSONCanvas, JSONCanvasEdge, JSONCanvasFileNode, JSONCanvasGroupNode, JSONCanvasLinkNode, JSONCanvasNode, JSONCanvasTextNode, _default as JSONCanvasViewer, type JSONCanvasViewerInterface, Minimap, MistouchPreventer, type AllOptions as Options, Parser, fetchCanvas, internal, parser, renderToString };
|
|
29
|
+
export { type BaseArgs, BaseModule, type BaseOptions, Controls, DebugPanel, type GeneralModule, type GeneralModuleCtor, type Hook, type JSONCanvas, type JSONCanvasEdge, type JSONCanvasFileNode, type JSONCanvasGroupNode, type JSONCanvasLinkNode, type JSONCanvasNode, type JSONCanvasTextNode, _default as JSONCanvasViewer, type JSONCanvasViewerInterface, Minimap, MistouchPreventer, type AllOptions as Options, type Parser, fetchCanvas, internal, parser, renderToString };
|
|
30
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\n// Must import env.d.ts, otherwise tsdown will throw at '*.scss?inline'\nimport './env.d.ts';\n\nexport {\n\tdefault as JSONCanvasViewer,\n\ttype JSONCanvasViewerInterface,\n\ttype AllOptions as Options,\n} from '$';\nexport { default as renderToString } from '@/utilities/render-to-string.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 { type Hook } from '$/utilities';\nexport { default as fetchCanvas } from '@/utilities/fetch-canvas.ts';\nexport { default as parser } from '@/utilities/parser';\nexport type * from '@repo/shared';\nexport const internal = {\n\tController,\n\tDataManager,\n\tInteractionHandler,\n\tOverlayManager,\n\tRenderer,\n\tStyleManager,\n};\n"],"mappings":"2nBA8BA,MAAa,EAAW,CACvB,aACA,cACA,qBACA,iBACA,WACA,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\n// Must import env.d.ts, otherwise tsdown will throw at '*.scss?inline'\nimport './env.d.ts';\n\nexport {\n\tdefault as JSONCanvasViewer,\n\ttype JSONCanvasViewerInterface,\n\ttype AllOptions as Options,\n} from '$';\nexport { default as renderToString } from '@/utilities/render-to-string.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 { type Hook } from '$/utilities';\nexport { default as fetchCanvas } from '@/utilities/fetch-canvas.ts';\nexport { default as parser } from '@/utilities/parser';\nexport type * from '@repo/shared';\nexport const internal = {\n\tController,\n\tDataManager,\n\tInteractionHandler,\n\tOverlayManager,\n\tRenderer,\n\tStyleManager,\n};\n"],"mappings":"2nBA8BA,MAAa,EAAW,CACvB,aACA,cACA,qBACA,iBACA,WACA,cACD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=class{onStart;onRestart;onDispose;constructor(e,t,n,r,i,a){this.container=e,this.augment=a,this.options=t,this.onStart=n.subscribe,this.onDispose=r.subscribe,this.onRestart=i.subscribe}options};export{e as BaseModule};
|
|
1
|
+
var e=class{container;augment;onStart;onRestart;onDispose;constructor(e,t,n,r,i,a){this.container=e,this.augment=a,this.options=t,this.onStart=n.subscribe,this.onDispose=r.subscribe,this.onRestart=i.subscribe}options};export{e as BaseModule};
|
|
2
2
|
//# sourceMappingURL=BaseModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseModule.js","names":[],"sources":["../../src/kernel/BaseModule.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { General, GeneralObject, ModuleInput as MI, Orchestratable } from '$/types';\nimport type { Hook } from '$/utilities';\nimport type { Container } from '@needle-di/core';\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\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\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"],"mappings":"AAeA,IAAa,EAAb,KAA2F,
|
|
1
|
+
{"version":3,"file":"BaseModule.js","names":[],"sources":["../../src/kernel/BaseModule.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { General, GeneralObject, ModuleInput as MI, Orchestratable } from '$/types';\nimport type { Hook } from '$/utilities';\nimport type { Container } from '@needle-di/core';\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\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\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"],"mappings":"AAeA,IAAa,EAAb,KAA2F,CAQ/E,UAKA,QAVX,QACA,UACA,UAEA,YACC,EACA,EACA,EACA,EACA,EACA,EACC,CANS,KAAA,UAAA,EAKA,KAAA,QAAA,EAEV,KAAK,QAAU,EACf,KAAK,QAAU,EAAQ,UACvB,KAAK,UAAY,EAAU,UAC3B,KAAK,UAAY,EAAU,SAC5B,CACA,OACD"}
|
|
@@ -16,8 +16,8 @@ declare class Controller extends BaseModule<BaseOptions, Augmentation> {
|
|
|
16
16
|
private readonly resizeObserver;
|
|
17
17
|
private perFrame;
|
|
18
18
|
private readonly lastResizeCenter;
|
|
19
|
-
onResize: Hook<[number, number]
|
|
20
|
-
onRefresh: Hook<[]
|
|
19
|
+
onResize: Hook<[number, number]>;
|
|
20
|
+
onRefresh: Hook<[]>;
|
|
21
21
|
constructor(...args: BaseArgs);
|
|
22
22
|
private readonly start;
|
|
23
23
|
private readonly draw;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{BaseModule as e}from"./BaseModule.js";import{
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import{hook as t}from"./utilities.js";import n from"./DataManager.js";import r from"./StyleManager.js";var i=class extends e{animationId;resizeAnimationId;DM;SM;resizeObserver;perFrame={lastOffsets:{x:0,y:0},lastScale:1};lastResizeCenter={};onResize=t();onRefresh=t();constructor(...e){super(...e),this.DM=this.container.get(n),this.SM=this.container.get(r),this.resizeObserver=new ResizeObserver(this.onResizeCallback),this.SM.onChangeTheme.subscribe(this.refresh),this.augment({onRefresh:this.onRefresh,onResize:this.onResize,refresh:this.refresh}),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={lastOffsets:{x:this.DM.data.offsetX,y:this.DM.data.offsetY},lastScale:this.DM.data.scale},this.onRefresh()};onResizeCallback=()=>{this.resizeAnimationId=requestAnimationFrame(()=>{let 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{i as default};
|
|
2
2
|
//# sourceMappingURL=Controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Controller.js","names":[],"sources":["../../src/kernel/Controller.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport { BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport {
|
|
1
|
+
{"version":3,"file":"Controller.js","names":[],"sources":["../../src/kernel/Controller.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport { BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport { hook } from '$/utilities';\n\ntype 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?: number;\n\tprivate resizeAnimationId?: number;\n\tprivate readonly DM: DataManager;\n\tprivate readonly SM: StyleManager;\n\tprivate readonly resizeObserver: ResizeObserver;\n\tprivate perFrame: {\n\t\tlastScale: number;\n\t\tlastOffsets: { x: number; y: number };\n\t} = {\n\t\tlastOffsets: { x: 0, y: 0 },\n\t\tlastScale: 1,\n\t};\n\tprivate readonly lastResizeCenter: {\n\t\tx?: number;\n\t\ty?: number;\n\t} = {};\n\n\tonResize = hook<[number, number]>();\n\tonRefresh = hook();\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\tonRefresh: this.onRefresh,\n\t\t\tonResize: this.onResize,\n\t\t\trefresh: this.refresh,\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 readonly start = () => {\n\t\tthis.resizeObserver.observe(this.DM.data.container);\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate readonly 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\tlastOffsets: { x: this.DM.data.offsetX, y: this.DM.data.offsetY },\n\t\t\tlastScale: this.DM.data.scale,\n\t\t};\n\t\tthis.onRefresh();\n\t};\n\n\tprivate readonly 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 readonly 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"],"mappings":"oJAaA,IAAqB,EAArB,cAAwC,CAAsC,CAC7E,YACA,kBACA,GACA,GACA,eACA,SAGI,CACH,YAAa,CAAE,EAAG,EAAG,EAAG,CAAE,EAC1B,UAAW,CACZ,EACA,iBAGI,CAAC,EAEL,SAAW,EAAuB,EAClC,UAAY,EAAK,EAEjB,YAAY,GAAG,EAAgB,CAC9B,MAAM,GAAG,CAAI,EACb,KAAK,GAAK,KAAK,UAAU,IAAI,CAAW,EACxC,KAAK,GAAK,KAAK,UAAU,IAAI,CAAY,EACzC,KAAK,eAAiB,IAAI,eAAe,KAAK,gBAAgB,EAC9D,KAAK,GAAG,cAAc,UAAU,KAAK,OAAO,EAC5C,KAAK,QAAQ,CACZ,UAAW,KAAK,UAChB,SAAU,KAAK,SACf,QAAS,KAAK,OACf,CAAC,EACD,KAAK,QAAQ,KAAK,KAAK,EACvB,KAAK,UAAU,KAAK,OAAO,EAC3B,KAAK,UAAU,KAAK,OAAO,CAC5B,CAEA,UAA+B,CAC9B,KAAK,eAAe,QAAQ,KAAK,GAAG,KAAK,SAAS,EAClD,KAAK,YAAc,sBAAsB,KAAK,IAAI,CACnD,EAEA,SAA8B,EAE5B,KAAK,SAAS,YAAc,KAAK,GAAG,KAAK,OACzC,KAAK,SAAS,YAAY,IAAM,KAAK,GAAG,KAAK,SAC7C,KAAK,SAAS,YAAY,IAAM,KAAK,GAAG,KAAK,UAE7C,KAAK,QAAQ,EACd,KAAK,YAAc,sBAAsB,KAAK,IAAI,CACnD,EAEA,YAAgB,CACf,KAAK,SAAW,CACf,YAAa,CAAE,EAAG,KAAK,GAAG,KAAK,QAAS,EAAG,KAAK,GAAG,KAAK,OAAQ,EAChE,UAAW,KAAK,GAAG,KAAK,KACzB,EACA,KAAK,UAAU,CAChB,EAEA,qBAA0C,CACzC,KAAK,kBAAoB,0BAA4B,CACpD,IAAM,EAAS,KAAK,GAAG,aAAa,EAChC,KAAK,iBAAiB,GAAK,KAAK,iBAAiB,IACpD,KAAK,GAAG,KAAK,QAAU,KAAK,GAAG,KAAK,QAAU,EAAO,EAAI,KAAK,iBAAiB,EAC/E,KAAK,GAAG,KAAK,QAAU,KAAK,GAAG,KAAK,QAAU,EAAO,EAAI,KAAK,iBAAiB,GAEhF,KAAK,iBAAiB,EAAI,EAAO,EACjC,KAAK,iBAAiB,EAAI,EAAO,EACjC,KAAK,SAAS,EAAO,MAAO,EAAO,MAAM,EACzC,KAAK,QAAQ,CACd,CAAC,CACF,EAEA,YAAiC,CAC5B,KAAK,aAAa,qBAAqB,KAAK,WAAW,EACvD,KAAK,mBAAmB,qBAAqB,KAAK,iBAAiB,EACvE,KAAK,eAAe,WAAW,CAChC,CACD"}
|
|
@@ -8,10 +8,7 @@ import { BaseOptions } from "./index.js";
|
|
|
8
8
|
type Options = {
|
|
9
9
|
shadowed?: boolean;
|
|
10
10
|
canvas?: JSONCanvas;
|
|
11
|
-
attachmentDir?: string;
|
|
12
|
-
extraCSS?: string;
|
|
13
11
|
attachments?: Record<string, string>;
|
|
14
|
-
noAttachmentRelocation?: boolean;
|
|
15
12
|
} & BaseOptions;
|
|
16
13
|
type Augmentation = {
|
|
17
14
|
resetView: DataManager['resetView'];
|
|
@@ -34,12 +31,11 @@ type EdgeItem = {
|
|
|
34
31
|
type NodeMap = Record<string, NodeItem>;
|
|
35
32
|
type EdgeMap = Record<string, EdgeItem>;
|
|
36
33
|
declare class DataManager extends BaseModule<Options, Augmentation> {
|
|
37
|
-
onToggleFullscreen: Hook<["enter" | "exit"]
|
|
34
|
+
onToggleFullscreen: Hook<["enter" | "exit"]>;
|
|
38
35
|
data: {
|
|
39
36
|
canvasData: Required<JSONCanvas>;
|
|
40
37
|
nodeMap: NodeMap;
|
|
41
38
|
edgeMap: EdgeMap;
|
|
42
|
-
canvasBaseDir: string;
|
|
43
39
|
nodeBounds: NodeBounds;
|
|
44
40
|
offsetX: number;
|
|
45
41
|
offsetY: number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{BaseModule as e}from"./BaseModule.js";import t from"./styles.js";import{applyStyles as n,getAnchorCoord as r,
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import t from"./styles.js";import{applyStyles as n,getAnchorCoord as r,hook as i}from"./utilities.js";var a=class extends e{onToggleFullscreen=i();data={canvasData:{edges:[],nodes:[]},container:document.createElement(`div`),edgeMap:{},nodeBounds:{centerX:0,centerY:0,height:0,maxX:0,maxY:0,minX:0,minY:0,width:0},nodeMap:{},offsetX:0,offsetY:0,scale:1};constructor(...e){super(...e);let r=this.options.container;for(;r.firstElementChild;)r.firstElementChild.remove();r.innerHTML=``;let i=this.options.shadowed?r.attachShadow({mode:`open`}):r;n(i,t),this.data.container.classList.add(`JSON-Canvas-Viewer`),i.appendChild(this.data.container),this.augment({onToggleFullscreen:this.onToggleFullscreen,resetView:this.resetView,toggleFullscreen:this.toggleFullscreen}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}start=()=>{let e={edges:[],nodes:[],...this.options.canvas};Object.assign(this.data,{canvasData:e,edgeMap:{},nodeBounds:this.calculateNodeBounds(e),nodeMap:{},offsetX:0,offsetY:0,scale:1}),this.data.canvasData.nodes.forEach(e=>{let t={box:this.getNodeBox(e),ref:e};if(this.data.nodeMap[e.id]=t,e.type===`file`){let n=e.file,r=n.split(`/`).pop()??``,i=r.lastIndexOf(`?`);if(t.fileName=i===-1?r:r.slice(0,i),!e.file.includes(`://`)){let t=this.options.attachments?.[n];t&&(e.file=t)}}}),this.data.canvasData.edges.forEach(e=>{this.data.edgeMap[e.id]={box:this.getEdgeBox(e),ref:e}}),this.resetView()};processBaseDir=e=>e?e?.slice(-1)===`/`?e:`${e}/`:`./`;getNodeBox=e=>({bottom:e.y+e.height,left:e.x,right:e.width+e.x,top:e.type===`file`||e.type===`group`?e.y-40:e.y});getEdgeBox=e=>{let t=this.data.nodeMap,n=t[e.fromNode].ref,i=t[e.toNode].ref,a=r(n,e.fromSide),o=r(i,e.toSide),s={bottom:Math.max(a.y,o.y),left:Math.min(a.x,o.x),right:Math.max(a.x,o.x),top:Math.min(a.y,o.y)},c=s.right-s.left,l=s.bottom-s.top,u=Math.min(c,l),d=Math.log2(Math.max(c,l)/(u===0?1:u))*10;return{bottom:s.bottom+d,left:s.left-d,right:s.right+d,top:s.top-d}};calculateNodeBounds(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;e.nodes.forEach(e=>{t=Math.min(t,e.x),n=Math.min(n,e.y),r=Math.max(r,e.x+e.width),i=Math.max(i,e.y+e.height)});let a=r-t,o=i-n;return{centerX:t+a/2,centerY:n+o/2,height:o,maxX:r,maxY:i,minX:t,minY:n,width:a}}toggleFullscreen=async e=>{!document.fullscreenElement&&(!e||e===`enter`)?(await this.data.container.requestFullscreen(),this.onToggleFullscreen(`enter`)):document.fullscreenElement&&(!e||e===`exit`)&&(await document.exitFullscreen(),this.onToggleFullscreen(`exit`))};resetView=()=>{let e=this.data.nodeBounds,t=this.data.container;if(!e||!t)return;let n=e.width+200,r=e.height+200,i=t.clientWidth,a=t.clientHeight,o=i/n,s=a/r,c=Math.round(Math.min(o,s)*1e3)/1e3,l=e.centerX,u=e.centerY,d={offsetX:i/2-l*c,offsetY:a/2-u*c,scale:c};this.data.offsetX=d.offsetX,this.data.offsetY=d.offsetY,this.data.scale=d.scale};middleViewer=()=>{let e=this.data.container;return{height:e.clientHeight,width:e.clientWidth,x:e.clientWidth/2,y:e.clientHeight/2}};dispose=()=>{this.data.container.remove()}};export{a as default};
|
|
2
2
|
//# sourceMappingURL=DataManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataManager.js","names":["style"],"sources":["../../src/kernel/DataManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { Box, NodeBounds } from '$/types';\nimport type { Hook } from '$/utilities';\nimport type { JSONCanvas, JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport style from '$/styles.scss?inline';\nimport { applyStyles, getAnchorCoord, makeHook } from '$/utilities';\n\nconst INITIAL_VIEWPORT_PADDING = 100;\nconst NODE_LABEL_MARGIN = 40;\nconst EDGE_BOX_HEURISTICS_BASE_MARGIN = 10;\n\ntype Options = {\n\tshadowed?: boolean;\n\tcanvas?: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n\tattachments?: Record<string, string>;\n\tnoAttachmentRelocation?: boolean;\n} & BaseOptions;\n\ntype Augmentation = {\n\tresetView: DataManager['resetView'];\n\ttoggleFullscreen: DataManager['toggleFullscreen'];\n\tonToggleFullscreen: DataManager['onToggleFullscreen'];\n};\n\nexport type NodeItem = {\n\tref: JSONCanvasNode;\n\tbox: Box;\n\tfileName?: string;\n\tonBeforeUnmount?: Hook;\n\tonActive?: Hook;\n\tonLoseActive?: Hook;\n};\n\nexport type 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 = 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\tcanvasBaseDir: './',\n\t\tcanvasData: {\n\t\t\tedges: [],\n\t\t\tnodes: [],\n\t\t},\n\t\tcontainer: document.createElement('div'),\n\t\tedgeMap: {},\n\t\tnodeBounds: {\n\t\t\tcenterX: 0,\n\t\t\tcenterY: 0,\n\t\t\theight: 0,\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},\n\t\tnodeMap: {},\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\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\tapplyStyles(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\tonToggleFullscreen: this.onToggleFullscreen,\n\t\t\tresetView: this.resetView,\n\t\t\ttoggleFullscreen: this.toggleFullscreen,\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 readonly start = () => {\n\t\tconst canvasData = {\n\t\t\tedges: [],\n\t\t\tnodes: [],\n\t\t\t...this.options.canvas,\n\t\t};\n\n\t\tObject.assign(this.data, {\n\t\t\tcanvasBaseDir: this.processBaseDir(this.options.attachmentDir),\n\t\t\tcanvasData,\n\t\t\tedgeMap: {},\n\t\t\tnodeBounds: this.calculateNodeBounds(canvasData),\n\t\t\tnodeMap: {},\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\tbox: this.getNodeBox(node),\n\t\t\t\tref: 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\tbox: this.getEdgeBox(edge),\n\t\t\t\tref: edge,\n\t\t\t};\n\t\t});\n\t\tthis.resetView();\n\t};\n\n\tprivate readonly processBaseDir = (baseDir?: string) => {\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 readonly getNodeBox = (node: JSONCanvasNode) => ({\n\t\tbottom: node.y + node.height,\n\t\tleft: node.x,\n\t\tright: node.width + node.x,\n\t\ttop: node.type === 'file' || node.type === 'group' ? node.y - NODE_LABEL_MARGIN : node.y,\n\t});\n\n\tprivate readonly 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 = getAnchorCoord(from, edge.fromSide);\n\t\tconst toAnchor = getAnchorCoord(to, edge.toSide);\n\t\tconst strictBox = {\n\t\t\tbottom: Math.max(fromAnchor.y, toAnchor.y),\n\t\t\tleft: Math.min(fromAnchor.x, toAnchor.x),\n\t\t\tright: Math.max(fromAnchor.x, toAnchor.x),\n\t\t\ttop: Math.min(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\tbottom: strictBox.bottom + margin,\n\t\t\tleft: strictBox.left - margin,\n\t\t\tright: strictBox.right + margin,\n\t\t\ttop: strictBox.top - 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 { centerX, centerY, height, maxX, maxY, minX, minY, width };\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\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t\tscale: 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\theight: container.clientHeight,\n\t\t\twidth: container.clientWidth,\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t};\n\t};\n\n\tprivate readonly dispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataManager.js","names":["style"],"sources":["../../src/kernel/DataManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { Box, NodeBounds } from '$/types';\nimport type { Hook } from '$/utilities';\nimport type { JSONCanvas, JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport style from '$/styles.scss?inline';\nimport { applyStyles, getAnchorCoord, hook } from '$/utilities';\n\nconst INITIAL_VIEWPORT_PADDING = 100;\nconst NODE_LABEL_MARGIN = 40;\nconst EDGE_BOX_HEURISTICS_BASE_MARGIN = 10;\n\ntype Options = {\n\tshadowed?: boolean;\n\tcanvas?: JSONCanvas;\n\tattachments?: Record<string, string>;\n} & BaseOptions;\n\ntype Augmentation = {\n\tresetView: DataManager['resetView'];\n\ttoggleFullscreen: DataManager['toggleFullscreen'];\n\tonToggleFullscreen: DataManager['onToggleFullscreen'];\n};\n\nexport type NodeItem = {\n\tref: JSONCanvasNode;\n\tbox: Box;\n\tfileName?: string;\n\tonBeforeUnmount?: Hook;\n\tonActive?: Hook;\n\tonLoseActive?: Hook;\n};\n\nexport type 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 = hook<['enter' | 'exit']>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: NodeMap;\n\t\tedgeMap: EdgeMap;\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\tedges: [],\n\t\t\tnodes: [],\n\t\t},\n\t\tcontainer: document.createElement('div'),\n\t\tedgeMap: {},\n\t\tnodeBounds: {\n\t\t\tcenterX: 0,\n\t\t\tcenterY: 0,\n\t\t\theight: 0,\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},\n\t\tnodeMap: {},\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\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\tapplyStyles(realContainer, style);\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\tonToggleFullscreen: this.onToggleFullscreen,\n\t\t\tresetView: this.resetView,\n\t\t\ttoggleFullscreen: this.toggleFullscreen,\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 readonly start = () => {\n\t\tconst canvasData = {\n\t\t\tedges: [],\n\t\t\tnodes: [],\n\t\t\t...this.options.canvas,\n\t\t};\n\n\t\tObject.assign(this.data, {\n\t\t\tcanvasData,\n\t\t\tedgeMap: {},\n\t\t\tnodeBounds: this.calculateNodeBounds(canvasData),\n\t\t\tnodeMap: {},\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\tbox: this.getNodeBox(node),\n\t\t\t\tref: 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;\n\t\t\t\tconst basename = path.split('/').pop() ?? '';\n\t\t\t\tconst lastIndex = basename.lastIndexOf('?');\n\t\t\t\titem.fileName = lastIndex !== -1 ? basename.slice(0, lastIndex) : basename;\n\t\t\t\tif (!node.file.includes('://')) {\n\t\t\t\t\tconst userDefinedAttachment = this.options.attachments?.[path];\n\t\t\t\t\tif (userDefinedAttachment) node.file = userDefinedAttachment;\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\tbox: this.getEdgeBox(edge),\n\t\t\t\tref: edge,\n\t\t\t};\n\t\t});\n\t\tthis.resetView();\n\t};\n\n\tprivate readonly processBaseDir = (baseDir?: string) => {\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 readonly getNodeBox = (node: JSONCanvasNode) => ({\n\t\tbottom: node.y + node.height,\n\t\tleft: node.x,\n\t\tright: node.width + node.x,\n\t\ttop: node.type === 'file' || node.type === 'group' ? node.y - NODE_LABEL_MARGIN : node.y,\n\t});\n\n\tprivate readonly 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 = getAnchorCoord(from, edge.fromSide);\n\t\tconst toAnchor = getAnchorCoord(to, edge.toSide);\n\t\tconst strictBox = {\n\t\t\tbottom: Math.max(fromAnchor.y, toAnchor.y),\n\t\t\tleft: Math.min(fromAnchor.x, toAnchor.x),\n\t\t\tright: Math.max(fromAnchor.x, toAnchor.x),\n\t\t\ttop: Math.min(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\tbottom: strictBox.bottom + margin,\n\t\t\tleft: strictBox.left - margin,\n\t\t\tright: strictBox.right + margin,\n\t\t\ttop: strictBox.top - 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 { centerX, centerY, height, maxX, maxY, minX, minY, width };\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\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t\tscale: 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\theight: container.clientHeight,\n\t\t\twidth: container.clientWidth,\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t};\n\t};\n\n\tprivate readonly dispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ type Augmentation = {
|
|
|
18
18
|
declare class InteractionHandler extends BaseModule<Options$1, Augmentation> {
|
|
19
19
|
pointeract: PointeractInterface<LoadedModules>;
|
|
20
20
|
private readonly DM;
|
|
21
|
-
onClick: Hook<[string | undefined]
|
|
21
|
+
onClick: Hook<[string | undefined]>;
|
|
22
22
|
constructor(...args: BaseArgs);
|
|
23
23
|
private readonly start;
|
|
24
24
|
private readonly startInteract;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{BaseModule as e}from"./BaseModule.js";import{
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import{hook as t}from"./utilities.js";import n from"./DataManager.js";import r from"./OverlayManager.js";import{Click as i,Drag as a,Lubricator as o,MultitouchPanZoom as s,Pointeract as c,PreventDefault as l,WheelPanZoom as u,lubricatorDragPreset as d,lubricatorPanPreset as f,lubricatorZoomPreset as p}from"pointeract";var m=class extends e{pointeract;DM;onClick=t();constructor(...e){super(...e),this.DM=this.container.get(n);let t=Object.assign(this.options.pointeract??{},{coordinateOutput:`relative`,element:this.DM.data.container,lubricator:{drag:d,pan:f,zoom:p}});this.pointeract=new c(t,[i,a,u,l,s,o]);let m=this.container.get(r);m.onInteractionStart.subscribe(this.stopInteract),m.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=e=>{this.truePan({x:e.deltaX,y:e.deltaY})};onZoom=e=>{this.trueZoom(e.factor,e)};trueZoom=(e,t)=>{let n=Math.max(Math.min(this.DM.data.scale*e,20),.05);if(n===this.DM.data.scale)return;let r=n/this.DM.data.scale,i=this.C2C(t);this.DM.data.offsetX=t.x-i.x*r,this.DM.data.offsetY=t.y-i.y*r,this.DM.data.scale=n};truePan=({x:e,y:t})=>{this.DM.data.offsetX+=e,this.DM.data.offsetY+=t};zoom=(e,t)=>{this.pointeract.dispatch(`zoom`,{factor:e,...t})};pan=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e,deltaY:t})};zoomToScale=(e,t)=>{let n=e/this.DM.data.scale;this.pointeract.dispatch(`zoom`,{factor:n,...t})};panToCoords=({x:e,y:t})=>{this.pointeract.dispatch(`pan`,{deltaX:e-this.DM.data.offsetX,deltaY:t-this.DM.data.offsetY})};C2C=({x:e,y:t})=>({x:e-this.DM.data.offsetX,y:t-this.DM.data.offsetY});onTrueClick=e=>{let t=e.target?e.target:void 0;if(this.isUIControl(t))return;let n=this.findNodeId(t);this.onClick(n)};isUIControl=e=>e?e.closest(`.controls`)||e.closest(`button`)||e.closest(`input`):!1;findNodeId=e=>{if(!e)return;let t=e;for(;(!t.id||t.id===``)&&t.parentElement;)t=t.parentElement;if(!(t.id===`overlays`||!t.id||t.id===``))return t.id};dispose=()=>this.pointeract.dispose()};export{m as default};
|
|
2
2
|
//# sourceMappingURL=InteractionHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractionHandler.js","names":[],"sources":["../../src/kernel/InteractionHandler.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { Coordinates } from '$/types';\nimport type { Options as PointeractOptions, Events, PointeractInterface } from 'pointeract';\nimport { BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport OverlayManager from '$/OverlayManager';\nimport {
|
|
1
|
+
{"version":3,"file":"InteractionHandler.js","names":[],"sources":["../../src/kernel/InteractionHandler.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { Coordinates } from '$/types';\nimport type { Options as PointeractOptions, Events, PointeractInterface } from 'pointeract';\nimport { BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport OverlayManager from '$/OverlayManager';\nimport { hook } from '$/utilities';\nimport {\n\tClick,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\tPreventDefault,\n\tWheelPanZoom,\n\tLubricator,\n\tlubricatorPanPreset as pan,\n\tlubricatorZoomPreset as zoom,\n\tlubricatorDragPreset as drag,\n} from 'pointeract';\n\ntype LoadedModules = [Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom, Lubricator];\n\ntype LoadedEvents = Events<LoadedModules>;\n\ntype Options = {\n\tpointeract?: PointeractOptions<LoadedModules>;\n} & BaseOptions;\n\ntype 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 readonly DM: DataManager;\n\tonClick = hook<[string | undefined]>();\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: { drag, pan, zoom },\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 readonly 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 readonly startInteract = () => {\n\t\tthis.pointeract.start();\n\t};\n\tprivate readonly stopInteract = () => {\n\t\tthis.pointeract.stop();\n\t};\n\n\tprivate readonly 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 readonly 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 += x;\n\t\tthis.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 readonly 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 readonly onTrueClick = (e: LoadedEvents['trueClick']) => {\n\t\tconst element = e.target ? (e.target as HTMLElement) : undefined;\n\t\tif (this.isUIControl(element)) return;\n\t\tconst node = this.findNodeId(element);\n\t\tthis.onClick(node);\n\t};\n\n\tprivate readonly isUIControl = (target?: HTMLElement) => {\n\t\tif (!target) return false;\n\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t};\n\n\tprivate readonly findNodeId = (element?: HTMLElement) => {\n\t\tif (!element) return;\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;\n\t\treturn ele.id;\n\t};\n\n\tprivate readonly dispose = () => this.pointeract.dispose();\n}\n"],"mappings":"6WAoCA,IAAqB,EAArB,cAAgD,CAAkC,CACjF,WACA,GACA,QAAU,EAA2B,EAErC,YAAY,GAAG,EAAgB,CAC9B,MAAM,GAAG,CAAI,EACb,KAAK,GAAK,KAAK,UAAU,IAAI,CAAW,EACxC,IAAM,EAAU,OAAO,OAAO,KAAK,QAAQ,YAAc,CAAC,EAAG,CAC5D,iBAAkB,WAClB,QAAS,KAAK,GAAG,KAAK,UACtB,WAAY,CAAE,KAAA,EAAM,IAAA,EAAK,KAAA,CAAK,CAC/B,CAA4C,EAC5C,KAAK,WAAa,IAAI,EAAW,EAAS,CACzC,EACA,EACA,EACA,EACA,EACA,CACD,CAAC,EACD,IAAM,EAAK,KAAK,UAAU,IAAI,CAAc,EAC5C,EAAG,mBAAmB,UAAU,KAAK,YAAY,EACjD,EAAG,iBAAiB,UAAU,KAAK,aAAa,EAEhD,KAAK,QAAQ,CACZ,IAAK,KAAK,IACV,YAAa,KAAK,YAClB,KAAM,KAAK,KACX,YAAa,KAAK,WACnB,CAAC,EACD,KAAK,QAAQ,KAAK,KAAK,EACvB,KAAK,UAAU,KAAK,OAAO,CAC5B,CAEA,UAA+B,CAC9B,KAAK,WACH,GAAG,MAAO,KAAK,KAAK,EACpB,GAAG,OAAQ,KAAK,KAAK,EACrB,GAAG,OAAQ,KAAK,MAAM,EACtB,GAAG,YAAa,KAAK,WAAW,EAChC,MAAM,CACT,EAEA,kBAAuC,CACtC,KAAK,WAAW,MAAM,CACvB,EACA,iBAAsC,CACrC,KAAK,WAAW,KAAK,CACtB,EAEA,MAA0B,GAA+B,CACxD,KAAK,QAAQ,CACZ,EAAG,EAAM,OACT,EAAG,EAAM,MACV,CAAC,CACF,EACA,OAA2B,GAAgC,CAC1D,KAAK,SAAS,EAAM,OAAQ,CAAK,CAClC,EAEA,UAAY,EAAiB,IAAwB,CACpD,IAAM,EAAW,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,MAAQ,EAAS,EAAE,EAAG,GAAI,EAE1E,GAAI,IADU,KAAK,GAAG,KAAK,MACH,OACxB,IAAM,EAAS,EAAW,KAAK,GAAG,KAAK,MACjC,EAAe,KAAK,IAAI,CAAM,EACpC,KAAK,GAAG,KAAK,QAAU,EAAO,EAAI,EAAa,EAAI,EACnD,KAAK,GAAG,KAAK,QAAU,EAAO,EAAI,EAAa,EAAI,EACnD,KAAK,GAAG,KAAK,MAAQ,CACtB,EACA,SAAW,CAAE,IAAG,OAAqB,CACpC,KAAK,GAAG,KAAK,SAAW,EACxB,KAAK,GAAG,KAAK,SAAW,CACzB,EAEA,MAAQ,EAAiB,IAAwB,CAChD,KAAK,WAAW,SAAS,OAAQ,CAAE,OAAQ,EAAS,GAAG,CAAO,CAAC,CAChE,EACA,KAAO,CAAE,IAAG,OAAqB,CAChC,KAAK,WAAW,SAAS,MAAO,CAAE,OAAQ,EAAG,OAAQ,CAAE,CAAC,CACzD,EACA,aAAe,EAAkB,IAAwB,CACxD,IAAM,EAAS,EAAW,KAAK,GAAG,KAAK,MACvC,KAAK,WAAW,SAAS,OAAQ,CAAE,SAAQ,GAAG,CAAO,CAAC,CACvD,EACA,aAAe,CAAE,IAAG,OAAqB,CACxC,KAAK,WAAW,SAAS,MAAO,CAC/B,OAAQ,EAAI,KAAK,GAAG,KAAK,QACzB,OAAQ,EAAI,KAAK,GAAG,KAAK,OAC1B,CAAC,CACF,EAGA,KAAwB,CAAE,EAAG,EAAY,EAAG,MAA+B,CAC1E,EAAG,EAAa,KAAK,GAAG,KAAK,QAC7B,EAAG,EAAa,KAAK,GAAG,KAAK,OAC9B,GAEA,YAAgC,GAAiC,CAChE,IAAM,EAAU,EAAE,OAAU,EAAE,OAAyB,IAAA,GACvD,GAAI,KAAK,YAAY,CAAO,EAAG,OAC/B,IAAM,EAAO,KAAK,WAAW,CAAO,EACpC,KAAK,QAAQ,CAAI,CAClB,EAEA,YAAgC,GAC1B,EACE,EAAO,QAAQ,WAAW,GAAK,EAAO,QAAQ,QAAQ,GAAK,EAAO,QAAQ,OAAO,EADpE,GAIrB,WAA+B,GAA0B,CACxD,GAAI,CAAC,EAAS,OACd,IAAI,EAAM,EACV,MAAO,CAAC,EAAI,IAAM,EAAI,KAAO,KACvB,EAAI,eACT,EAAM,EAAI,cAEP,OAAI,KAAO,YAAc,CAAC,EAAI,IAAM,EAAI,KAAO,IACnD,OAAO,EAAI,EACZ,EAEA,YAAiC,KAAK,WAAW,QAAQ,CAC1D"}
|
|
@@ -40,10 +40,10 @@ declare class OverlayManager extends BaseModule<Options, Augmentation> {
|
|
|
40
40
|
private readonly parse;
|
|
41
41
|
private readonly componentDict;
|
|
42
42
|
private get overlaysLayer();
|
|
43
|
-
onInteractionStart: Hook<[]
|
|
44
|
-
onInteractionEnd: Hook<[]
|
|
45
|
-
onNodeActive: Hook<[JSONCanvasNode]
|
|
46
|
-
onNodeLosesActive: Hook<[JSONCanvasNode]
|
|
43
|
+
onInteractionStart: Hook<[]>;
|
|
44
|
+
onInteractionEnd: Hook<[]>;
|
|
45
|
+
onNodeActive: Hook<[JSONCanvasNode]>;
|
|
46
|
+
onNodeLosesActive: Hook<[JSONCanvasNode]>;
|
|
47
47
|
constructor(...args: BaseArgs);
|
|
48
48
|
private readonly start;
|
|
49
49
|
private readonly restart;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{BaseModule as e}from"./BaseModule.js";import{destroyError as t,
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import{destroyError as t,hook as n}from"./utilities.js";import r from"./DataManager.js";import i from"./StyleManager.js";import a from"./Controller.js";import o from"./InteractionHandler.js";const s={audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,markdown:/\.(md|mdx|markdown|txt)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},c=[`markdown`,`image`,`audio`,`video`];var l=class extends e{_overlaysLayer=document.createElement(`div`);overlays={};selectedId;aborted=!1;eventListeners={};DM;SM;parse;componentDict={audio:({container:e,content:t})=>{let n=document.createElement(`audio`);n.className=`JCV-audio`,n.src=t,n.controls=!0,e.appendChild(n)},image:({container:e,content:t})=>{let n=document.createElement(`img`);n.className=`JCV-img`,n.src=t,n.loading=`lazy`,e.appendChild(n)},link:({container:e,content:t})=>{let n=document.createElement(`iframe`);n.src=t,n.sandbox=`allow-scripts allow-same-origin`,n.className=`JCV-link-iframe`,n.loading=`lazy`,e.appendChild(n)},markdown:async({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.textContent=`Loading...`,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n);let r;try{let e=await(await fetch(t)).text(),n=/^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(e);r=await this.parse(n?n[2]:e)}catch(e){console.error(`[JSON Canvas Viewer] Failed to load markdown:`,e),r=`Failed to load content.`}n.innerHTML=r},text:({container:e,content:t})=>{e.classList.add(`JCV-markdown-content`);let n=document.createElement(`div`);n.innerHTML=t,n.classList.add(`JCV-parsed-content-wrapper`),e.appendChild(n)},video:({container:e,content:t})=>{let n=document.createElement(`video`);n.className=`JCV-video`,n.src=t,n.controls=!0,e.appendChild(n)}};get overlaysLayer(){if(!this._overlaysLayer)throw t;return this._overlaysLayer}onInteractionStart=n();onInteractionEnd=n();onNodeActive=n();onNodeLosesActive=n();constructor(...e){super(...e),this.parse=this.options.parser??(e=>e),this.DM=this.container.get(r),this.SM=this.container.get(i),this.container.get(a).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);let t=this.options.nodeComponents;t&&Object.assign(this.componentDict,t),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(o).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{let e=async({ref:e,fileName:t})=>{switch(e.type){case`text`:this.createOverlay(e,await this.parse(e.text),`text`);break;case`file`:for(let n of c)if(t?.match(s[n])){this.createOverlay(e,e.file,n);break}break;case`link`:this.createOverlay(e,e.url,`link`);break}};Object.values(this.DM.data.nodeMap).forEach(async t=>await e(t))};themeChanged=()=>{Object.values(this.overlays).forEach(e=>{let t=this.DM.data.nodeMap[e.id].ref,n=this.SM.getColor(t.color);this.setOverlayColor(e,n)})};select=e=>{let t=this.selectedId,n=t?this.overlays[t]:void 0,r=e?this.overlays[e]:void 0;if(n&&t){n.classList.remove(`JCV-active`);let e=this.DM.data.nodeMap[t];this.onNodeLosesActive(e.ref),e.onLoseActive?.()}if(r&&e){r.classList.add(`JCV-active`),this.onInteractionStart();let t=this.DM.data.nodeMap[e];this.onNodeActive(t.ref),t.onActive?.()}else this.onInteractionEnd();this.selectedId=e};updateOverlays=()=>{let e=this.DM.data;this.overlaysLayer.style.transform=`translate(${e.offsetX}px, ${e.offsetY}px) scale(${e.scale})`};createOverlay=(...e)=>{if(this.aborted)return;let t=e[0],n=this.overlays[t.id];if(!n){if(n=this.constructOverlay(...e),this.aborted)return;this.overlaysLayer.appendChild(n),this.overlays[t.id]=n,n.style.left=`${t.x}px`,n.style.top=`${t.y}px`,n.style.width=`${t.width}px`,n.style.height=`${t.height}px`}};constructOverlay=(...e)=>{let t=e[0],r=document.createElement(`div`);r.classList.add(`JCV-overlay-container`),r.id=t.id,this.setOverlayColor(r,this.SM.getColor(t.color));let i=document.createElement(`div`);i.classList.add(`JCV-content`),r.appendChild(i);let a=document.createElement(`div`);a.className=`JCV-click-layer`,r.appendChild(a);let o=document.createElement(`div`);o.className=`JCV-overlay-border`,r.appendChild(o);let s=this.DM.data.nodeMap[t.id];s.onActive=n(),s.onLoseActive=n(),s.onBeforeUnmount=n(),this.componentDict[e[2]]({container:i,content:e[1],node:e[0],onActive:s.onActive,onBeforeUnmount:s.onBeforeUnmount,onLoseActive:s.onLoseActive});let c=()=>{t.id===this.selectedId&&this.onInteractionStart()},l=()=>{t.id===this.selectedId&&this.onInteractionEnd()};return r.addEventListener(`pointerenter`,c),r.addEventListener(`pointerleave`,l),r.addEventListener(`touchstart`,c),r.addEventListener(`touchend`,l),this.eventListeners[t.id]=[c,l],r};setOverlayColor=(e,t)=>{Object.entries(t).forEach(([t,n])=>{e.style.setProperty(`--overlay-${t}`,n)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([e,n])=>{if(this.DM.data.nodeMap[e].onBeforeUnmount?.(),this.eventListeners[e]){let r=this.eventListeners[e][0],i=this.eventListeners[e][1];if(!r||!i)throw t;n.removeEventListener(`pointerenter`,r),n.removeEventListener(`pointerleave`,i),n.removeEventListener(`touchstart`,r),n.removeEventListener(`touchend`,i),this.eventListeners[e][0]=void 0,this.eventListeners[e][1]=void 0}n.remove(),delete this.overlays[e]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=void 0}};export{l as default};
|
|
2
2
|
//# sourceMappingURL=OverlayManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayManager.js","names":[],"sources":["../../src/kernel/OverlayManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { WithBorderWidth as Color } from '$/StyleManager';\nimport type { Hook } from '$/utilities';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager from '$/StyleManager';\nimport { destroyError, makeHook } from '$/utilities';\n\ntype Options = {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n} & BaseOptions;\n\ntype Augmentation = {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n};\n\nconst fileRegex = {\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (options: {\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 = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId?: string;\n\tprivate aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | undefined>> = {};\n\tprivate readonly DM: DataManager;\n\tprivate readonly SM: StyleManager;\n\tprivate readonly parse: Parser;\n\tprivate readonly componentDict: ComponentDict = {\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\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\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 = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/.exec(result);\n\t\t\t\tparsedContent = await this.parse(frontmatterMatch ? frontmatterMatch[2] : result);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', error);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\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\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 = makeHook();\n\tonInteractionEnd = makeHook();\n\tonNodeActive = makeHook<[JSONCanvasNode]>();\n\tonNodeLosesActive = 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 readonly start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly 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 readonly 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 readonly select = (id?: string) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = previousId ? this.overlays[previousId] : undefined;\n\t\tconst current = id ? this.overlays[id] : undefined;\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 readonly 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 readonly 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 readonly 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 = makeHook();\n\t\tnodeItem.onLoseActive = makeHook();\n\t\tnodeItem.onBeforeUnmount = makeHook();\n\n\t\tvoid this.componentDict[args[2]]({\n\t\t\tcontainer: contentWrapper,\n\t\t\tcontent: args[1],\n\t\t\tnode: args[0] as never,\n\t\t\tonActive: nodeItem.onActive,\n\t\t\tonBeforeUnmount: nodeItem.onBeforeUnmount,\n\t\t\tonLoseActive: nodeItem.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 readonly 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 readonly 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] = undefined;\n\t\t\t\tthis.eventListeners[id][1] = undefined;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate readonly dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = undefined;\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OverlayManager.js","names":[],"sources":["../../src/kernel/OverlayManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { NodeItem } from '$/DataManager';\nimport type { WithBorderWidth as Color } from '$/StyleManager';\nimport type { Hook } from '$/utilities';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager from '$/StyleManager';\nimport { destroyError, hook } from '$/utilities';\n\ntype Options = {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n} & BaseOptions;\n\ntype Augmentation = {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n};\n\nconst fileRegex = {\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (options: {\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 = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId?: string;\n\tprivate aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | undefined>> = {};\n\tprivate readonly DM: DataManager;\n\tprivate readonly SM: StyleManager;\n\tprivate readonly parse: Parser;\n\tprivate readonly componentDict: ComponentDict = {\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\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\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 = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/.exec(result);\n\t\t\t\tparsedContent = await this.parse(frontmatterMatch ? frontmatterMatch[2] : result);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', error);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\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\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 = hook();\n\tonInteractionEnd = hook();\n\tonNodeActive = hook<[JSONCanvasNode]>();\n\tonNodeLosesActive = hook<[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 readonly start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly renderOverlays = () => {\n\t\tconst overlayMatcher = async ({ ref, fileName }: NodeItem) => {\n\t\t\tswitch (ref.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.createOverlay(ref, await this.parse(ref.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 (!fileName?.match(fileRegex[type])) continue;\n\t\t\t\t\t\tthis.createOverlay(ref, ref.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(ref, ref.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) => await overlayMatcher(node));\n\t};\n\n\tprivate readonly 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 readonly select = (id?: string) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = previousId ? this.overlays[previousId] : undefined;\n\t\tconst current = id ? this.overlays[id] : undefined;\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 readonly 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 readonly 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 readonly 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 = hook();\n\t\tnodeItem.onLoseActive = hook();\n\t\tnodeItem.onBeforeUnmount = hook();\n\n\t\tvoid this.componentDict[args[2]]({\n\t\t\tcontainer: contentWrapper,\n\t\t\tcontent: args[1],\n\t\t\tnode: args[0] as never,\n\t\t\tonActive: nodeItem.onActive,\n\t\t\tonBeforeUnmount: nodeItem.onBeforeUnmount,\n\t\t\tonLoseActive: nodeItem.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 readonly 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 readonly 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] = undefined;\n\t\t\t\tthis.eventListeners[id][1] = undefined;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate readonly dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = undefined;\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import { BaseArgs, BaseModule } from "./BaseModule.js";
|
|
2
|
-
import { BaseOptions } from "./index.js";
|
|
3
2
|
|
|
4
3
|
//#region src/kernel/Renderer.d.ts
|
|
5
|
-
|
|
6
|
-
zoomInOptimization?: boolean;
|
|
7
|
-
} & BaseOptions;
|
|
8
|
-
declare class Renderer extends BaseModule<Options> {
|
|
4
|
+
declare class Renderer extends BaseModule {
|
|
9
5
|
private _canvas?;
|
|
10
6
|
private readonly ctx;
|
|
11
7
|
private readonly DM;
|
|
12
8
|
private readonly SM;
|
|
13
|
-
private readonly zoomInOptimize;
|
|
14
9
|
private get canvas();
|
|
15
10
|
constructor(...args: BaseArgs);
|
|
16
11
|
private readonly optimizeDPR;
|
|
17
12
|
private readonly redraw;
|
|
18
|
-
private trueRedraw;
|
|
19
|
-
private fakeRedraw;
|
|
20
13
|
private readonly isInside;
|
|
21
14
|
private readonly isOutside;
|
|
22
15
|
private readonly getCurrentViewport;
|