json-canvas-viewer 3.4.3 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +51 -107
- package/dist/chimp.js +1 -1
- package/dist/index.d.ts +619 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kernel/BaseModule.js +2 -0
- package/dist/kernel/BaseModule.js.map +1 -0
- package/dist/kernel/Controller.js +2 -0
- package/dist/kernel/Controller.js.map +1 -0
- package/dist/kernel/DataManager.js +2 -0
- package/dist/kernel/DataManager.js.map +1 -0
- package/dist/kernel/InteractionHandler.js +2 -0
- package/dist/kernel/InteractionHandler.js.map +1 -0
- package/dist/kernel/OverlayManager.js +2 -0
- package/dist/kernel/OverlayManager.js.map +1 -0
- package/dist/kernel/Renderer.js +2 -0
- package/dist/kernel/Renderer.js.map +1 -0
- package/dist/kernel/StyleManager.js +2 -0
- package/dist/kernel/StyleManager.js.map +1 -0
- package/dist/kernel/index.js +2 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/kernel/styles.scss.js +2 -0
- package/dist/kernel/styles.scss.js.map +1 -0
- package/dist/kernel/utilities.js +2 -0
- package/dist/kernel/utilities.js.map +1 -0
- package/dist/modules/Controls/index.js +2 -0
- package/dist/modules/Controls/index.js.map +1 -0
- package/dist/modules/Controls/styles.scss.js +2 -0
- package/dist/modules/Controls/styles.scss.js.map +1 -0
- package/dist/modules/DebugPanel/index.js +2 -0
- package/dist/modules/DebugPanel/index.js.map +1 -0
- package/dist/modules/DebugPanel/styles.scss.js +2 -0
- package/dist/modules/DebugPanel/styles.scss.js.map +1 -0
- package/dist/modules/Minimap/index.js +2 -0
- package/dist/modules/Minimap/index.js.map +1 -0
- package/dist/modules/Minimap/styles.scss.js +2 -0
- package/dist/modules/Minimap/styles.scss.js.map +1 -0
- package/dist/modules/MistouchPreventer/index.js +2 -0
- package/dist/modules/MistouchPreventer/index.js.map +1 -0
- package/dist/modules/MistouchPreventer/styles.scss.js +2 -0
- package/dist/modules/MistouchPreventer/styles.scss.js.map +1 -0
- package/dist/utilities/fetchCanvas.js +2 -0
- package/dist/utilities/fetchCanvas.js.map +1 -0
- package/dist/utilities/parser.js +2 -0
- package/dist/utilities/parser.js.map +1 -0
- package/dist/{renderToString-Dp8A-Rka.js → utilities/renderToString.js} +2 -2
- package/dist/utilities/renderToString.js.map +1 -0
- package/package.json +14 -46
- package/dist/bridges.js +0 -2
- package/dist/bridges.js.map +0 -1
- package/dist/dev.js +0 -2
- package/dist/dev.js.map +0 -1
- package/dist/index-BPBGNZi4.js +0 -2
- package/dist/index-BPBGNZi4.js.map +0 -1
- package/dist/interactionHandler-CrVH9u7P.js +0 -2
- package/dist/interactionHandler-CrVH9u7P.js.map +0 -1
- package/dist/modules.js +0 -2
- package/dist/modules.js.map +0 -1
- package/dist/react.js +0 -2
- package/dist/react.js.map +0 -1
- package/dist/renderToString-Dp8A-Rka.js.map +0 -1
- package/dist/renderer-BGA72dN1.js +0 -2
- package/dist/renderer-BGA72dN1.js.map +0 -1
- package/dist/types/bridges/reactComponent.d.ts +0 -12
- package/dist/types/bridges/renderToString.d.ts +0 -6
- package/dist/types/bridges/vitePlugin.d.ts +0 -8
- package/dist/types/bridges/vueComponent.vue.d.ts +0 -28
- package/dist/types/bridges/webpackPlugin.d.ts +0 -7
- package/dist/types/bridges.d.ts +0 -3
- package/dist/types/chimp.d.ts +0 -7
- package/dist/types/core/baseModule.d.ts +0 -19
- package/dist/types/core/controller.d.ts +0 -35
- package/dist/types/core/dataManager.d.ts +0 -59
- package/dist/types/core/declarations.d.ts +0 -105
- package/dist/types/core/index.d.ts +0 -25
- package/dist/types/core/interactionHandler.d.ts +0 -39
- package/dist/types/core/overlayManager.d.ts +0 -44
- package/dist/types/core/renderer.d.ts +0 -32
- package/dist/types/core/styleManager.d.ts +0 -49
- package/dist/types/core/utilities.d.ts +0 -25
- package/dist/types/dev.d.ts +0 -9
- package/dist/types/index.d.ts +0 -2
- package/dist/types/modules/controls/index.d.ts +0 -38
- package/dist/types/modules/debugPanel/index.d.ts +0 -9
- package/dist/types/modules/minimap/index.d.ts +0 -32
- package/dist/types/modules/mistouchPreventer/index.d.ts +0 -25
- package/dist/types/modules.d.ts +0 -4
- package/dist/vue.js +0 -2
- package/dist/vue.js.map +0 -1
- package/dist/webpackLoader.js +0 -33
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataManager.js","sources":["../../src/kernel/DataManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { Box, NodeBounds } from '$/types';\nimport type { JSONCanvas, JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport style from '$/styles.scss?inline';\nimport utilities, { type Hook } from '$/utilities';\n\nconst INITIAL_VIEWPORT_PADDING = 100;\nconst NODE_LABEL_MARGIN = 40;\nconst EDGE_BOX_HEURISTICS_BASE_MARGIN = 10;\n\ninterface Options extends BaseOptions {\n\tshadowed?: boolean;\n\tcanvas?: JSONCanvas;\n\tattachmentDir?: string;\n\textraCSS?: string;\n\tattachments?: Record<string, string>;\n\tnoAttachmentRelocation?: boolean;\n}\n\ninterface Augmentation {\n\tresetView: DataManager['resetView'];\n\ttoggleFullscreen: DataManager['toggleFullscreen'];\n\tonToggleFullscreen: DataManager['onToggleFullscreen'];\n}\n\nexport interface NodeItem {\n\tref: JSONCanvasNode;\n\tbox: Box;\n\tfileName?: string;\n\tonBeforeUnmount?: Hook;\n\tonActive?: Hook;\n\tonLoseActive?: Hook;\n}\n\nexport interface EdgeItem {\n\tref: JSONCanvasEdge;\n\tbox: Box;\n\tcontrolPoints?: Array<number>;\n}\n\ntype NodeMap = Record<string, NodeItem>;\ntype EdgeMap = Record<string, EdgeItem>;\n\nexport default class DataManager extends BaseModule<Options, Augmentation> {\n\tonToggleFullscreen = utilities.makeHook<['enter' | 'exit']>();\n\n\tdata: {\n\t\tcanvasData: Required<JSONCanvas>;\n\t\tnodeMap: NodeMap;\n\t\tedgeMap: EdgeMap;\n\t\tcanvasBaseDir: string;\n\t\tnodeBounds: NodeBounds;\n\t\toffsetX: number;\n\t\toffsetY: number;\n\t\tscale: number;\n\t\tcontainer: HTMLDivElement;\n\t} = {\n\t\tcanvasData: {\n\t\t\tnodes: [],\n\t\t\tedges: [],\n\t\t},\n\t\tnodeMap: {},\n\t\tedgeMap: {},\n\t\tcanvasBaseDir: './',\n\t\tnodeBounds: {\n\t\t\tmaxX: 0,\n\t\t\tmaxY: 0,\n\t\t\tminX: 0,\n\t\t\tminY: 0,\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\tcenterX: 0,\n\t\t\tcenterY: 0,\n\t\t},\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\n\t\tcontainer: document.createElement('div'),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst viewerContainer = this.options.container;\n\t\twhile (viewerContainer.firstElementChild) viewerContainer.firstElementChild.remove();\n\t\tviewerContainer.innerHTML = '';\n\n\t\tconst realContainer = this.options.shadowed\n\t\t\t? viewerContainer.attachShadow({ mode: 'open' })\n\t\t\t: viewerContainer;\n\n\t\tutilities.applyStyles(realContainer, style + this.options.extraCSS);\n\n\t\tthis.data.container.classList.add('JSON-Canvas-Viewer');\n\t\trealContainer.appendChild(this.data.container);\n\n\t\tthis.augment({\n\t\t\tresetView: this.resetView,\n\t\t\ttoggleFullscreen: this.toggleFullscreen,\n\t\t\tonToggleFullscreen: this.onToggleFullscreen,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tconst canvasData = Object.assign(\n\t\t\t{\n\t\t\t\tnodes: [],\n\t\t\t\tedges: [],\n\t\t\t},\n\t\t\tthis.options.canvas,\n\t\t);\n\n\t\tObject.assign(this.data, {\n\t\t\tcanvasData: canvasData,\n\t\t\tnodeMap: {},\n\t\t\tedgeMap: {},\n\t\t\tcanvasBaseDir: this.processBaseDir(this.options.attachmentDir),\n\t\t\tnodeBounds: this.calculateNodeBounds(canvasData),\n\t\t\toffsetX: 0,\n\t\t\toffsetY: 0,\n\t\t\tscale: 1,\n\t\t});\n\n\t\tthis.data.canvasData.nodes.forEach((node) => {\n\t\t\tconst item: NodeItem = {\n\t\t\t\tref: node,\n\t\t\t\tbox: this.getNodeBox(node),\n\t\t\t};\n\t\t\tthis.data.nodeMap[node.id] = item;\n\n\t\t\t// re-process attachments\n\t\t\tif (node.type === 'file') {\n\t\t\t\tconst path = node.file.split('/');\n\t\t\t\tconst fileName = path.pop() ?? '';\n\t\t\t\titem.fileName = fileName;\n\t\t\t\tif (!node.file.startsWith('http://') && !node.file.startsWith('https://')) {\n\t\t\t\t\tconst userDefinedAttachment = this.options.attachments?.[fileName];\n\t\t\t\t\tif (userDefinedAttachment) node.file = userDefinedAttachment;\n\t\t\t\t\telse if (!this.options.noAttachmentRelocation)\n\t\t\t\t\t\tnode.file = this.data.canvasBaseDir + fileName;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.data.canvasData.edges.forEach((edge) => {\n\t\t\tthis.data.edgeMap[edge.id] = {\n\t\t\t\tref: edge,\n\t\t\t\tbox: this.getEdgeBox(edge),\n\t\t\t};\n\t\t});\n\t\tthis.resetView();\n\t};\n\n\tprivate processBaseDir = (baseDir: string | undefined) => {\n\t\tif (!baseDir) return './';\n\t\tconst lastChar = baseDir?.slice(-1);\n\t\tif (lastChar === '/') return baseDir;\n\t\treturn `${baseDir}/`;\n\t};\n\n\tprivate getNodeBox = (node: JSONCanvasNode) => {\n\t\treturn {\n\t\t\tleft: node.x,\n\t\t\ttop:\n\t\t\t\tnode.type === 'file' || node.type === 'group' ? node.y - NODE_LABEL_MARGIN : node.y,\n\t\t\tright: node.width + node.x,\n\t\t\tbottom: node.y + node.height,\n\t\t};\n\t};\n\n\tprivate getEdgeBox = (edge: JSONCanvasEdge) => {\n\t\tconst nodes = this.data.nodeMap;\n\t\tconst from = nodes[edge.fromNode].ref;\n\t\tconst to = nodes[edge.toNode].ref;\n\t\tconst fromAnchor = utilities.getAnchorCoord(from, edge.fromSide);\n\t\tconst toAnchor = utilities.getAnchorCoord(to, edge.toSide);\n\t\tconst strictBox = {\n\t\t\tleft: Math.min(fromAnchor.x, toAnchor.x),\n\t\t\ttop: Math.min(fromAnchor.y, toAnchor.y),\n\t\t\tright: Math.max(fromAnchor.x, toAnchor.x),\n\t\t\tbottom: Math.max(fromAnchor.y, toAnchor.y),\n\t\t};\n\t\t// edge size heuristics\n\t\tconst width = strictBox.right - strictBox.left;\n\t\tconst height = strictBox.bottom - strictBox.top;\n\t\tconst _min = Math.min(width, height);\n\t\tconst min = _min === 0 ? 1 : _min;\n\t\tconst max = Math.max(width, height);\n\t\tconst edgeFactor = Math.log2(max / min);\n\t\tconst margin = edgeFactor * EDGE_BOX_HEURISTICS_BASE_MARGIN;\n\t\treturn {\n\t\t\tleft: strictBox.left - margin,\n\t\t\ttop: strictBox.top - margin,\n\t\t\tright: strictBox.right + margin,\n\t\t\tbottom: strictBox.bottom + margin,\n\t\t};\n\t};\n\n\tprivate calculateNodeBounds(canvasData: Required<JSONCanvas>) {\n\t\tlet minX = Infinity,\n\t\t\tminY = Infinity,\n\t\t\tmaxX = -Infinity,\n\t\t\tmaxY = -Infinity;\n\t\tcanvasData.nodes.forEach((node) => {\n\t\t\tminX = Math.min(minX, node.x);\n\t\t\tminY = Math.min(minY, node.y);\n\t\t\tmaxX = Math.max(maxX, node.x + node.width);\n\t\t\tmaxY = Math.max(maxY, node.y + node.height);\n\t\t});\n\t\tconst width = maxX - minX;\n\t\tconst height = maxY - minY;\n\t\tconst centerX = minX + width / 2;\n\t\tconst centerY = minY + height / 2;\n\t\treturn { minX, minY, maxX, maxY, width, height, centerX, centerY };\n\t}\n\ttoggleFullscreen = async (option?: 'enter' | 'exit') => {\n\t\tif (!document.fullscreenElement && (!option || option === 'enter')) {\n\t\t\tawait this.data.container.requestFullscreen();\n\t\t\tthis.onToggleFullscreen('enter');\n\t\t} else if (document.fullscreenElement && (!option || option === 'exit')) {\n\t\t\tawait document.exitFullscreen();\n\t\t\tthis.onToggleFullscreen('exit');\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n"],"names":["DataManager","BaseModule","onToggleFullscreen","utilities","makeHook","data","canvasData","nodes","edges","nodeMap","edgeMap","canvasBaseDir","nodeBounds","maxX","maxY","minX","minY","width","height","centerX","centerY","offsetX","offsetY","scale","container","document","createElement","constructor","args","super","viewerContainer","this","options","firstElementChild","remove","innerHTML","realContainer","shadowed","attachShadow","mode","applyStyles","style","extraCSS","classList","add","appendChild","augment","resetView","toggleFullscreen","onStart","start","onRestart","onDispose","dispose","Object","assign","canvas","processBaseDir","attachmentDir","calculateNodeBounds","forEach","node","item","ref","box","getNodeBox","id","type","fileName","file","split","pop","startsWith","userDefinedAttachment","attachments","noAttachmentRelocation","edge","getEdgeBox","baseDir","lastChar","slice","left","x","top","y","right","bottom","from","fromNode","to","toNode","fromAnchor","getAnchorCoord","fromSide","toAnchor","toSide","strictBox","Math","min","max","_min","margin","log2","Infinity","async","option","fullscreenElement","exitFullscreen","requestFullscreen","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","newScale","round","initialView","middleViewer"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"./BaseModule.js";import o from"./DataManager.js";import s from"./OverlayManager.js";import a from"./utilities.js";import{dragPreset as i,zoomPreset as e,panPreset as n,Pointeract as r,Click as c,Drag as h,WheelPanZoom as d,PreventDefault as p,MultitouchPanZoom as l,Lubricator as f}from"pointeract";class m extends t{pointeract;DM;onClick=a.makeHook();constructor(...t){super(...t),this.DM=this.container.get(o);const a=Object.assign(this.options.pointeract??{},{coordinateOutput:"relative",element:this.DM.data.container,lubricator:{pan:n,zoom:e,drag:i}});this.pointeract=new r(a,[c,h,d,p,l,f]);const m=this.container.get(s);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=t=>{this.truePan({x:t.deltaX,y:t.deltaY})};onZoom=t=>{this.trueZoom(t.factor,t)};trueZoom=(t,o)=>{const s=Math.max(Math.min(this.DM.data.scale*t,20),.05);if(s===this.DM.data.scale)return;const a=s/this.DM.data.scale,i=this.C2C(o);this.DM.data.offsetX=o.x-i.x*a,this.DM.data.offsetY=o.y-i.y*a,this.DM.data.scale=s};truePan=({x:t,y:o})=>{this.DM.data.offsetX=this.DM.data.offsetX+t,this.DM.data.offsetY=this.DM.data.offsetY+o};zoom=(t,o)=>{this.pointeract.dispatch("zoom",{factor:t,...o})};pan=({x:t,y:o})=>{this.pointeract.dispatch("pan",{deltaX:t,deltaY:o})};zoomToScale=(t,o)=>{const s=t/this.DM.data.scale;this.pointeract.dispatch("zoom",{factor:s,...o})};panToCoords=({x:t,y:o})=>{this.pointeract.dispatch("pan",{deltaX:t-this.DM.data.offsetX,deltaY:o-this.DM.data.offsetY})};C2C=({x:t,y:o})=>({x:t-this.DM.data.offsetX,y:o-this.DM.data.offsetY});onTrueClick=t=>{const o=t.target;if(this.isUIControl(o))return;const s=this.findNodeId(o);this.onClick(s)};isUIControl=t=>!!t&&(t.closest(".controls")||t.closest("button")||t.closest("input"));findNodeId=t=>{if(!t)return null;let o=t;for(;(!o.id||""===o.id)&&o.parentElement;)o=o.parentElement;return"overlays"!==o.id&&o.id&&""!==o.id?o.id:null};dispose=()=>this.pointeract.dispose()}export{m as default};
|
|
2
|
+
//# sourceMappingURL=InteractionHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionHandler.js","sources":["../../src/kernel/InteractionHandler.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { Coordinates } from '$/types';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport OverlayManager from '$/OverlayManager';\nimport utilities from '$/utilities';\nimport {\n\tClick,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\ttype Options as PointeractOptions,\n\tPreventDefault,\n\ttype Events,\n\tWheelPanZoom,\n\tLubricator,\n\tpanPreset as pan,\n\tzoomPreset as zoom,\n\tdragPreset as drag,\n\ttype PointeractInterface,\n} from 'pointeract';\n\ntype LoadedModules = [Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom, Lubricator];\n\ntype LoadedEvents = Events<LoadedModules>;\n\ninterface Options extends BaseOptions {\n\tpointeract?: PointeractOptions<LoadedModules>;\n}\n\ninterface Augmentation {\n\tpan: InteractionHandler['pan'];\n\tpanToCoords: InteractionHandler['panToCoords'];\n\tzoom: InteractionHandler['zoom'];\n\tzoomToScale: InteractionHandler['zoomToScale'];\n}\n\nexport default class InteractionHandler extends BaseModule<Options, Augmentation> {\n\tpointeract: PointeractInterface<LoadedModules>;\n\tprivate DM: DataManager;\n\tonClick = utilities.makeHook<[string | null]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tconst options = Object.assign(this.options.pointeract ?? {}, {\n\t\t\tcoordinateOutput: 'relative',\n\t\t\telement: this.DM.data.container,\n\t\t\tlubricator: { pan, zoom, drag },\n\t\t} satisfies PointeractOptions<LoadedModules>);\n\t\tthis.pointeract = new Pointeract(options, [\n\t\t\tClick,\n\t\t\tDrag,\n\t\t\tWheelPanZoom,\n\t\t\tPreventDefault,\n\t\t\tMultitouchPanZoom,\n\t\t\tLubricator,\n\t\t]);\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.onInteractionStart.subscribe(this.stopInteract);\n\t\tOM.onInteractionEnd.subscribe(this.startInteract);\n\n\t\tthis.augment({\n\t\t\tpan: this.pan,\n\t\t\tpanToCoords: this.panToCoords,\n\t\t\tzoom: this.zoom,\n\t\t\tzoomToScale: this.zoomToScale,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.pointeract\n\t\t\t.on('pan', this.onPan)\n\t\t\t.on('drag', this.onPan)\n\t\t\t.on('zoom', this.onZoom)\n\t\t\t.on('trueClick', this.onTrueClick)\n\t\t\t.start();\n\t};\n\n\tprivate startInteract = () => {\n\t\tthis.pointeract.start();\n\t};\n\tprivate stopInteract = () => {\n\t\tthis.pointeract.stop();\n\t};\n\n\tprivate onPan = (event: LoadedEvents['pan']) => {\n\t\tthis.truePan({\n\t\t\tx: event.deltaX,\n\t\t\ty: event.deltaY,\n\t\t});\n\t};\n\tprivate onZoom = (event: LoadedEvents['zoom']) => {\n\t\tthis.trueZoom(event.factor, event);\n\t};\n\n\ttrueZoom = (_factor: number, origin: Coordinates) => {\n\t\tconst newScale = Math.max(Math.min(this.DM.data.scale * _factor, 20), 0.05);\n\t\tconst scale = this.DM.data.scale;\n\t\tif (newScale === scale) return;\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.DM.data.offsetX = origin.x - canvasCoords.x * factor;\n\t\tthis.DM.data.offsetY = origin.y - canvasCoords.y * factor;\n\t\tthis.DM.data.scale = newScale;\n\t};\n\ttruePan = ({ x, y }: Coordinates) => {\n\t\tthis.DM.data.offsetX = this.DM.data.offsetX + x;\n\t\tthis.DM.data.offsetY = this.DM.data.offsetY + y;\n\t};\n\n\tzoom = (_factor: number, origin: Coordinates) => {\n\t\tthis.pointeract.dispatch('zoom', { factor: _factor, ...origin });\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', { deltaX: x, deltaY: y });\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst factor = newScale / this.DM.data.scale;\n\t\tthis.pointeract.dispatch('zoom', { factor, ...origin });\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.pointeract.dispatch('pan', {\n\t\t\tdeltaX: x - this.DM.data.offsetX,\n\t\t\tdeltaY: y - this.DM.data.offsetY,\n\t\t});\n\t};\n\n\t// Container Coords to Canvas Coords relative to the top-left corner of the scaled canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.DM.data.offsetX,\n\t\ty: containerY - this.DM.data.offsetY,\n\t});\n\n\tprivate onTrueClick = (e: LoadedEvents['trueClick']) => {\n\t\tconst element = e.target as HTMLElement | null;\n\t\tif (this.isUIControl(element)) return;\n\t\tconst node = this.findNodeId(element);\n\t\tthis.onClick(node);\n\t};\n\n\tprivate isUIControl = (target: HTMLElement | null) => {\n\t\tif (!target) return false;\n\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t};\n\n\tprivate findNodeId = (element: HTMLElement | null) => {\n\t\tif (!element) return null;\n\t\tlet ele = element;\n\t\twhile (!ele.id || ele.id === '') {\n\t\t\tif (!ele.parentElement) break;\n\t\t\tele = ele.parentElement;\n\t\t}\n\t\tif (ele.id === 'overlays' || !ele.id || ele.id === '') return null;\n\t\treturn ele.id;\n\t};\n\n\tprivate dispose = () => this.pointeract.dispose();\n}\n"],"names":["InteractionHandler","BaseModule","pointeract","DM","onClick","utilities","makeHook","constructor","args","super","this","container","get","DataManager","options","Object","assign","coordinateOutput","element","data","lubricator","pan","zoom","drag","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","Lubricator","OM","OverlayManager","onInteractionStart","subscribe","stopInteract","onInteractionEnd","startInteract","augment","panToCoords","zoomToScale","onStart","start","onDispose","dispose","on","onPan","onZoom","onTrueClick","stop","event","truePan","x","deltaX","y","deltaY","trueZoom","factor","_factor","origin","newScale","Math","max","min","scale","canvasCoords","C2C","offsetX","offsetY","dispatch","containerX","containerY","e","target","isUIControl","node","findNodeId","closest","ele","id","parentElement"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as e}from"./BaseModule.js";import t from"./Controller.js";import s from"./DataManager.js";import a from"./InteractionHandler.js";import o from"./StyleManager.js";import i,{destroyError as n}from"./utilities.js";const r={markdown:/\.(md|mdx|markdown|txt)$/i,image:/\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,audio:/\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,video:/\.(mp4|webm|ogv|mov|m3u8|mpd)$/i},c=["markdown","image","audio","video"];class d extends e{_overlaysLayer=document.createElement("div");overlays={};selectedId=null;aborted=!1;eventListeners={};DM;SM;parse;componentDict={text:(e,t)=>{e.classList.add("JCV-markdown-content");const s=document.createElement("div");s.innerHTML=t,s.classList.add("JCV-parsed-content-wrapper"),e.appendChild(s)},markdown:async(e,t)=>{e.classList.add("JCV-markdown-content");const s=document.createElement("div");let a;s.textContent="Loading...",s.classList.add("JCV-parsed-content-wrapper"),e.appendChild(s);try{const e=await fetch(t),s=await e.text(),o=s.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);a=o?await this.parse(o[2]):await this.parse(s)}catch(o){console.error("[JSON Canvas Viewer] Failed to load markdown:",o),a="Failed to load content."}s.innerHTML=a},link:(e,t)=>{const s=document.createElement("iframe");s.src=t,s.sandbox="allow-scripts allow-same-origin",s.className="JCV-link-iframe",s.loading="lazy",e.appendChild(s)},audio:(e,t)=>{const s=document.createElement("audio");s.className="JCV-audio",s.src=t,s.controls=!0,e.appendChild(s)},image:(e,t)=>{const s=document.createElement("img");s.className="JCV-img",s.src=t,s.loading="lazy",e.appendChild(s)},video:(e,t)=>{const s=document.createElement("video");s.className="JCV-video",s.src=t,s.controls=!0,e.appendChild(s)}};get overlaysLayer(){if(!this._overlaysLayer)throw n;return this._overlaysLayer}onInteractionStart=i.makeHook();onInteractionEnd=i.makeHook();onNodeActive=i.makeHook();onNodeLosesActive=i.makeHook();constructor(...e){super(...e),this.parse=this.options.parser||(e=>e),this.DM=this.container.get(s),this.SM=this.container.get(o);this.container.get(t).onRefresh.subscribe(this.updateOverlays),this.SM.onChangeTheme.subscribe(this.themeChanged),this._overlaysLayer=document.createElement("div"),this._overlaysLayer.className="JCV-overlays",this._overlaysLayer.id="overlays",this.DM.data.container.appendChild(this.overlaysLayer);const a=this.options.nodeComponents;a&&Object.assign(this.componentDict,a),this.augment({onNodeActive:this.onNodeActive,onNodeLosesActive:this.onNodeLosesActive}),this.onStart(this.start),this.onRestart(this.restart),this.onDispose(this.dispose)}start=()=>{this.container.get(a).onClick.subscribe(this.select),this.renderOverlays()};restart=()=>{this.clearOverlays(),this.renderOverlays()};renderOverlays=()=>{const e=async e=>{switch(e.type){case"text":this.createOverlay(e,await this.parse(e.text),"text");break;case"file":for(const t of c)if(e.file.match(r[t])){this.createOverlay(e,e.file,t);break}break;case"link":this.createOverlay(e,e.url,"link")}};Object.values(this.DM.data.nodeMap).forEach(async t=>{await e(t.ref)})};themeChanged=()=>{Object.values(this.overlays).forEach(e=>{const t=this.DM.data.nodeMap[e.id].ref,s=this.SM.getColor(t.color);this.setOverlayColor(e,s)})};select=e=>{const t=this.selectedId,s=t?this.overlays[t]:null,a=e?this.overlays[e]:null;if(s&&t){s.classList.remove("JCV-active");const e=this.DM.data.nodeMap[t];this.onNodeLosesActive(e.ref),e.onLoseActive?.()}if(a&&e){a.classList.add("JCV-active"),this.onInteractionStart();const t=this.DM.data.nodeMap[e];this.onNodeActive(t.ref),t.onActive?.()}else this.onInteractionEnd();this.selectedId=e};updateOverlays=()=>{const e=this.DM.data;this.overlaysLayer.style.transform=`translate(${e.offsetX}px, ${e.offsetY}px) scale(${e.scale})`};createOverlay=(...e)=>{if(this.aborted)return;const t=e[0];let s=this.overlays[t.id];if(!s){if(s=this.constructOverlay(...e),this.aborted)return;this.overlaysLayer.appendChild(s),this.overlays[t.id]=s,s.style.left=`${t.x}px`,s.style.top=`${t.y}px`,s.style.width=`${t.width}px`,s.style.height=`${t.height}px`}};constructOverlay=(...e)=>{const t=e[0],s=document.createElement("div");s.classList.add("JCV-overlay-container"),s.id=t.id,this.setOverlayColor(s,this.SM.getColor(t.color));const a=document.createElement("div");a.classList.add("JCV-content"),s.appendChild(a);const o=document.createElement("div");o.className="JCV-click-layer",s.appendChild(o);const n=document.createElement("div");n.className="JCV-overlay-border",s.appendChild(n);const r=this.DM.data.nodeMap[t.id];r.onActive=i.makeHook(),r.onLoseActive=i.makeHook(),r.onBeforeUnmount=i.makeHook(),this.componentDict[e[2]](a,e[1],e[0],r.onBeforeUnmount,r.onActive,r.onLoseActive);const c=()=>{t.id===this.selectedId&&this.onInteractionStart()},d=()=>{t.id===this.selectedId&&this.onInteractionEnd()};return s.addEventListener("pointerenter",c),s.addEventListener("pointerleave",d),s.addEventListener("touchstart",c),s.addEventListener("touchend",d),this.eventListeners[t.id]=[c,d],s};setOverlayColor=(e,t)=>{Object.entries(t).forEach(([t,s])=>{e.style.setProperty(`--overlay-${t}`,s)})};clearOverlays=()=>{Object.entries(this.overlays).forEach(([e,t])=>{if(this.DM.data.nodeMap[e].onBeforeUnmount?.(),this.eventListeners[e]){const s=this.eventListeners[e][0],a=this.eventListeners[e][1];if(!s||!a)throw n;t.removeEventListener("pointerenter",s),t.removeEventListener("pointerleave",a),t.removeEventListener("touchstart",s),t.removeEventListener("touchend",a),this.eventListeners[e][0]=null,this.eventListeners[e][1]=null}t.remove(),delete this.overlays[e]})};dispose=()=>{this.aborted=!0,this.clearOverlays(),this.overlaysLayer.remove(),this._overlaysLayer=null}}export{d as default};
|
|
2
|
+
//# sourceMappingURL=OverlayManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverlayManager.js","sources":["../../src/kernel/OverlayManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager, { type Color } from '$/StyleManager';\nimport utilities, { destroyError, type Hook } from '$/utilities';\n\ninterface Options extends BaseOptions {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n}\n\ninterface Augmentation {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n}\n\n// TODO: add more formats\nconst fileRegex = {\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (\n\tcontainer: HTMLDivElement,\n\tcontent: string,\n\tnode: N,\n\tonBeforeUnmount: Hook,\n\tonActive: Hook,\n\tonLoseActive: Hook,\n) => void | Promise<void>;\n\ntype CreateOverlayArgs =\n\t| [ComponentNodeMap['text'], string, 'text']\n\t| [ComponentNodeMap['markdown'], string, 'markdown']\n\t| [ComponentNodeMap['image'], string, 'image']\n\t| [ComponentNodeMap['audio'], string, 'audio']\n\t| [ComponentNodeMap['video'], string, 'video']\n\t| [ComponentNodeMap['link'], string, 'link'];\n\ntype ComponentNodeMap = {\n\ttext: JSONCanvasTextNode;\n\tmarkdown: JSONCanvasFileNode;\n\timage: JSONCanvasFileNode;\n\taudio: JSONCanvasFileNode;\n\tvideo: JSONCanvasFileNode;\n\tlink: JSONCanvasLinkNode;\n};\n\ntype ComponentDict = {\n\t[K in keyof ComponentNodeMap]: NodeComponentHook<ComponentNodeMap[K]>;\n};\n\nconst supportedTypes = ['markdown', 'image', 'audio', 'video'] as const;\n\nexport default class OverlayManager extends BaseModule<Options, Augmentation> {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate parse: Parser;\n\tprivate componentDict: ComponentDict = {\n\t\ttext: (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.innerHTML = content;\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t},\n\t\tmarkdown: async (container, content) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.textContent = 'Loading...';\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t\tlet parsedContent: string;\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(content);\n\t\t\t\tconst result = await response.text();\n\t\t\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\t\t\tif (frontmatterMatch) parsedContent = await this.parse(frontmatterMatch[2]);\n\t\t\t\telse parsedContent = await this.parse(result);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', err);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\n\t\tlink: (container, content) => {\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.src = content;\n\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\tiframe.className = 'JCV-link-iframe';\n\t\t\tiframe.loading = 'lazy';\n\t\t\tcontainer.appendChild(iframe);\n\t\t},\n\t\taudio: (container, content) => {\n\t\t\tconst audio = document.createElement('audio');\n\t\t\taudio.className = 'JCV-audio';\n\t\t\taudio.src = content;\n\t\t\taudio.controls = true;\n\t\t\tcontainer.appendChild(audio);\n\t\t},\n\t\timage: (container, content) => {\n\t\t\tconst img = document.createElement('img');\n\t\t\timg.className = 'JCV-img';\n\t\t\timg.src = content;\n\t\t\timg.loading = 'lazy';\n\t\t\tcontainer.appendChild(img);\n\t\t},\n\t\tvideo: (container, content) => {\n\t\t\tconst video = document.createElement('video');\n\t\t\tvideo.className = 'JCV-video';\n\t\t\tvideo.src = content;\n\t\t\tvideo.controls = true;\n\t\t\tcontainer.appendChild(video);\n\t\t},\n\t};\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\tonInteractionStart = utilities.makeHook();\n\tonInteractionEnd = utilities.makeHook();\n\tonNodeActive = utilities.makeHook<[JSONCanvasNode]>();\n\tonNodeLosesActive = utilities.makeHook<[JSONCanvasNode]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.parser || ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.onRefresh.subscribe(this.updateOverlays);\n\t\tthis.SM.onChangeTheme.subscribe(this.themeChanged);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'JCV-overlays';\n\t\tthis._overlaysLayer.id = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tconst components = this.options.nodeComponents;\n\t\tif (components) Object.assign(this.componentDict, components);\n\n\t\tthis.augment({\n\t\t\tonNodeActive: this.onNodeActive,\n\t\t\tonNodeLosesActive: this.onNodeLosesActive,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.restart);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate renderOverlays = () => {\n\t\tconst overlayMatcher = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.createOverlay(node, await this.parse(node.text), 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tfor (const type of supportedTypes) {\n\t\t\t\t\t\tif (!node.file.match(fileRegex[type])) continue;\n\t\t\t\t\t\tthis.createOverlay(node, node.file, type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.createOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(async (node) => {\n\t\t\tawait overlayMatcher(node.ref);\n\t\t});\n\t};\n\n\tprivate themeChanged = () => {\n\t\tObject.values(this.overlays).forEach((overlay) => {\n\t\t\tconst node = this.DM.data.nodeMap[overlay.id].ref;\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.setOverlayColor(overlay, color);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = !previousId ? null : this.overlays[previousId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous && previousId) {\n\t\t\tprevious.classList.remove('JCV-active');\n\t\t\tconst nodeItem = this.DM.data.nodeMap[previousId];\n\t\t\tthis.onNodeLosesActive(nodeItem.ref);\n\t\t\tnodeItem.onLoseActive?.();\n\t\t}\n\t\tif (current && id) {\n\t\t\tcurrent.classList.add('JCV-active');\n\t\t\tthis.onInteractionStart();\n\t\t\tconst nodeItem = this.DM.data.nodeMap[id];\n\t\t\tthis.onNodeActive(nodeItem.ref);\n\t\t\tnodeItem.onActive?.();\n\t\t} else this.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate createOverlay = (...args: CreateOverlayArgs) => {\n\t\tif (this.aborted) return;\n\t\tconst node = args[0];\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = this.constructOverlay(...args);\n\t\t\tif (this.aborted) return;\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t}\n\t};\n\n\tprivate constructOverlay = (...args: CreateOverlayArgs) => {\n\t\tconst node = args[0];\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('JCV-overlay-container');\n\t\toverlay.id = node.id;\n\t\tthis.setOverlayColor(overlay, this.SM.getColor(node.color));\n\t\tconst contentWrapper = document.createElement('div');\n\t\tcontentWrapper.classList.add('JCV-content');\n\t\toverlay.appendChild(contentWrapper);\n\t\tconst clickLayer = document.createElement('div');\n\t\tclickLayer.className = 'JCV-click-layer';\n\t\toverlay.appendChild(clickLayer);\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'JCV-overlay-border';\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst nodeItem = this.DM.data.nodeMap[node.id];\n\n\t\tnodeItem.onActive = utilities.makeHook();\n\t\tnodeItem.onLoseActive = utilities.makeHook();\n\t\tnodeItem.onBeforeUnmount = utilities.makeHook();\n\n\t\tvoid this.componentDict[args[2]](\n\t\t\tcontentWrapper,\n\t\t\targs[1],\n\t\t\targs[0] as never,\n\t\t\tnodeItem.onBeforeUnmount,\n\t\t\tnodeItem.onActive,\n\t\t\tnodeItem.onLoseActive,\n\t\t);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t};\n\n\tprivate setOverlayColor = (overlay: HTMLDivElement, color: Color) => {\n\t\tObject.entries(color).forEach(([key, value]) => {\n\t\t\toverlay.style.setProperty(`--overlay-${key}`, value);\n\t\t});\n\t};\n\n\tprivate clearOverlays = () => {\n\t\tObject.entries(this.overlays).forEach(([id, overlay]) => {\n\t\t\tthis.DM.data.nodeMap[id].onBeforeUnmount?.();\n\t\t\tif (this.eventListeners[id]) {\n\t\t\t\tconst onStart = this.eventListeners[id][0];\n\t\t\t\tconst onEnd = this.eventListeners[id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\toverlay.removeEventListener('pointerenter', onStart);\n\t\t\t\toverlay.removeEventListener('pointerleave', onEnd);\n\t\t\t\toverlay.removeEventListener('touchstart', onStart);\n\t\t\t\toverlay.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[id][0] = null;\n\t\t\t\tthis.eventListeners[id][1] = null;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n"],"names":["fileRegex","markdown","image","audio","video","supportedTypes","OverlayManager","BaseModule","_overlaysLayer","document","createElement","overlays","selectedId","aborted","eventListeners","DM","SM","parse","componentDict","text","container","content","classList","add","parsedContentWrapper","innerHTML","appendChild","async","parsedContent","textContent","response","fetch","result","frontmatterMatch","match","this","err","console","error","link","iframe","src","sandbox","className","loading","controls","img","overlaysLayer","destroyError","onInteractionStart","utilities","makeHook","onInteractionEnd","onNodeActive","onNodeLosesActive","constructor","args","super","options","parser","get","DataManager","StyleManager","Controller","onRefresh","subscribe","updateOverlays","onChangeTheme","themeChanged","id","data","components","nodeComponents","Object","assign","augment","onStart","start","onRestart","restart","onDispose","dispose","InteractionHandler","onClick","select","renderOverlays","clearOverlays","overlayMatcher","node","type","createOverlay","file","url","values","nodeMap","forEach","ref","overlay","color","getColor","setOverlayColor","previousId","previous","current","remove","nodeItem","onLoseActive","onActive","style","transform","offsetX","offsetY","scale","element","constructOverlay","left","x","top","y","width","height","contentWrapper","clickLayer","overlayBorder","onBeforeUnmount","onEnd","addEventListener","entries","key","value","setProperty","removeEventListener"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"./BaseModule.js";import i from"./Controller.js";import e from"./DataManager.js";import s from"./StyleManager.js";import a,{destroyError as o}from"./utilities.js";class h extends t{_canvas;ctx;DM;SM;zoomInOptimize={lastDrawnScale:0,lastDrawnViewport:{left:0,right:0,top:0,bottom:0},timeout:null,lastCallTime:0};get canvas(){if(!this._canvas)throw o;return this._canvas}constructor(...t){super(...t);const a=this.container.get(i);this.SM=this.container.get(s),a.onRefresh.subscribe(this.redraw),a.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(e),this._canvas=document.createElement("canvas"),this._canvas.className="JCV-main-canvas",this.ctx=this._canvas.getContext("2d"),this.DM.data.container.appendChild(this._canvas),this.onDispose(this.dispose)}optimizeDPR=()=>{const t=this.DM.data.container;a.resizeCanvasForDPR(this.canvas,t.offsetWidth,t.offsetHeight)};redraw=()=>{const t=this.DM.data.offsetX,i=this.DM.data.offsetY,e=this.DM.data.scale,s=this.getCurrentViewport(t,i,e);if(!this.options.zoomInOptimization)return void this.trueRedraw(t,i,e,s);this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null);const a=Date.now();if(this.isInside(s,this.zoomInOptimize.lastDrawnViewport)&&e!==this.zoomInOptimize.lastDrawnScale){if(a-this.zoomInOptimize.lastCallTime<500)return this.zoomInOptimize.timeout=setTimeout(()=>{this.trueRedraw(t,i,e,s),this.zoomInOptimize.lastCallTime=a,this.zoomInOptimize.timeout=null},60),void this.fakeRedraw(s,e)}this.zoomInOptimize.lastCallTime=a,this.trueRedraw(t,i,e,s)};trueRedraw(t,i,e,s){this.zoomInOptimize.lastDrawnViewport=s,this.zoomInOptimize.lastDrawnScale=e,this.canvas.style.transform="",this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.drawGridDots(e,t,i),this.ctx.translate(t,i),this.ctx.scale(e,e),Object.values(this.DM.data.nodeMap).forEach(t=>{if(this.isOutside(t.box,s))return;const i=t.ref;"file"===i.type?this.drawFile(t):"group"===i.type&&this.drawGroup(i,e)}),Object.values(this.DM.data.edgeMap).forEach(t=>{this.isOutside(t.box,s)||this.drawEdge(t)}),this.ctx.restore()}fakeRedraw(t,i){const e=i/this.zoomInOptimize.lastDrawnScale,s=(this.zoomInOptimize.lastDrawnViewport.left-t.left)*i,a=(this.zoomInOptimize.lastDrawnViewport.top-t.top)*i;this.canvas.style.transform=`translate(${s}px, ${a}px) scale(${e})`}isInside=(t,i)=>t.left>i.left&&t.top>i.top&&t.right<i.right&&t.bottom<i.bottom;isOutside=(t,i)=>t.right<i.left||t.bottom<i.top||t.left>i.right||t.top>i.bottom;getCurrentViewport=(t,i,e)=>{const s=-t/e,a=-i/e,o=this.DM.data.container;return{left:s,top:a,right:s+o.clientWidth/e,bottom:a+o.clientHeight/e}};drawLabelBar=(t,i,e,s,a,o)=>{const h=30*o,r=6*o,c=8*o,l=16*o,n=6*o;this.ctx.save(),this.ctx.translate(t,i),this.ctx.scale(1/o,1/o),this.ctx.font=`${l}px 'Inter', sans-serif`;const d=this.ctx.measureText(e).width+2*n;this.ctx.translate(0,-h-c),this.ctx.fillStyle=s,this.ctx.beginPath(),this.ctx.moveTo(r,0),this.ctx.lineTo(d-r,0),this.ctx.quadraticCurveTo(d,0,d,r),this.ctx.lineTo(d,h-r),this.ctx.quadraticCurveTo(d,h,d-r,h),this.ctx.lineTo(r,h),this.ctx.quadraticCurveTo(0,h,0,h-r),this.ctx.lineTo(0,r),this.ctx.quadraticCurveTo(0,0,r,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=a,this.ctx.fillText(e,n,.65*h),this.ctx.restore()};drawNodeBackground=t=>{const i=this.SM.getColor(t.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=i.background,a.drawRoundRect(this.ctx,t.x+1,t.y+1,t.width-2,t.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=i.border,this.ctx.lineWidth=2,a.drawRoundRect(this.ctx,t.x,t.y,t.width,t.height,12),this.ctx.stroke()};drawGroup=(t,i)=>{if(this.drawNodeBackground(t),t.label){const e=this.SM.getColor(t.color);this.drawLabelBar(t.x,t.y,t.label,e.active,e.text,i)}};drawFile=t=>{this.ctx.fillStyle=this.SM.getColor().text;const i=t.ref;this.ctx.font="16px sans-serif",this.ctx.fillText(t.fileName??"",i.x+5,i.y-10)};drawEdge=t=>{const i=t.ref,e=this.DM.data.nodeMap[i.fromNode].ref,s=this.DM.data.nodeMap[i.toNode].ref,o=a.getAnchorCoord,{x:h,y:r}=o(e,i.fromSide),{x:c,y:l}=o(s,i.toSide),n=this.SM.getColor(i.color);let[d,x,m,f]=[0,0,0,0];if(t.controlPoints?[d,x,m,f]=t.controlPoints:([d,x,m,f]=this.getControlPoints(h,r,c,l,i.fromSide,i.toSide),t.controlPoints=[d,x,m,f]),this.drawCurvedPath(h,r,c,l,d,x,m,f,n.active),this.drawArrowhead(c,l,m,f,n.active),i.label){const t=.5,e=(1-t)**3*h+3*(1-t)**2*t*d+3*(1-t)*t*t*m+t**3*c,s=(1-t)**3*r+3*(1-t)**2*t*x+3*(1-t)*t*t*f+t**3*l;this.ctx.font="18px sans-serif";const o=8,p=this.ctx.measureText(i.label).width+2*o,u=20;this.ctx.fillStyle=n.active,this.ctx.beginPath(),a.drawRoundRect(this.ctx,e-p/2,s-u/2-2,p,u,4),this.ctx.fill(),this.ctx.fillStyle=n.text,this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillText(i.label,e,s-2),this.ctx.textAlign="left",this.ctx.textBaseline="alphabetic"}};getControlPoints=(t,i,e,s,a,o)=>{const h=e-t,r=s-i,c=Math.min(Math.abs(h),Math.abs(r))+.3*Math.max(Math.abs(h),Math.abs(r)),l=(n=.5*c,d=60,x=300,Math.max(d,Math.min(x,n)));var n,d,x;let m=t,f=i,p=e,u=s;switch(a){case"top":f=i-l;break;case"bottom":f=i+l;break;case"left":m=t-l;break;case"right":m=t+l}switch(o){case"top":u=s-l;break;case"bottom":u=s+l;break;case"left":p=e-l;break;case"right":p=e+l}return[m,f,p,u]};drawGridDots=(t,i,e)=>{const s=10*2**-Math.floor(Math.log2(t))*t,a=this.canvas.width,o=this.canvas.height,h=i%s,r=e%s;this.ctx.fillStyle=this.SM.getNamedColor("dots");for(let c=h;c<=a;c+=s)for(let t=r;t<=o;t+=s)this.ctx.beginPath(),this.ctx.arc(c,t,1,0,2*Math.PI),this.ctx.fill()};drawCurvedPath=(t,i,e,s,a,o,h,r,c)=>{this.ctx.beginPath(),this.ctx.moveTo(t,i),this.ctx.bezierCurveTo(a,o,h,r,e,s),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(t,i,e,s,a)=>{const o=t-e,h=i-s,r=Math.sqrt(o*o+h*h);if(0===r)return;const c=o/r,l=h/r,n=t-12*c-4*l,d=i-12*l+4*c,x=t-12*c+4*l,m=i-12*l-4*c;this.ctx.beginPath(),this.ctx.fillStyle=a,this.ctx.moveTo(t,i),this.ctx.lineTo(n,d),this.ctx.lineTo(x,m),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=null),this.canvas.remove(),this._canvas=null}}export{h as default};
|
|
2
|
+
//# sourceMappingURL=Renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Renderer.js","sources":["../../src/kernel/Renderer.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { Box } from '$/types';\nimport type { JSONCanvasGroupNode, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager, { type EdgeItem, type NodeItem } from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 4;\nconst NODE_RADIUS = 12;\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\nconst NODE_BORDER_WIDTH = 2;\nconst DOT_RADIUS = 1; // Dot radius in CSS pixels\nconst DOT_BASE_GAP = 10; // Base gap between dots in CSS pixels\n\nconst NODE_BORDER_HALF_WIDTH = NODE_BORDER_WIDTH / 2;\n\ninterface Options extends BaseOptions {\n\tzoomInOptimization?: boolean;\n}\n\nexport default class Renderer extends BaseModule<Options> {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: Box;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (!this._canvas) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tcontroller.onRefresh.subscribe(this.redraw);\n\t\tcontroller.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'JCV-main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate optimizeDPR = () => {\n\t\tconst container = this.DM.data.container;\n\t\tutilities.resizeCanvasForDPR(this.canvas, container.offsetWidth, container.offsetHeight);\n\t};\n\n\tprivate redraw = () => {\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (!this.options.zoomInOptimization) {\n\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\treturn;\n\t\t}\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tif (\n\t\t\tthis.isInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: Box) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.drawGridDots(scale, offsetX, offsetY);\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tObject.values(this.DM.data.nodeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tconst node = item.ref;\n\t\t\tif (node.type === 'file') this.drawFile(item);\n\t\t\telse if (node.type === 'group') this.drawGroup(node, scale);\n\t\t});\n\t\tObject.values(this.DM.data.edgeMap).forEach((item) => {\n\t\t\tif (this.isOutside(item.box, currentViewport)) return;\n\t\t\tthis.drawEdge(item);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: Box, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX =\n\t\t\t(this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY =\n\t\t\t(this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isInside = (inner: Box, outer: Box) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate isOutside = (inner: Box, outer: Box) =>\n\t\tinner.right < outer.left ||\n\t\tinner.bottom < outer.top ||\n\t\tinner.left > outer.right ||\n\t\tinner.top > outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (\n\t\tx: number,\n\t\ty: number,\n\t\tlabel: string,\n\t\tcolor: string,\n\t\ttextColor: string,\n\t\tscale: number,\n\t) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = textColor;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = this.SM.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tutilities.drawRoundRect(\n\t\t\tthis.ctx,\n\t\t\tnode.x + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.y + NODE_BORDER_HALF_WIDTH,\n\t\t\tnode.width - NODE_BORDER_WIDTH,\n\t\t\tnode.height - NODE_BORDER_WIDTH,\n\t\t\tradius,\n\t\t);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = NODE_BORDER_WIDTH;\n\t\tutilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasGroupNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label) {\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, color.active, color.text, scale);\n\t\t}\n\t};\n\n\tprivate drawFile = (item: NodeItem) => {\n\t\tthis.ctx.fillStyle = this.SM.getColor().text;\n\t\tconst node = item.ref;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(item.fileName ?? '', node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (item: EdgeItem) => {\n\t\tconst edge = item.ref;\n\t\tconst fromNode = this.DM.data.nodeMap[edge.fromNode].ref;\n\t\tconst toNode = this.DM.data.nodeMap[edge.toNode].ref;\n\t\tconst gac = utilities.getAnchorCoord;\n\t\tconst { x: startX, y: startY } = gac(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = gac(toNode, edge.toSide);\n\t\tconst color = this.SM.getColor(edge.color);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!item.controlPoints) {\n\t\t\t[startControlX, startControlY, endControlX, endControlY] = this.getControlPoints(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tedge.fromSide,\n\t\t\t\tedge.toSide,\n\t\t\t);\n\t\t\titem.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = item.controlPoints;\n\t\tthis.drawCurvedPath(\n\t\t\tstartX,\n\t\t\tstartY,\n\t\t\tendX,\n\t\t\tendY,\n\t\t\tstartControlX,\n\t\t\tstartControlY,\n\t\t\tendControlX,\n\t\t\tendControlY,\n\t\t\tcolor.active,\n\t\t);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY, color.active);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = color.active;\n\t\t\tthis.ctx.beginPath();\n\t\t\tutilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = color.text;\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawGridDots = (scale: number, offsetX: number, offsetY: number) => {\n\t\tconst scaleLevel = -Math.floor(Math.log2(scale));\n\t\tconst actualGap = DOT_BASE_GAP * 2 ** scaleLevel * scale;\n\t\tconst width = this.canvas.width;\n\t\tconst height = this.canvas.height;\n\t\tconst startX = offsetX % actualGap;\n\t\tconst startY = offsetY % actualGap;\n\t\tthis.ctx.fillStyle = this.SM.getNamedColor('dots');\n\t\tfor (let x = startX; x <= width; x += actualGap) {\n\t\t\tfor (let y = startY; y <= height; y += actualGap) {\n\t\t\t\tthis.ctx.beginPath();\n\t\t\t\tthis.ctx.arc(x, y, DOT_RADIUS, 0, 2 * Math.PI);\n\t\t\t\tthis.ctx.fill();\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t\tcolor: string,\n\t) => {\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(startX, startY);\n\t\tthis.ctx.bezierCurveTo(c1x, c1y, c2x, c2y, endX, endY);\n\t\tthis.ctx.strokeStyle = color;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (\n\t\ttipX: number,\n\t\ttipY: number,\n\t\tfromX: number,\n\t\tfromY: number,\n\t\tcolor: string,\n\t) => {\n\t\tconst dx = tipX - fromX;\n\t\tconst dy = tipY - fromY;\n\t\tconst length = Math.sqrt(dx * dx + dy * dy);\n\t\tif (length === 0) return;\n\t\tconst unitX = dx / length;\n\t\tconst unitY = dy / length;\n\t\tconst leftX = tipX - unitX * ARROW_LENGTH - unitY * ARROW_WIDTH;\n\t\tconst leftY = tipY - unitY * ARROW_LENGTH + unitX * ARROW_WIDTH;\n\t\tconst rightX = tipX - unitX * ARROW_LENGTH + unitY * ARROW_WIDTH;\n\t\tconst rightY = tipY - unitY * ARROW_LENGTH - unitX * ARROW_WIDTH;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.moveTo(tipX, tipY);\n\t\tthis.ctx.lineTo(leftX, leftY);\n\t\tthis.ctx.lineTo(rightX, rightY);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t};\n\n\tprivate dispose = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tthis.canvas.remove();\n\t\tthis._canvas = null;\n\t};\n}\n"],"names":["Renderer","BaseModule","_canvas","ctx","DM","SM","zoomInOptimize","lastDrawnScale","lastDrawnViewport","left","right","top","bottom","timeout","lastCallTime","canvas","this","destroyError","constructor","args","super","controller","container","get","Controller","StyleManager","onRefresh","subscribe","redraw","onResize","optimizeDPR","DataManager","document","createElement","className","getContext","data","appendChild","onDispose","dispose","utilities","resizeCanvasForDPR","offsetWidth","offsetHeight","offsetX","offsetY","scale","currentViewport","getCurrentViewport","options","zoomInOptimization","trueRedraw","clearTimeout","now","Date","isInside","setTimeout","fakeRedraw","style","transform","clearRect","width","height","save","drawGridDots","translate","Object","values","nodeMap","forEach","item","isOutside","box","node","ref","type","drawFile","drawGroup","edgeMap","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","clientWidth","clientHeight","drawLabelBar","x","y","label","color","textColor","barHeight","radius","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillText","drawNodeBackground","colors","getColor","globalAlpha","background","drawRoundRect","NODE_BORDER_WIDTH","strokeStyle","border","lineWidth","stroke","active","text","fileName","edge","fromNode","toNode","gac","getAnchorCoord","startX","startY","fromSide","endX","endY","toSide","startControlX","startControlY","endControlX","endControlY","controlPoints","getControlPoints","drawCurvedPath","drawArrowhead","t","padding","labelWidth","labelHeight","textAlign","textBaseline","distanceX","distanceY","realDistance","Math","min","abs","max","PADDING","val","actualGap","floor","log2","getNamedColor","arc","PI","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","length","sqrt","unitX","unitY","leftX","leftY","rightX","rightY","remove"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"./BaseModule.js";import e from"./DataManager.js";import s from"./utilities.js";import{toHslString as r,rgbToHsl as h,parseRgb as o,parseHex as a,parseHsl as i}from"@ahmedsemih/color-fns";class n extends t{theme="light";onChangeTheme=s.makeHook();definedColors={light:{0:{hue:0,saturation:0,lightness:72},1:{hue:358,saturation:81,lightness:55},2:{hue:19,saturation:87,lightness:58},3:{hue:41,saturation:79,lightness:52},4:{hue:150,saturation:100,lightness:37},5:{hue:221,saturation:100,lightness:59},6:{hue:257,saturation:81,lightness:62}},dark:{0:{hue:0,saturation:0,lightness:40},1:{hue:358,saturation:100,lightness:65},2:{hue:23,saturation:86,lightness:63},3:{hue:39,saturation:91,lightness:70},4:{hue:153,saturation:80,lightness:45},5:{hue:217,saturation:100,lightness:62},6:{hue:259,saturation:100,lightness:75}}};namedColors={light:{dots:"hsla(0, 0%, 72%, 0.4)",text:"rgb(30, 30, 30)",background:"rgb(250, 250, 250)","background-secondary":"rgb(255, 255, 255)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.1)",border:"hsla(0, 0%, 82%, 0.7)"},dark:{dots:"hsla(0, 0%, 40%, 0.3)",text:"rgb(242, 242, 242)",background:"rgb(30, 30, 30)","background-secondary":"rgb(37, 37, 40)",shadow:"0px 0px 8px rgb(0, 0, 0, 0.2)",border:"hsla(0, 0%, 30%, 0.7)"}};colorCache={dark:{},light:{}};constructor(...t){super(...t);const e=this.options.colors;if(e){["light","dark"].forEach(t=>{if(!(t in e))return;const s=e[t];s&&Object.entries(s).forEach(([e,s])=>{if(!s)return;const r=this.namedColors[t],h=this.definedColors[t];if(e in r)r[e]=s;else if(e in h){const t=this.parseColor(s);if(!t)return void console.warn(`[JSON Canvas Viewer] Color ${s} unsupported.`);h[e]=t}})})}this.changeTheme(this.options.theme??"light"),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=t=>{const{hue:e,saturation:s,lightness:h}=t;let o;return o="dark"===this.theme?{active:t,card:{hue:e,saturation:s/3,lightness:h/3},border:{...t,alpha:.7},background:{...t,alpha:.1},text:t.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"}:{active:t,card:0===e?{hue:e,saturation:s,lightness:100}:{hue:e,saturation:.4*s,lightness:90},border:{...t,alpha:.7},background:{...t,alpha:.1},text:t.lightness>=70?"rgb(30, 30, 30)":"rgb(242, 242, 242)"},{active:r(o.active),card:r(o.card),border:r(o.border),background:r(o.background),text:o.text}};parseColor=t=>t.startsWith("rgb")?h(o(t)):t.startsWith("#")?h(a(t)):t.startsWith("hsl")?i(t):void 0;getColor=(t="0")=>{const e=this.theme;let s;return this.colorCache[e][t]?this.colorCache[e][t]:(s=t in this.definedColors[e]?this.hslProcessor(this.definedColors[e][t]):this.hslProcessor(h(a(t))),this.colorCache[e][t]=s,s)};getNamedColor=t=>this.namedColors[this.theme][t];changeTheme=t=>{this.theme=t||("dark"===this.theme?"light":"dark");const s=this.container.get(e).data.container;Object.entries(this.namedColors[this.theme]).forEach(([t,e])=>{s.style.setProperty(`--${t}`,e)}),this.onChangeTheme(this.theme)}}export{n as default};
|
|
2
|
+
//# sourceMappingURL=StyleManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StyleManager.js","sources":["../../src/kernel/StyleManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport { BaseModule, type BaseArgs } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities from '$/utilities';\nimport {\n\tparseHex,\n\ttoHslString,\n\ttype HslColor,\n\trgbToHsl,\n\tparseHsl,\n\tparseRgb,\n} from '@ahmedsemih/color-fns';\n\nexport type Color = {\n\tborder: string;\n\tbackground: string;\n\tactive: string;\n\ttext: string;\n\tcard: string;\n};\n\ntype ColorOptions = {\n\t[K in keyof (StyleManager['definedColors']['light'] &\n\t\tStyleManager['namedColors']['light'])]?: string;\n};\n\ninterface Options extends BaseOptions {\n\ttheme?: 'dark' | 'light';\n\tcolors?: {\n\t\tlight?: ColorOptions;\n\t\tdark?: ColorOptions;\n\t};\n}\n\ninterface Augmentation {\n\tchangeTheme: StyleManager['changeTheme'];\n\tonChangeTheme: StyleManager['onChangeTheme'];\n}\n\nexport default class StyleManager extends BaseModule<Options, Augmentation> {\n\ttheme: 'dark' | 'light' = 'light';\n\tonChangeTheme = utilities.makeHook<['light' | 'dark']>();\n\tdefinedColors = {\n\t\tlight: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 72 },\n\t\t\t'1': { hue: 358, saturation: 81, lightness: 55 },\n\t\t\t'2': { hue: 19, saturation: 87, lightness: 58 },\n\t\t\t'3': { hue: 41, saturation: 79, lightness: 52 },\n\t\t\t'4': { hue: 150, saturation: 100, lightness: 37 },\n\t\t\t'5': { hue: 221, saturation: 100, lightness: 59 },\n\t\t\t'6': { hue: 257, saturation: 81, lightness: 62 },\n\t\t},\n\t\tdark: {\n\t\t\t'0': { hue: 0, saturation: 0, lightness: 40 },\n\t\t\t'1': { hue: 358, saturation: 100, lightness: 65 },\n\t\t\t'2': { hue: 23, saturation: 86, lightness: 63 },\n\t\t\t'3': { hue: 39, saturation: 91, lightness: 70 },\n\t\t\t'4': { hue: 153, saturation: 80, lightness: 45 },\n\t\t\t'5': { hue: 217, saturation: 100, lightness: 62 },\n\t\t\t'6': { hue: 259, saturation: 100, lightness: 75 },\n\t\t},\n\t};\n\n\tnamedColors = {\n\t\tlight: {\n\t\t\tdots: 'hsla(0, 0%, 72%, 0.4)',\n\t\t\ttext: 'rgb(30, 30, 30)',\n\t\t\tbackground: 'rgb(250, 250, 250)',\n\t\t\t'background-secondary': 'rgb(255, 255, 255)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.1)',\n\t\t\tborder: 'hsla(0, 0%, 82%, 0.7)',\n\t\t},\n\t\tdark: {\n\t\t\tdots: 'hsla(0, 0%, 40%, 0.3)',\n\t\t\ttext: 'rgb(242, 242, 242)',\n\t\t\tbackground: 'rgb(30, 30, 30)',\n\t\t\t'background-secondary': 'rgb(37, 37, 40)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.2)',\n\t\t\tborder: 'hsla(0, 0%, 30%, 0.7)',\n\t\t},\n\t};\n\n\tprivate colorCache: {\n\t\tdark: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t\tlight: {\n\t\t\t[key: string]: Color;\n\t\t};\n\t} = {\n\t\tdark: {},\n\t\tlight: {},\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\n\t\t// user-defined color merging\n\t\tconst colors = this.options.colors;\n\t\tif (colors) {\n\t\t\tconst themes = ['light', 'dark'] as const;\n\t\t\tthemes.forEach((theme) => {\n\t\t\t\tif (!(theme in colors)) return;\n\t\t\t\tconst colorObject = colors[theme];\n\t\t\t\tif (!colorObject) return;\n\t\t\t\tObject.entries(colorObject).forEach(([key, value]) => {\n\t\t\t\t\tif (!value) return;\n\t\t\t\t\tconst namedColorsDict = this.namedColors[theme];\n\t\t\t\t\tconst definedColorsDict = this.definedColors[theme];\n\t\t\t\t\tif (key in namedColorsDict)\n\t\t\t\t\t\tnamedColorsDict[key as keyof typeof namedColorsDict] = value;\n\t\t\t\t\telse if (key in definedColorsDict) {\n\t\t\t\t\t\tconst color = this.parseColor(value);\n\t\t\t\t\t\tif (!color) {\n\t\t\t\t\t\t\tconsole.warn(`[JSON Canvas Viewer] Color ${value} unsupported.`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefinedColorsDict[key as keyof typeof definedColorsDict] = color;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tthis.changeTheme(this.options.theme ?? 'light');\n\t\tthis.augment({\n\t\t\tchangeTheme: this.changeTheme,\n\t\t\tonChangeTheme: this.onChangeTheme,\n\t\t});\n\t}\n\n\tprivate hslProcessor = (color: HslColor) => {\n\t\tconst { hue, saturation, lightness } = color;\n\t\tlet result;\n\t\tif (this.theme === 'dark') {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard: { hue, saturation: saturation / 3, lightness: lightness / 3 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t} else {\n\t\t\tresult = {\n\t\t\t\tactive: color,\n\t\t\t\tcard:\n\t\t\t\t\thue === 0\n\t\t\t\t\t\t? { hue, saturation, lightness: 100 }\n\t\t\t\t\t\t: { hue, saturation: saturation * 0.4, lightness: 90 },\n\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tactive: toHslString(result.active),\n\t\t\tcard: toHslString(result.card),\n\t\t\tborder: toHslString(result.border),\n\t\t\tbackground: toHslString(result.background),\n\t\t\ttext: result.text,\n\t\t};\n\t};\n\n\tprivate parseColor = (color: string) => {\n\t\tif (color.startsWith('rgb')) return rgbToHsl(parseRgb(color));\n\t\tif (color.startsWith('#')) return rgbToHsl(parseHex(color));\n\t\tif (color.startsWith('hsl')) return parseHsl(color);\n\t};\n\n\tgetColor = (colorIndex: string = '0') => {\n\t\tconst theme = this.theme;\n\t\tlet color: Color;\n\t\tif (this.colorCache[theme][colorIndex]) return this.colorCache[theme][colorIndex];\n\t\telse if (colorIndex in this.definedColors[theme])\n\t\t\tcolor = this.hslProcessor(\n\t\t\t\tthis.definedColors[theme][colorIndex as keyof typeof this.definedColors.dark],\n\t\t\t);\n\t\telse color = this.hslProcessor(rgbToHsl(parseHex(colorIndex)));\n\t\tthis.colorCache[theme][colorIndex] = color;\n\t\treturn color;\n\t};\n\n\tgetNamedColor = (name: keyof typeof this.namedColors.light) =>\n\t\tthis.namedColors[this.theme][name];\n\n\tchangeTheme = (theme?: 'dark' | 'light') => {\n\t\tthis.theme = theme ? theme : this.theme === 'dark' ? 'light' : 'dark';\n\t\tconst container = this.container.get(DataManager).data.container;\n\t\tObject.entries(this.namedColors[this.theme]).forEach(([key, value]) => {\n\t\t\tcontainer.style.setProperty(`--${key}`, value);\n\t\t});\n\t\tthis.onChangeTheme(this.theme);\n\t};\n}\n"],"names":["StyleManager","BaseModule","theme","onChangeTheme","utilities","makeHook","definedColors","light","hue","saturation","lightness","dark","namedColors","dots","text","background","shadow","border","colorCache","constructor","args","super","colors","this","options","forEach","colorObject","Object","entries","key","value","namedColorsDict","definedColorsDict","color","parseColor","console","warn","changeTheme","augment","hslProcessor","result","active","card","alpha","toHslString","startsWith","rgbToHsl","parseRgb","parseHex","parseHsl","getColor","colorIndex","getNamedColor","name","container","get","DataManager","data","style","setProperty"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import t from"./Controller.js";import s from"./DataManager.js";import o from"./InteractionHandler.js";import i from"./OverlayManager.js";import e from"./Renderer.js";import r from"./StyleManager.js";import n from"./utilities.js";import{Container as a}from"@needle-di/core";const h=[s,r,t,i,o,e];class l{allModules;IO=null;started=!1;disposed=!1;options;container;onDispose=n.makeHook(!0);onStart=n.makeHook();onRestart=n.makeHook();constructor(t,s){this.container=new a,this.options=t;this.allModules=[...h,...s??[]],this.allModules.forEach(t=>{this.container.bind({provide:t,useFactory:()=>new t(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})}),this.allModules.forEach(t=>{this.container.get(t)});const o=this.options.loading??"normal";"normal"===o?this.load():"lazy"===o&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{root:null,rootMargin:"50px",threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=t=>{t.forEach(t=>{if(t.isIntersecting)return this.load(),this.IO?.disconnect(),void(this.IO=null)})};augment=t=>{const s=Object.getOwnPropertyDescriptors(t);Object.defineProperties(this,s)};load=t=>{this.disposed||(t&&Object.assign(this.options,t),this.started?this.onRestart():(this.onStart(),this.started=!0))};dispose=()=>{if(!this.started||this.disposed)return;this.IO?.disconnect(),this.IO=null;const t=this.options.container;for(;t.firstChild;)t.firstChild.remove();this.onDispose(),this.container.unbindAll(),this.disposed=!0}}export{l as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/kernel/index.ts"],"sourcesContent":["import type {\n\tModuleInputCtor,\n\tModuleInput,\n\tOptions,\n\tAugmentation,\n\tGeneralModuleCtor,\n} from '$/BaseModule';\nimport type { GeneralObject } from '$/types';\nimport type { JSONCanvas } from '@repo/shared';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport OverlayManager from '$/OverlayManager';\nimport Renderer from '$/Renderer';\nimport StyleManager from '$/StyleManager';\nimport utilities from '$/utilities';\nimport { Container } from '@needle-di/core';\n\nexport interface BaseOptions {\n\tcontainer: HTMLElement;\n\tloading?: 'normal' | 'lazy' | 'none';\n}\n\nconst internalModules = [\n\tDataManager,\n\tStyleManager,\n\tController,\n\tOverlayManager,\n\tInteractionHandler,\n\tRenderer,\n];\n\ntype InternalModules = typeof internalModules;\n\nexport type AllOptions<M extends ModuleInput = []> = Options<M> & Options<InternalModules>;\ntype AllAugmentation<M extends ModuleInput = []> = Augmentation<M> & Augmentation<InternalModules>;\n\nclass JSONCanvasViewer<M extends ModuleInputCtor> {\n\tprivate allModules: ModuleInputCtor;\n\tprivate IO: IntersectionObserver | null = null;\n\tprivate started = false;\n\tprivate disposed = false;\n\toptions: AllOptions<M>;\n\tcontainer: Container;\n\tonDispose = utilities.makeHook(true);\n\tonStart = utilities.makeHook();\n\tonRestart = utilities.makeHook();\n\n\tconstructor(options: AllOptions<M>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () =>\n\t\t\t\t\tnew Class(\n\t\t\t\t\t\tthis.container,\n\t\t\t\t\t\tthis.options,\n\t\t\t\t\t\tthis.onStart,\n\t\t\t\t\t\tthis.onDispose,\n\t\t\t\t\t\tthis.onRestart,\n\t\t\t\t\t\tthis.augment,\n\t\t\t\t\t),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [...internalModules, ...(modules ?? [])];\n\t\tthis.allModules.forEach(bind);\n\t\tthis.allModules.forEach((Module) => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\n\t\tconst loading = this.options.loading ?? 'normal';\n\t\tif (loading === 'normal') this.load();\n\t\telse if (loading === 'lazy') {\n\t\t\tthis.IO = new IntersectionObserver(this.onVisibilityCheck, {\n\t\t\t\troot: null,\n\t\t\t\trootMargin: '50px',\n\t\t\t\tthreshold: 0,\n\t\t\t});\n\t\t\tthis.IO.observe(this.options.container);\n\t\t}\n\t}\n\n\tprivate onVisibilityCheck = (entries: Array<IntersectionObserverEntry>) => {\n\t\tentries.forEach((entry) => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tthis.load();\n\t\t\t\tthis.IO?.disconnect();\n\t\t\t\tthis.IO = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t});\n\t};\n\n\tprivate augment = (aug: GeneralObject) => {\n\t\tconst descriptors = Object.getOwnPropertyDescriptors(aug);\n\t\tObject.defineProperties(this, descriptors);\n\t};\n\n\tload = (options?: {\n\t\tcanvas?: JSONCanvas;\n\t\tattachmentDir?: string;\n\t\tattachments?: Record<string, string>;\n\t}) => {\n\t\tif (this.disposed) return;\n\t\tif (options) Object.assign(this.options, options);\n\t\tif (this.started) this.onRestart();\n\t\telse {\n\t\t\tthis.onStart();\n\t\t\tthis.started = true;\n\t\t}\n\t};\n\n\tdispose = () => {\n\t\tif (!this.started || this.disposed) return;\n\t\tthis.IO?.disconnect();\n\t\tthis.IO = null;\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.onDispose();\n\t\tthis.container.unbindAll();\n\t\tthis.disposed = true;\n\t};\n}\n\ntype JSONCanvasViewerType = new <M extends ModuleInputCtor = []>(\n\t...args: ConstructorParameters<typeof JSONCanvasViewer<M>>\n) => JSONCanvasViewer<M> & AllAugmentation<M>;\n\nexport type JSONCanvasViewerInterface<M extends ModuleInput = []> = JSONCanvasViewer<never> &\n\tAllAugmentation<M>;\n\nexport default JSONCanvasViewer as JSONCanvasViewerType;\n"],"names":["internalModules","DataManager","StyleManager","Controller","OverlayManager","InteractionHandler","Renderer","JSONCanvasViewer","allModules","IO","started","disposed","options","container","onDispose","utilities","makeHook","onStart","onRestart","constructor","modules","this","Container","forEach","Class","bind","provide","useFactory","augment","Module","get","loading","load","IntersectionObserver","onVisibilityCheck","root","rootMargin","threshold","observe","entries","entry","isIntersecting","disconnect","aug","descriptors","Object","getOwnPropertyDescriptors","defineProperties","assign","dispose","firstChild","remove","unbindAll"],"mappings":"iRAuBA,MAAMA,EAAkB,CACvBC,EACAC,EACAC,EACAC,EACAC,EACAC,GAQD,MAAMC,EACGC,WACAC,GAAkC,KAClCC,SAAU,EACVC,UAAW,EACnBC,QACAC,UACAC,UAAYC,EAAUC,UAAS,GAC/BC,QAAUF,EAAUC,WACpBE,UAAYH,EAAUC,WAEtB,WAAAG,CAAYP,EAAwBQ,GACnCC,KAAKR,UAAY,IAAIS,EACrBD,KAAKT,QAAUA,EAefS,KAAKb,WAAa,IAAIR,KAAqBoB,GAAW,IACtDC,KAAKb,WAAWe,QAfFC,IACbH,KAAKR,UAAUY,KAAK,CACnBC,QAASF,EACTG,WAAY,IACX,IAAIH,EACHH,KAAKR,UACLQ,KAAKT,QACLS,KAAKJ,QACLI,KAAKP,UACLO,KAAKH,UACLG,KAAKO,aAMTP,KAAKb,WAAWe,QAASM,IACxBR,KAAKR,UAAUiB,IAAID,KAGpB,MAAME,EAAUV,KAAKT,QAAQmB,SAAW,SACxB,WAAZA,EAAsBV,KAAKW,OACV,SAAZD,IACRV,KAAKZ,GAAK,IAAIwB,qBAAqBZ,KAAKa,kBAAmB,CAC1DC,KAAM,KACNC,WAAY,OACZC,UAAW,IAEZhB,KAAKZ,GAAG6B,QAAQjB,KAAKT,QAAQC,WAE/B,CAEQqB,kBAAqBK,IAC5BA,EAAQhB,QAASiB,IAChB,GAAIA,EAAMC,eAIT,OAHApB,KAAKW,OACLX,KAAKZ,IAAIiC,kBACTrB,KAAKZ,GAAK,SAMLmB,QAAWe,IAClB,MAAMC,EAAcC,OAAOC,0BAA0BH,GACrDE,OAAOE,iBAAiB1B,KAAMuB,IAG/BZ,KAAQpB,IAKHS,KAAKV,WACLC,GAASiC,OAAOG,OAAO3B,KAAKT,QAASA,GACrCS,KAAKX,QAASW,KAAKH,aAEtBG,KAAKJ,UACLI,KAAKX,SAAU,KAIjBuC,QAAU,KACT,IAAK5B,KAAKX,SAAWW,KAAKV,SAAU,OACpCU,KAAKZ,IAAIiC,aACTrB,KAAKZ,GAAK,KACV,MAAMI,EAAYQ,KAAKT,QAAQC,UAC/B,KAAOA,EAAUqC,YAAYrC,EAAUqC,WAAWC,SAClD9B,KAAKP,YACLO,KAAKR,UAAUuC,YACf/B,KAAKV,UAAW"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=".JSON-Canvas-Viewer{--contentTransition: color .2s, opacity .2s, text-shadow .2s, fill .2s;--containerTransition: background .2s, opacity .2s, box-shadow .2s, border .2s, filter .2s, backdrop-filter .2s;color:var(--text);fill:var(--text);stroke:var(--text);background-color:var(--background);position:relative;width:100%;height:100%;overflow:hidden}.JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-full,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{top:0;left:0;width:100%;height:100%;position:absolute}.JSON-Canvas-Viewer .JCV-flex-center,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{display:flex;justify-content:center;align-items:center}.JSON-Canvas-Viewer .JCV-border-shadow-bg{background:var(--background-secondary);border:1px solid var(--border)!important;box-shadow:var(--shadow)}.JSON-Canvas-Viewer .JCV-button{cursor:pointer;font-size:18px;height:32px;border:none;transition:var(--containerTransition);background-color:var(--background-secondary);text-align:center;width:32px;padding:5px 0}.JSON-Canvas-Viewer .JCV-button svg{width:100%;height:100%}.JSON-Canvas-Viewer .JCV-button:hover{background-color:var(--border)}.JSON-Canvas-Viewer .JCV-button.JCV-collapse-button{border-radius:8px;transition:transform .2s,background-color .2s}.JSON-Canvas-Viewer .JCV-collapsed .JCV-collapse-button{transform:rotate(180deg)}.JSON-Canvas-Viewer .JCV-main-canvas{width:100%;height:100%;transform-origin:top left}.JSON-Canvas-Viewer .JCV-overlays{position:absolute;transform-origin:top left;will-change:transform}.JSON-Canvas-Viewer .JCV-overlay-container{position:absolute;box-sizing:border-box;border-radius:12px;-webkit-user-select:none;user-select:none;contain:strict;content-visibility:auto;background-color:var(--overlay-card);transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-overlay-border{box-sizing:border-box;pointer-events:none;position:absolute;color:var(--overlay-border);top:0;left:0;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:12px;transition:var(--containerTransition)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content{overflow:hidden}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content{position:absolute;padding:0 7px}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-content.JCV-markdown-content.rtl{direction:rtl;text-align:right}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active{-webkit-user-select:auto;user-select:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-overlay-border{border:4px solid var(--overlay-active)}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-link-iframe,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-audio,.JSON-Canvas-Viewer .JCV-overlay-container .JCV-video{border:none;background:transparent}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-click-layer{background:transparent;pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-click-layer{pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-img{width:100%;height:100%;object-fit:cover;pointer-events:none}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-img{pointer-events:auto}.JSON-Canvas-Viewer .JCV-overlay-container .JCV-parsed-content-wrapper{font-family:sans-serif;box-sizing:border-box;max-width:100%;max-height:100%;padding:10px 6px;pointer-events:none;overflow:hidden;scrollbar-gutter:stable both-edges;display:flex;flex-direction:column;gap:12px}@supports not (scrollbar-gutter: stable both-edges){.JSON-Canvas-Viewer .JCV-overlay-container .JCV-parsed-content-wrapper{padding:10px}}.JSON-Canvas-Viewer .JCV-overlay-container.JCV-active .JCV-parsed-content-wrapper{overflow:auto;pointer-events:auto}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar{width:4px}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-track{background-color:transparent}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb{border-radius:2px;background:#ffffff40}.JSON-Canvas-Viewer .JCV-markdown-content ::-webkit-scrollbar-thumb:hover{background:#1e1e1ebf}.JSON-Canvas-Viewer .JCV-markdown-content p{font-size:16px;line-height:21px}.JSON-Canvas-Viewer .JCV-markdown-content img{width:100%;border-radius:8px}.JSON-Canvas-Viewer .JCV-markdown-content h1{font-size:25px}.JSON-Canvas-Viewer .JCV-markdown-content h2{font-size:23px}.JSON-Canvas-Viewer .JCV-markdown-content h3{font-size:22px}.JSON-Canvas-Viewer .JCV-markdown-content h4{font-size:20px}.JSON-Canvas-Viewer .JCV-markdown-content h5{font-size:19px}.JSON-Canvas-Viewer .JCV-markdown-content h6{font-size:17px}.JSON-Canvas-Viewer .JCV-markdown-content p,.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2,.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4,.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6,.JSON-Canvas-Viewer .JCV-markdown-content ol,.JSON-Canvas-Viewer .JCV-markdown-content ul{margin:0}.JSON-Canvas-Viewer .JCV-markdown-content h1,.JSON-Canvas-Viewer .JCV-markdown-content h2{font-weight:800}.JSON-Canvas-Viewer .JCV-markdown-content h3,.JSON-Canvas-Viewer .JCV-markdown-content h4{font-weight:700}.JSON-Canvas-Viewer .JCV-markdown-content h5,.JSON-Canvas-Viewer .JCV-markdown-content h6{font-weight:600}.JSON-Canvas-Viewer .JCV-markdown-content code{background:#ffffff1a;padding:2px 4px;border-radius:8px}pre .JSON-Canvas-Viewer .JCV-markdown-content code{display:block;box-sizing:border-box;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content pre:has(code),.JSON-Canvas-Viewer .JCV-markdown-content table{margin:6px 0}.JSON-Canvas-Viewer .JCV-markdown-content strong{color:#fe8e7c}.JSON-Canvas-Viewer .JCV-markdown-content em{color:#5affb2}.JSON-Canvas-Viewer .JCV-markdown-content a{text-decoration:none;color:#6dadd0;font-weight:800;font-style:italic;cursor:pointer;transition:var(--contentTransition)}.JSON-Canvas-Viewer .JCV-markdown-content a:hover{color:#86d3fd}.JSON-Canvas-Viewer .JCV-markdown-content hr{height:1px;width:100%;background-color:#fff3;border:none}.JSON-Canvas-Viewer .JCV-markdown-content li{margin:5px 0}.JSON-Canvas-Viewer .JCV-markdown-content ul{padding-left:16px}.JSON-Canvas-Viewer .JCV-markdown-content ol{padding-left:15px;padding-right:7.5px}.JSON-Canvas-Viewer .JCV-markdown-content table{border-collapse:collapse;border-radius:8px;overflow:hidden;width:100%}.JSON-Canvas-Viewer .JCV-markdown-content table th,.JSON-Canvas-Viewer .JCV-markdown-content table td{border:1px solid rgba(255,255,255,.2);padding:6px 10px;background:#ffffff0f;text-align:left}.JSON-Canvas-Viewer .JCV-markdown-content table th{background:#ffffff1f;font-weight:700}";export{e as default};
|
|
2
|
+
//# sourceMappingURL=styles.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={round:function(e,o){const r=10**o;return Math.round(e*r)/r},resizeCanvasForDPR:function(e,o,r){const t=window.devicePixelRatio??1,n=e.getContext("2d");if(!n)throw new Error("[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.");e.width=Math.round(o*t),e.height=Math.round(r*t),n.setTransform(1,0,0,1,0,0),n.scale(t,t)},applyStyles:function(e,o){const r=document.createElement("style");r.innerHTML=o,e.appendChild(r)},drawRoundRect:function(e,o,r,t,n,s){e.beginPath(),e.moveTo(o+s,r),e.lineTo(o+t-s,r),e.quadraticCurveTo(o+t,r,o+t,r+s),e.lineTo(o+t,r+n-s),e.quadraticCurveTo(o+t,r+n,o+t-s,r+n),e.lineTo(o+s,r+n),e.quadraticCurveTo(o,r+n,o,r+n-s),e.lineTo(o,r+s),e.quadraticCurveTo(o,r,o+s,r),e.closePath()},getAnchorCoord:function(e,o){const r=e.x+e.width/2,t=e.y+e.height/2;switch(o){case"top":return{x:r,y:e.y};case"bottom":return{x:r,y:e.y+e.height};case"left":return{x:e.x,y:t};case"right":return{x:e.x+e.width,y:t};default:return{x:r,y:t}}},makeHook:r},o=new Error("[JSONCanvasViewer] Resource hasn't been set up or has been disposed.");function r(e=!1,o=!1){const r=o?async(...o)=>{if(e){const e=Array.from(r.subs).reverse();for(const r of e)await r(...o)}else for(const e of r.subs)await e(...o)}:(...o)=>{if(e){const e=Array.from(r.subs).reverse();for(const r of e)r(...o)}else for(const e of r.subs)e(...o)};return r.subs=/* @__PURE__ */new Set,r.subscribe=e=>{r.subs.add(e)},r.unsubscribe=e=>{r.subs.delete(e)},r}export{e as default,o as destroyError,r as makeHook};
|
|
2
|
+
//# sourceMappingURL=utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.js","sources":["../../src/kernel/utilities.ts"],"sourcesContent":["import type { GeneralArray } from '$/types';\nimport type { JSONCanvasNode } from '@repo/shared';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tmakeHook,\n};\n\nexport const destroyError = new Error(\n\t\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\",\n);\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn { x: midX, y: node.y };\n\t\tcase 'bottom':\n\t\t\treturn { x: midX, y: node.y + node.height };\n\t\tcase 'left':\n\t\t\treturn { x: node.x, y: midY };\n\t\tcase 'right':\n\t\t\treturn { x: node.x + node.width, y: midY };\n\t\tdefault:\n\t\t\treturn { x: midX, y: midY };\n\t}\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio ?? 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx)\n\t\tthrow new Error(\n\t\t\t'[JSONCanvasViewer] This error is unexpected, probably caused uncontrollable runtime errors. Please contact the developer and show how to reproduce.',\n\t\t);\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n\ntype MatchingFunc<Args extends GeneralArray> = (...args: Args) => void | Promise<void>;\nexport type Hook<Args extends GeneralArray = [], Async extends boolean = false> = {\n\t(...args: Args): Async extends true ? Promise<void> : void;\n\tsubs: Set<MatchingFunc<Args>>;\n\tsubscribe(callback: MatchingFunc<Args>): void;\n\tunsubscribe(callback: MatchingFunc<Args>): void;\n};\n\n/**\n * A quick function to create a hook that can be subscribed to and unsubscribed from.\n * Pass your arguments as the type parameter\n *\n * @param reverse - Whether the hook should reverse the execution order or not\n * @param async - Whether the hook is async or not\n * @example const hook = makeHook(true);\n */\nexport function makeHook<Args extends GeneralArray = [], Async extends boolean = false>(\n\treverse: boolean = false,\n\tasync: Async = false as Async,\n) {\n\tconst result = (\n\t\tasync\n\t\t\t? async (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) await callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) await callback(...args);\n\t\t\t\t}\n\t\t\t: (...args: Args) => {\n\t\t\t\t\tif (reverse) {\n\t\t\t\t\t\tconst items = Array.from(result.subs).reverse();\n\t\t\t\t\t\tfor (const callback of items) void callback(...args);\n\t\t\t\t\t} else for (const callback of result.subs) void callback(...args);\n\t\t\t\t}\n\t) as Hook<Args, Async>;\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc<Args>) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n"],"names":["utilities","round","roundedNum","digits","factor","Math","resizeCanvasForDPR","canvas","width","height","dpr","window","devicePixelRatio","ctx","getContext","Error","setTransform","scale","applyStyles","container","styleString","style","document","createElement","innerHTML","appendChild","drawRoundRect","x","y","radius","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","getAnchorCoord","node","side","midX","midY","makeHook","destroyError","reverse","async","result","args","items","Array","from","subs","callback","Set","subscribe","add","unsubscribe","delete"],"mappings":"AAGA,MAAAA,EAAe,CACdC,MAqED,SAAeC,EAAoBC,GAClC,MAAMC,EAAS,IAAMD,EACrB,OAAOE,KAAKJ,MAAMC,EAAaE,GAAUA,CAC1C,EAvECE,mBAuDD,SAA4BC,EAA2BC,EAAeC,GACrE,MAAMC,EAAMC,OAAOC,kBAAoB,EACjCC,EAAMN,EAAOO,WAAW,MAC9B,IAAKD,EACJ,MAAM,IAAIE,MACT,uJAEFR,EAAOC,MAAQH,KAAKJ,MAAMO,EAAQE,GAClCH,EAAOE,OAASJ,KAAKJ,MAAMQ,EAASC,GACpCG,EAAIG,aAAa,EAAG,EAAG,EAAG,EAAG,EAAG,GAChCH,EAAII,MAAMP,EAAKA,EAChB,EAjECQ,YAUD,SAAqBC,EAAqCC,GACzD,MAAMC,EAAQC,SAASC,cAAc,SACrCF,EAAMG,UAAYJ,EAClBD,EAAUM,YAAYJ,EACvB,EAbCK,cAeD,SACCb,EACAc,EACAC,EACApB,EACAC,EACAoB,GAEAhB,EAAIiB,YACJjB,EAAIkB,OAAOJ,EAAIE,EAAQD,GACvBf,EAAImB,OAAOL,EAAInB,EAAQqB,EAAQD,GAC/Bf,EAAIoB,iBAAiBN,EAAInB,EAAOoB,EAAGD,EAAInB,EAAOoB,EAAIC,GAClDhB,EAAImB,OAAOL,EAAInB,EAAOoB,EAAInB,EAASoB,GACnChB,EAAIoB,iBAAiBN,EAAInB,EAAOoB,EAAInB,EAAQkB,EAAInB,EAAQqB,EAAQD,EAAInB,GACpEI,EAAImB,OAAOL,EAAIE,EAAQD,EAAInB,GAC3BI,EAAIoB,iBAAiBN,EAAGC,EAAInB,EAAQkB,EAAGC,EAAInB,EAASoB,GACpDhB,EAAImB,OAAOL,EAAGC,EAAIC,GAClBhB,EAAIoB,iBAAiBN,EAAGC,EAAGD,EAAIE,EAAQD,GACvCf,EAAIqB,WACL,EAjCCC,eAmCD,SAAwBC,EAAsBC,GAC7C,MAAMC,EAAOF,EAAKT,EAAIS,EAAK5B,MAAQ,EAC7B+B,EAAOH,EAAKR,EAAIQ,EAAK3B,OAAS,EACpC,OAAQ4B,GACP,IAAK,MACJ,MAAO,CAAEV,EAAGW,EAAMV,EAAGQ,EAAKR,GAC3B,IAAK,SACJ,MAAO,CAAED,EAAGW,EAAMV,EAAGQ,EAAKR,EAAIQ,EAAK3B,QACpC,IAAK,OACJ,MAAO,CAAEkB,EAAGS,EAAKT,EAAGC,EAAGW,GACxB,IAAK,QACJ,MAAO,CAAEZ,EAAGS,EAAKT,EAAIS,EAAK5B,MAAOoB,EAAGW,GACrC,QACC,MAAO,CAAEZ,EAAGW,EAAMV,EAAGW,GAExB,EAjDCC,YAGYC,EAAe,IAAI1B,MAC/B,wEAiFM,SAASyB,EACfE,GAAmB,EACnBC,GAAe,GAEf,MAAMC,EACLD,EACGA,SAAUE,KACV,GAAIH,EAAS,CACZ,MAAMI,EAAQC,MAAMC,KAAKJ,EAAOK,MAAMP,UACtC,IAAA,MAAWQ,KAAYJ,QAAaI,KAAYL,EACjD,gBAAkBK,KAAYN,EAAOK,WAAYC,KAAYL,IAE7D,IAAIA,KACJ,GAAIH,EAAS,CACZ,MAAMI,EAAQC,MAAMC,KAAKJ,EAAOK,MAAMP,UACtC,IAAA,MAAWQ,KAAYJ,EAAYI,KAAYL,EAChD,gBAAkBK,KAAYN,EAAOK,KAAWC,KAAYL,IAUhE,OAPAD,EAAOK,wBAAWE,IAClBP,EAAOQ,UAAaF,IACnBN,EAAOK,KAAKI,IAAIH,IAEjBN,EAAOU,YAAeJ,IACrBN,EAAOK,KAAKM,OAAOL,IAEbN,CACR"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"../../kernel/BaseModule.js";import e from"../../kernel/Controller.js";import l from"../../kernel/DataManager.js";import s from"../../kernel/InteractionHandler.js";import o,{destroyError as n}from"../../kernel/utilities.js";import i from"./styles.scss.js";const r='<svg viewBox="-5.28 -5.28 34.56 34.56" fill="none"><path d="M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15" stroke-width="2.4" stroke-linecap="round"/></svg>';class a extends t{_controlsPanel=null;_toggleCollapseBtn=null;_toggleFullscreenBtn=null;_zoomOutBtn=null;_zoomSlider=null;_zoomInBtn=null;_resetViewBtn=null;DM;IH;collapsed;get controlsPanel(){if(null===this._controlsPanel)throw n;return this._controlsPanel}get toggleCollapseBtn(){if(null===this._toggleCollapseBtn)throw n;return this._toggleCollapseBtn}get toggleFullscreenBtn(){if(null===this._toggleFullscreenBtn)throw n;return this._toggleFullscreenBtn}get zoomOutBtn(){if(null===this._zoomOutBtn)throw n;return this._zoomOutBtn}get zoomSlider(){if(null===this._zoomSlider)throw n;return this._zoomSlider}get zoomInBtn(){if(null===this._zoomInBtn)throw n;return this._zoomInBtn}get resetViewBtn(){if(null===this._resetViewBtn)throw n;return this._resetViewBtn}constructor(...t){super(...t),this.collapsed=this.options.controlsCollapsed??!1,this.DM=this.container.get(l),this.IH=this.container.get(s),this.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn),this.container.get(e).onRefresh.subscribe(this.updateSlider),this._controlsPanel=document.createElement("div"),this._controlsPanel.className="JCV-controls",this._controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),o.applyStyles(this._controlsPanel,i),this._toggleCollapseBtn=document.createElement("button"),this._toggleCollapseBtn.className="JCV-button JCV-collapse-button JCV-border-shadow-bg",this._toggleCollapseBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._controlsPanel.appendChild(this._toggleCollapseBtn);const n=document.createElement("div");n.className="JCV-controls-content",this._toggleFullscreenBtn=document.createElement("button"),this._toggleFullscreenBtn.className="JCV-button",this._toggleFullscreenBtn.innerHTML=r,n.appendChild(this._toggleFullscreenBtn),this._zoomOutBtn=document.createElement("button"),this.zoomOutBtn.className="JCV-button",this._zoomOutBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12" stroke-width="2" stroke-linecap="round" /></svg>',n.appendChild(this._zoomOutBtn),this._zoomSlider=document.createElement("input"),this._zoomSlider.type="range",this._zoomSlider.className="JCV-zoom-slider",this._zoomSlider.min="-30",this._zoomSlider.max="30",this._zoomSlider.value="0",n.appendChild(this._zoomSlider),this._zoomInBtn=document.createElement("button"),this._zoomInBtn.className="JCV-button",this._zoomInBtn.innerHTML='<svg viewBox="-1.2 -1.2 26.4 26.4"><path d="M6 12h12m-6-6v12" stroke-width="2" stroke-linecap="round" /></svg>',n.appendChild(this._zoomInBtn),this._resetViewBtn=document.createElement("button"),this._resetViewBtn.className="JCV-button",this._resetViewBtn.innerHTML='<svg viewBox="-6 -6 30 30" stroke-width=".08"><path d="m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z" /></svg>',n.appendChild(this._resetViewBtn),this._controlsPanel.appendChild(n),this.DM.data.container.appendChild(this._controlsPanel),this._toggleCollapseBtn.addEventListener("click",this.toggleCollapse),this._zoomInBtn.addEventListener("click",this.zoomIn),this._zoomOutBtn.addEventListener("click",this.zoomOut),this._zoomSlider.addEventListener("input",this.slide),this._resetViewBtn.addEventListener("click",this.DM.resetView),this._toggleFullscreenBtn.addEventListener("click",this.toggleFullscreen),this.augment({toggleControlsCollapse:this.toggleCollapse}),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.controlsPanel.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateSlider()};zoomIn=()=>this.IH.zoom(1.3,this.DM.middleViewer());zoomOut=()=>this.IH.zoom(1/1.3,this.DM.middleViewer());slide=()=>this.IH.trueZoom(1.1**Number(this.zoomSlider.value)/this.DM.data.scale,this.DM.middleViewer());updateFullscreenBtn=t=>{this.toggleFullscreenBtn.innerHTML="enter"===t?'<svg viewBox="-40.32 -40.32 176.64 176.64"><path d="M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z"/></svg>':r};toggleFullscreen=()=>this.DM.toggleFullscreen();updateSlider=()=>{this.collapsed||(this.zoomSlider.value=String(this.scaleToSlider(this.DM.data.scale)))};scaleToSlider=t=>Math.log(t)/Math.log(1.1);dispose=()=>{this.toggleCollapseBtn.removeEventListener("click",this.toggleCollapse),this.zoomInBtn.removeEventListener("click",this.zoomIn),this.zoomOutBtn.removeEventListener("click",this.zoomOut),this.zoomSlider.removeEventListener("input",this.slide),this.resetViewBtn.removeEventListener("click",this.DM.resetView),this.toggleFullscreenBtn.removeEventListener("click",this.toggleFullscreen),this.controlsPanel.remove(),this._controlsPanel=null,this._toggleCollapseBtn=null,this._zoomInBtn=null,this._zoomOutBtn=null,this._zoomSlider=null,this._resetViewBtn=null,this._toggleFullscreenBtn=null}}export{a as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/modules/Controls/index.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tcontrolsCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleControlsCollapse: Controls['toggleCollapse'];\n}\n\nconst resetIcon =\n\t'<svg viewBox=\"-6 -6 30 30\" stroke-width=\".08\"><path d=\"m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z\" /></svg>';\nconst enterFullscreenIcon =\n\t'<svg viewBox=\"-5.28 -5.28 34.56 34.56\" fill=\"none\"><path d=\"M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15\" stroke-width=\"2.4\" stroke-linecap=\"round\"/></svg>';\nconst exitFullscreenIcon =\n\t'<svg viewBox=\"-40.32 -40.32 176.64 176.64\"><path d=\"M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z\"/></svg>';\nconst zoomInIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12m-6-6v12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst zoomOutIcon =\n\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Controls extends BaseModule<Options, Augmentation> {\n\tprivate _controlsPanel: HTMLDivElement | null = null;\n\tprivate _toggleCollapseBtn: HTMLButtonElement | null = null;\n\tprivate _toggleFullscreenBtn: HTMLButtonElement | null = null;\n\tprivate _zoomOutBtn: HTMLButtonElement | null = null;\n\tprivate _zoomSlider: HTMLInputElement | null = null;\n\tprivate _zoomInBtn: HTMLButtonElement | null = null;\n\tprivate _resetViewBtn: HTMLButtonElement | null = null;\n\tprivate DM: DataManager;\n\tprivate IH: InteractionHandler;\n\tprivate collapsed: boolean;\n\n\tprivate get controlsPanel() {\n\t\tif (this._controlsPanel === null) throw destroyError;\n\t\treturn this._controlsPanel;\n\t}\n\tprivate get toggleCollapseBtn() {\n\t\tif (this._toggleCollapseBtn === null) throw destroyError;\n\t\treturn this._toggleCollapseBtn;\n\t}\n\tprivate get toggleFullscreenBtn() {\n\t\tif (this._toggleFullscreenBtn === null) throw destroyError;\n\t\treturn this._toggleFullscreenBtn;\n\t}\n\tprivate get zoomOutBtn() {\n\t\tif (this._zoomOutBtn === null) throw destroyError;\n\t\treturn this._zoomOutBtn;\n\t}\n\tprivate get zoomSlider() {\n\t\tif (this._zoomSlider === null) throw destroyError;\n\t\treturn this._zoomSlider;\n\t}\n\tprivate get zoomInBtn() {\n\t\tif (this._zoomInBtn === null) throw destroyError;\n\t\treturn this._zoomInBtn;\n\t}\n\tprivate get resetViewBtn() {\n\t\tif (this._resetViewBtn === null) throw destroyError;\n\t\treturn this._resetViewBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.controlsCollapsed ?? false;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler);\n\t\tthis.DM.onToggleFullscreen.subscribe(this.updateFullscreenBtn);\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.updateSlider);\n\n\t\tthis._controlsPanel = document.createElement('div');\n\t\tthis._controlsPanel.className = 'JCV-controls';\n\t\tthis._controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\n\t\tutilities.applyStyles(this._controlsPanel, style);\n\n\t\tthis._toggleCollapseBtn = document.createElement('button');\n\t\tthis._toggleCollapseBtn.className = 'JCV-button JCV-collapse-button JCV-border-shadow-bg';\n\t\tthis._toggleCollapseBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._controlsPanel.appendChild(this._toggleCollapseBtn);\n\n\t\tconst controlsContent = document.createElement('div');\n\t\tcontrolsContent.className = 'JCV-controls-content';\n\n\t\tthis._toggleFullscreenBtn = document.createElement('button');\n\t\tthis._toggleFullscreenBtn.className = 'JCV-button';\n\t\tthis._toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t\tcontrolsContent.appendChild(this._toggleFullscreenBtn);\n\n\t\tthis._zoomOutBtn = document.createElement('button');\n\t\tthis.zoomOutBtn.className = 'JCV-button';\n\t\tthis._zoomOutBtn.innerHTML = zoomOutIcon;\n\t\tcontrolsContent.appendChild(this._zoomOutBtn);\n\n\t\tthis._zoomSlider = document.createElement('input');\n\t\tthis._zoomSlider.type = 'range';\n\t\tthis._zoomSlider.className = 'JCV-zoom-slider';\n\t\tthis._zoomSlider.min = '-30';\n\t\tthis._zoomSlider.max = '30';\n\t\tthis._zoomSlider.value = '0';\n\t\tcontrolsContent.appendChild(this._zoomSlider);\n\n\t\tthis._zoomInBtn = document.createElement('button');\n\t\tthis._zoomInBtn.className = 'JCV-button';\n\t\tthis._zoomInBtn.innerHTML = zoomInIcon;\n\t\tcontrolsContent.appendChild(this._zoomInBtn);\n\n\t\tthis._resetViewBtn = document.createElement('button');\n\t\tthis._resetViewBtn.className = 'JCV-button';\n\t\tthis._resetViewBtn.innerHTML = resetIcon;\n\t\tcontrolsContent.appendChild(this._resetViewBtn);\n\n\t\tthis._controlsPanel.appendChild(controlsContent);\n\n\t\tthis.DM.data.container.appendChild(this._controlsPanel);\n\n\t\tthis._toggleCollapseBtn.addEventListener('click', this.toggleCollapse);\n\t\tthis._zoomInBtn.addEventListener('click', this.zoomIn);\n\t\tthis._zoomOutBtn.addEventListener('click', this.zoomOut);\n\t\tthis._zoomSlider.addEventListener('input', this.slide);\n\t\tthis._resetViewBtn.addEventListener('click', this.DM.resetView);\n\t\tthis._toggleFullscreenBtn.addEventListener('click', this.toggleFullscreen);\n\n\t\tthis.augment({ toggleControlsCollapse: this.toggleCollapse });\n\t\tthis.onDispose(this.dispose);\n\t}\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.controlsPanel.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateSlider();\n\t};\n\tprivate zoomIn = () => this.IH.zoom(1.3, this.DM.middleViewer());\n\tprivate zoomOut = () => this.IH.zoom(1 / 1.3, this.DM.middleViewer());\n\tprivate slide = () =>\n\t\tthis.IH.trueZoom(\n\t\t\t1.1 ** Number(this.zoomSlider.value) / this.DM.data.scale,\n\t\t\tthis.DM.middleViewer(),\n\t\t);\n\n\tprivate updateFullscreenBtn = (enter: 'enter' | 'exit') => {\n\t\tif (enter === 'enter') this.toggleFullscreenBtn.innerHTML = exitFullscreenIcon;\n\t\telse this.toggleFullscreenBtn.innerHTML = enterFullscreenIcon;\n\t};\n\tprivate toggleFullscreen = () => this.DM.toggleFullscreen();\n\n\tprivate updateSlider = () => {\n\t\tif (this.collapsed) return;\n\t\tthis.zoomSlider.value = String(this.scaleToSlider(this.DM.data.scale));\n\t};\n\tprivate scaleToSlider = (scale: number) => Math.log(scale) / Math.log(1.1);\n\n\tprivate dispose = () => {\n\t\tthis.toggleCollapseBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.zoomInBtn.removeEventListener('click', this.zoomIn);\n\t\tthis.zoomOutBtn.removeEventListener('click', this.zoomOut);\n\t\tthis.zoomSlider.removeEventListener('input', this.slide);\n\t\tthis.resetViewBtn.removeEventListener('click', this.DM.resetView);\n\t\tthis.toggleFullscreenBtn.removeEventListener('click', this.toggleFullscreen);\n\t\tthis.controlsPanel.remove();\n\t\tthis._controlsPanel = null;\n\t\tthis._toggleCollapseBtn = null;\n\t\tthis._zoomInBtn = null;\n\t\tthis._zoomOutBtn = null;\n\t\tthis._zoomSlider = null;\n\t\tthis._resetViewBtn = null;\n\t\tthis._toggleFullscreenBtn = null;\n\t};\n}\n"],"names":["enterFullscreenIcon","Controls","BaseModule","_controlsPanel","_toggleCollapseBtn","_toggleFullscreenBtn","_zoomOutBtn","_zoomSlider","_zoomInBtn","_resetViewBtn","DM","IH","collapsed","controlsPanel","this","destroyError","toggleCollapseBtn","toggleFullscreenBtn","zoomOutBtn","zoomSlider","zoomInBtn","resetViewBtn","constructor","args","super","options","controlsCollapsed","container","get","DataManager","InteractionHandler","onToggleFullscreen","subscribe","updateFullscreenBtn","Controller","onRefresh","updateSlider","document","createElement","className","classList","toggle","utilities","applyStyles","style","innerHTML","appendChild","controlsContent","type","min","max","value","data","addEventListener","toggleCollapse","zoomIn","zoomOut","slide","resetView","toggleFullscreen","augment","toggleControlsCollapse","onDispose","dispose","zoom","middleViewer","trueZoom","Number","scale","enter","String","scaleToSlider","Math","log","removeEventListener","remove"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const r=".JSON-Canvas-Viewer>.JCV-controls{position:absolute;top:10px;right:10px;display:flex;align-items:center;transition:transform .2s;border-radius:8px;gap:10px}.JSON-Canvas-Viewer>.JCV-controls.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-controls .JCV-controls-content{display:flex;gap:1px;align-items:center;border-radius:8px;overflow:hidden;background:var(--border);box-shadow:var(--shadow);outline:1px solid var(--border)}.JSON-Canvas-Viewer>.JCV-controls .JCV-zoom-slider{width:100px;margin:0 10px}";export{r as default};
|
|
2
|
+
//# sourceMappingURL=styles.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as e}from"../../kernel/BaseModule.js";import s from"../../kernel/Controller.js";import t from"../../kernel/DataManager.js";import n,{destroyError as a}from"../../kernel/utilities.js";import i from"./styles.scss.js";class r extends e{_debugPanel=null;DM;get debugPanel(){if(!this._debugPanel)throw a;return this._debugPanel}constructor(...e){super(...e),this.DM=this.container.get(t),this.container.get(s).onRefresh.subscribe(this.update),this._debugPanel=document.createElement("div"),this._debugPanel.className="JCV-debug-panel JCV-border-shadow-bg";const a=this.DM.data.container;n.applyStyles(a,i),a.appendChild(this._debugPanel),this.onDispose(this.dispose)}update=()=>{const e=n.round,s=this.DM.data;this.debugPanel.innerHTML=`<p>Scale: ${e(s.scale,3)}</p><p>Offset: ${e(s.offsetX,1)}, ${e(s.offsetY,1)}</p>`};dispose=()=>{this.debugPanel.remove(),this._debugPanel=null}}export{r as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/modules/DebugPanel/index.ts"],"sourcesContent":["import { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\nexport default class DebugPanel extends BaseModule {\n\tprivate _debugPanel: HTMLDivElement | null = null;\n\tprivate DM: DataManager;\n\n\tprivate get debugPanel() {\n\t\tif (!this._debugPanel) throw destroyError;\n\t\treturn this._debugPanel;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.update);\n\t\tthis._debugPanel = document.createElement('div');\n\t\tthis._debugPanel.className = 'JCV-debug-panel JCV-border-shadow-bg';\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tutilities.applyStyles(HTMLContainer, style);\n\t\tHTMLContainer.appendChild(this._debugPanel);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate update = () => {\n\t\tconst round = utilities.round;\n\t\tconst data = this.DM.data;\n\t\tthis.debugPanel.innerHTML = `<p>Scale: ${round(data.scale, 3)}</p><p>Offset: ${round(data.offsetX, 1)}, ${round(data.offsetY, 1)}</p>`;\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.debugPanel.remove();\n\t\tthis._debugPanel = null;\n\t};\n}\n"],"names":["DebugPanel","BaseModule","_debugPanel","DM","debugPanel","this","destroyError","constructor","args","super","container","get","DataManager","Controller","onRefresh","subscribe","update","document","createElement","className","HTMLContainer","data","utilities","applyStyles","style","appendChild","onDispose","dispose","round","innerHTML","scale","offsetX","offsetY","remove"],"mappings":"yOAMA,MAAqBA,UAAmBC,EAC/BC,YAAqC,KACrCC,GAER,cAAYC,GACX,IAAKC,KAAKH,YAAa,MAAMI,EAC7B,OAAOD,KAAKH,WACb,CAEA,WAAAK,IAAeC,GACdC,SAASD,GACTH,KAAKF,GAAKE,KAAKK,UAAUC,IAAIC,GAC7BP,KAAKK,UAAUC,IAAIE,GAAYC,UAAUC,UAAUV,KAAKW,QACxDX,KAAKH,YAAce,SAASC,cAAc,OAC1Cb,KAAKH,YAAYiB,UAAY,uCAC7B,MAAMC,EAAgBf,KAAKF,GAAGkB,KAAKX,UACnCY,EAAUC,YAAYH,EAAeI,GACrCJ,EAAcK,YAAYpB,KAAKH,aAC/BG,KAAKqB,UAAUrB,KAAKsB,QACrB,CAEQX,OAAS,KAChB,MAAMY,EAAQN,EAAUM,MAClBP,EAAOhB,KAAKF,GAAGkB,KACrBhB,KAAKD,WAAWyB,UAAY,aAAaD,EAAMP,EAAKS,MAAO,oBAAoBF,EAAMP,EAAKU,QAAS,OAAOH,EAAMP,EAAKW,QAAS,UAGvHL,QAAU,KACjBtB,KAAKD,WAAW6B,SAChB5B,KAAKH,YAAc"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=".JSON-Canvas-Viewer>.JCV-debug-panel{position:absolute;bottom:12px;left:12px;border-radius:12px;padding:12px;color:var(--text);font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);pointer-events:none}";export{e as default};
|
|
2
|
+
//# sourceMappingURL=styles.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as i}from"../../kernel/BaseModule.js";import t from"../../kernel/Controller.js";import e from"../../kernel/DataManager.js";import n from"../../kernel/StyleManager.js";import a,{destroyError as s}from"../../kernel/utilities.js";import m from"./styles.scss.js";class o extends i{_minimapCtx=null;_viewportRectangle=null;_minimap=null;_minimapContainer=null;_toggleMinimapBtn=null;minimapCache={scale:1,centerX:0,centerY:0};DM;SM;collapsed;get minimap(){if(null===this._minimap)throw s;return this._minimap}get minimapCtx(){if(null===this._minimapCtx)throw s;return this._minimapCtx}get viewportRectangle(){if(null===this._viewportRectangle)throw s;return this._viewportRectangle}get minimapContainer(){if(null===this._minimapContainer)throw s;return this._minimapContainer}get toggleMinimapBtn(){if(null===this._toggleMinimapBtn)throw s;return this._toggleMinimapBtn}constructor(...i){super(...i),this.collapsed=this.options.minimapCollapsed??!1,this.container.get(t).onRefresh.subscribe(this.updateViewportRectangle),this.DM=this.container.get(e),this.SM=this.container.get(n),this._minimapContainer=document.createElement("div"),this._minimapContainer.className="JCV-minimap-container",a.applyStyles(this._minimapContainer,m),this._toggleMinimapBtn=document.createElement("button"),this._toggleMinimapBtn.className="JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg",this._toggleMinimapBtn.innerHTML='<svg viewBox="-3.6 -3.6 31.2 31.2" stroke-width=".4"><path d="M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z" /></svg>',this._minimapContainer.appendChild(this._toggleMinimapBtn),this._minimap=document.createElement("div"),this._minimap.className="JCV-minimap JCV-border-shadow-bg";const s=document.createElement("canvas");s.className="JCV-minimap-canvas",s.width=200,s.height=150,this._minimap.appendChild(s),this._minimapCtx=s.getContext("2d"),this._viewportRectangle=document.createElement("div"),this._viewportRectangle.className="JCV-viewport-rectangle",this._minimap.appendChild(this._viewportRectangle),this._minimapContainer.appendChild(this._minimap),this.DM.data.container.appendChild(this._minimapContainer),this._minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this._toggleMinimapBtn.addEventListener("click",this.toggleCollapse),a.resizeCanvasForDPR(s,s.width,s.height),this.augment({toggleMinimapCollapse:this.toggleCollapse}),this.onStart(this.start),this.onRestart(this.start),this.onDispose(this.dispose)}toggleCollapse=()=>{this.collapsed=!this.collapsed,this.minimapContainer.classList.toggle("JCV-collapsed",this.collapsed),this.collapsed||this.updateViewportRectangle()};start=()=>{const i=this.DM.data.nodeBounds;if(!i)return;const t=this.minimap.clientWidth,e=this.minimap.clientHeight,n=t/i.width,a=e/i.height;this.minimapCache.scale=.9*Math.min(n,a),this.minimapCache.centerX=t/2,this.minimapCache.centerY=e/2,this.minimapCtx.clearRect(0,0,t,e),this.minimapCtx.save(),this.minimapCtx.translate(this.minimapCache.centerX,this.minimapCache.centerY),this.minimapCtx.scale(this.minimapCache.scale,this.minimapCache.scale),this.minimapCtx.translate(-i.centerX,-i.centerY);const s=this.DM.data.canvasData;for(const m of s.edges)this.drawMinimapEdge(m);for(const m of s.nodes)this.drawMinimapNode(m);this.minimapCtx.restore()};drawMinimapNode=i=>{const t=this.SM.getColor(i.color);this.minimapCtx.fillStyle=t.border,a.drawRoundRect(this.minimapCtx,i.x,i.y,i.width,i.height,25),this.minimapCtx.fill()};drawMinimapEdge=i=>{const t=this.DM.data.nodeMap,e=t[i.fromNode].ref,n=t[i.toNode].ref;if(!e||!n)return;const{x:s,y:m}=a.getAnchorCoord(e,i.fromSide),{x:o,y:l}=a.getAnchorCoord(n,i.toSide);this.minimapCtx.beginPath(),this.minimapCtx.moveTo(s,m),this.minimapCtx.lineTo(o,l),this.minimapCtx.strokeStyle=this.SM.getColor(i.color).active,this.minimapCtx.lineWidth=10,this.minimapCtx.stroke()};updateViewportRectangle=()=>{if(this.collapsed)return;const i=this.DM.data.nodeBounds,t=this.DM.data.container,e=this.DM.data.scale;if(!i)return;const n=t.clientWidth/e,a=t.clientHeight/e,s=-this.DM.data.offsetX/e+t.clientWidth/(2*e),m=-this.DM.data.offsetY/e+t.clientHeight/(2*e),o=this.minimapCache.centerX+(s-n/2-i.centerX)*this.minimapCache.scale,l=this.minimapCache.centerY+(m-a/2-i.centerY)*this.minimapCache.scale,h=n*this.minimapCache.scale,p=a*this.minimapCache.scale;this.viewportRectangle.style.left=`${o}px`,this.viewportRectangle.style.top=`${l}px`,this.viewportRectangle.style.width=`${h}px`,this.viewportRectangle.style.height=`${p}px`};dispose=()=>{this.toggleMinimapBtn.removeEventListener("click",this.toggleCollapse),this.minimapCtx.clearRect(0,0,this.minimap.clientWidth,this.minimap.clientHeight),this.minimapContainer.remove(),this._minimapContainer=null,this._toggleMinimapBtn=null,this._viewportRectangle=null,this._minimap=null}}export{o as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/modules/Minimap/index.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { JSONCanvasEdge, JSONCanvasNode } from '@repo/shared';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tminimapCollapsed?: boolean;\n}\n\ninterface Augmentation {\n\ttoggleMinimapCollapse: Minimap['toggleCollapse'];\n}\n\nconst toggleCollapseIcon =\n\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\nexport default class Minimap extends BaseModule<Options, Augmentation> {\n\tprivate _minimapCtx: CanvasRenderingContext2D | null = null;\n\tprivate _viewportRectangle: HTMLDivElement | null = null;\n\tprivate _minimap: HTMLDivElement | null = null;\n\tprivate _minimapContainer: HTMLDivElement | null = null;\n\tprivate _toggleMinimapBtn: HTMLButtonElement | null = null;\n\tprivate minimapCache: { scale: number; centerX: number; centerY: number } = {\n\t\tscale: 1,\n\t\tcenterX: 0,\n\t\tcenterY: 0,\n\t};\n\tprivate DM: DataManager;\n\tprivate SM: StyleManager;\n\tprivate collapsed: boolean;\n\n\tprivate get minimap() {\n\t\tif (this._minimap === null) throw destroyError;\n\t\treturn this._minimap;\n\t}\n\tprivate get minimapCtx() {\n\t\tif (this._minimapCtx === null) throw destroyError;\n\t\treturn this._minimapCtx;\n\t}\n\tprivate get viewportRectangle() {\n\t\tif (this._viewportRectangle === null) throw destroyError;\n\t\treturn this._viewportRectangle;\n\t}\n\tprivate get minimapContainer() {\n\t\tif (this._minimapContainer === null) throw destroyError;\n\t\treturn this._minimapContainer;\n\t}\n\tprivate get toggleMinimapBtn() {\n\t\tif (this._toggleMinimapBtn === null) throw destroyError;\n\t\treturn this._toggleMinimapBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.minimapCollapsed ?? false;\n\t\tthis.container.get(Controller).onRefresh.subscribe(this.updateViewportRectangle);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\n\t\tthis._minimapContainer = document.createElement('div');\n\t\tthis._minimapContainer.className = 'JCV-minimap-container';\n\n\t\tutilities.applyStyles(this._minimapContainer, style);\n\n\t\tthis._toggleMinimapBtn = document.createElement('button');\n\t\tthis._toggleMinimapBtn.className =\n\t\t\t'JCV-button JCV-toggle-minimap JCV-collapse-button JCV-border-shadow-bg';\n\t\tthis._toggleMinimapBtn.innerHTML = toggleCollapseIcon;\n\t\tthis._minimapContainer.appendChild(this._toggleMinimapBtn);\n\n\t\tthis._minimap = document.createElement('div');\n\t\tthis._minimap.className = 'JCV-minimap JCV-border-shadow-bg';\n\t\tconst minimapCanvas = document.createElement('canvas');\n\t\tminimapCanvas.className = 'JCV-minimap-canvas';\n\t\tminimapCanvas.width = 200;\n\t\tminimapCanvas.height = 150;\n\n\t\tthis._minimap.appendChild(minimapCanvas);\n\t\tthis._minimapCtx = minimapCanvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis._viewportRectangle = document.createElement('div');\n\t\tthis._viewportRectangle.className = 'JCV-viewport-rectangle';\n\t\tthis._minimap.appendChild(this._viewportRectangle);\n\t\tthis._minimapContainer.appendChild(this._minimap);\n\n\t\tthis.DM.data.container.appendChild(this._minimapContainer);\n\n\t\tthis._minimapContainer.classList.toggle('JCV-collapsed', this.collapsed);\n\n\t\tthis._toggleMinimapBtn.addEventListener('click', this.toggleCollapse);\n\t\tutilities.resizeCanvasForDPR(minimapCanvas, minimapCanvas.width, minimapCanvas.height);\n\n\t\tthis.augment({ toggleMinimapCollapse: this.toggleCollapse });\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.start);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.minimapContainer.classList.toggle('JCV-collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateViewportRectangle();\n\t};\n\n\tprivate start = () => {\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tif (!bounds) return;\n\t\tconst displayWidth = this.minimap.clientWidth;\n\t\tconst displayHeight = this.minimap.clientHeight;\n\t\tconst scaleX = displayWidth / bounds.width;\n\t\tconst scaleY = displayHeight / bounds.height;\n\t\tthis.minimapCache.scale = Math.min(scaleX, scaleY) * 0.9;\n\t\tthis.minimapCache.centerX = displayWidth / 2;\n\t\tthis.minimapCache.centerY = displayHeight / 2;\n\t\tthis.minimapCtx.clearRect(0, 0, displayWidth, displayHeight);\n\t\tthis.minimapCtx.save();\n\t\tthis.minimapCtx.translate(this.minimapCache.centerX, this.minimapCache.centerY);\n\t\tthis.minimapCtx.scale(this.minimapCache.scale, this.minimapCache.scale);\n\t\tthis.minimapCtx.translate(-bounds.centerX, -bounds.centerY);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tfor (const edge of canvasData.edges) this.drawMinimapEdge(edge);\n\t\tfor (const node of canvasData.nodes) this.drawMinimapNode(node);\n\t\tthis.minimapCtx.restore();\n\t};\n\n\tprivate drawMinimapNode = (node: JSONCanvasNode) => {\n\t\tconst colors = this.SM.getColor(node.color);\n\t\tconst radius = 25;\n\t\tthis.minimapCtx.fillStyle = colors.border;\n\t\tutilities.drawRoundRect(this.minimapCtx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.minimapCtx.fill();\n\t};\n\n\tprivate drawMinimapEdge = (edge: JSONCanvasEdge) => {\n\t\tconst canvasMap = this.DM.data.nodeMap;\n\t\tconst fromNode = canvasMap[edge.fromNode].ref;\n\t\tconst toNode = canvasMap[edge.toNode].ref;\n\t\tif (!fromNode || !toNode) return;\n\t\tconst { x: startX, y: startY } = utilities.getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = utilities.getAnchorCoord(toNode, edge.toSide);\n\t\tthis.minimapCtx.beginPath();\n\t\tthis.minimapCtx.moveTo(startX, startY);\n\t\tthis.minimapCtx.lineTo(endX, endY);\n\t\tthis.minimapCtx.strokeStyle = this.SM.getColor(edge.color).active;\n\t\tthis.minimapCtx.lineWidth = 10;\n\t\tthis.minimapCtx.stroke();\n\t};\n\n\tprivate updateViewportRectangle = () => {\n\t\tif (this.collapsed) return;\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tconst container = this.DM.data.container;\n\t\tconst scale = this.DM.data.scale;\n\t\tif (!bounds) return;\n\t\tconst viewWidth = container.clientWidth / scale;\n\t\tconst viewHeight = container.clientHeight / scale;\n\t\tconst viewportCenterX = -this.DM.data.offsetX / scale + container.clientWidth / (2 * scale);\n\t\tconst viewportCenterY =\n\t\t\t-this.DM.data.offsetY / scale + container.clientHeight / (2 * scale);\n\t\tconst viewRectX =\n\t\t\tthis.minimapCache.centerX +\n\t\t\t(viewportCenterX - viewWidth / 2 - bounds.centerX) * this.minimapCache.scale;\n\t\tconst viewRectY =\n\t\t\tthis.minimapCache.centerY +\n\t\t\t(viewportCenterY - viewHeight / 2 - bounds.centerY) * this.minimapCache.scale;\n\t\tconst viewRectWidth = viewWidth * this.minimapCache.scale;\n\t\tconst viewRectHeight = viewHeight * this.minimapCache.scale;\n\t\tthis.viewportRectangle.style.left = `${viewRectX}px`;\n\t\tthis.viewportRectangle.style.top = `${viewRectY}px`;\n\t\tthis.viewportRectangle.style.width = `${viewRectWidth}px`;\n\t\tthis.viewportRectangle.style.height = `${viewRectHeight}px`;\n\t};\n\n\tprivate dispose = () => {\n\t\tthis.toggleMinimapBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.minimapCtx.clearRect(0, 0, this.minimap.clientWidth, this.minimap.clientHeight);\n\t\tthis.minimapContainer.remove();\n\t\tthis._minimapContainer = null;\n\t\tthis._toggleMinimapBtn = null;\n\t\tthis._viewportRectangle = null;\n\t\tthis._minimap = null;\n\t};\n}\n"],"names":["Minimap","BaseModule","_minimapCtx","_viewportRectangle","_minimap","_minimapContainer","_toggleMinimapBtn","minimapCache","scale","centerX","centerY","DM","SM","collapsed","minimap","this","destroyError","minimapCtx","viewportRectangle","minimapContainer","toggleMinimapBtn","constructor","args","super","options","minimapCollapsed","container","get","Controller","onRefresh","subscribe","updateViewportRectangle","DataManager","StyleManager","document","createElement","className","utilities","applyStyles","style","innerHTML","appendChild","minimapCanvas","width","height","getContext","data","classList","toggle","addEventListener","toggleCollapse","resizeCanvasForDPR","augment","toggleMinimapCollapse","onStart","start","onRestart","onDispose","dispose","bounds","nodeBounds","displayWidth","clientWidth","displayHeight","clientHeight","scaleX","scaleY","Math","min","clearRect","save","translate","canvasData","edge","edges","drawMinimapEdge","node","nodes","drawMinimapNode","restore","colors","getColor","color","fillStyle","border","drawRoundRect","x","y","fill","canvasMap","nodeMap","fromNode","ref","toNode","startX","startY","getAnchorCoord","fromSide","endX","endY","toSide","beginPath","moveTo","lineTo","strokeStyle","active","lineWidth","stroke","viewWidth","viewHeight","viewportCenterX","offsetX","viewportCenterY","offsetY","viewRectX","viewRectY","viewRectWidth","viewRectHeight","left","top","removeEventListener","remove"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const n=".JSON-Canvas-Viewer>.JCV-minimap-container{position:absolute;bottom:10px;right:10px;display:flex;pointer-events:none;transition:transform .2s}.JSON-Canvas-Viewer>.JCV-minimap-container.JCV-collapsed{transform:translate(calc(100% - 30px))}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-toggle-minimap{margin:auto 10px 0 0;pointer-events:auto}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap{position:relative;pointer-events:none;width:200px;height:150px;overflow:hidden;border-radius:12px;transform-origin:0 0}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-minimap-canvas{width:100%;height:100%}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-minimap .JCV-viewport-rectangle{position:absolute;top:0;left:0;pointer-events:none;border-radius:6px;box-sizing:border-box;border:2px dashed var(--text)}@container (max-width: 768px){.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap{transform:scale(.6)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px)}.collapsed .JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-toggle-minimap{transform:translateY(-60px) rotate(180deg)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container{transform:translateY(60px) translate(80px)}.JSON-Canvas-Viewer>.JCV-minimap-container .JCV-container .JCV-minimap-container.JCV-collapsed{transform:translateY(60px) translate(calc(100% - 32px))}}";export{n as default};
|
|
2
|
+
//# sourceMappingURL=styles.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{BaseModule as t}from"../../kernel/BaseModule.js";import e from"../../kernel/DataManager.js";import n,{destroyError as i}from"../../kernel/utilities.js";import o from"./styles.scss.js";class s extends t{_preventionContainer=null;preventMt=!1;DM;preventMistouch={record:!1,lastX:0,lastY:0,initialX:0,initialY:0};get preventionContainer(){if(null===this._preventionContainer)throw i;return this._preventionContainer}constructor(...t){super(...t);const i=document.createElement("div");i.className="JCV-prevention-banner JCV-border-shadow-bg",i.textContent=this.options.mistouchPreventerBannerText??"Click on to unlock.",this.DM=this.container.get(e),this._preventionContainer=document.createElement("div"),this._preventionContainer.className="JCV-prevention-container JCV-hidden JCV-full JCV-flex-center",n.applyStyles(this._preventionContainer,o),this._preventionContainer.appendChild(i),this.DM.data.container.appendChild(this._preventionContainer),this.options.preventMistouchAtStart&&this.startPrevention(),window.addEventListener("pointerdown",this.onPointerDown),window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp),this.augment({startMistouchPrevention:this.startPrevention,endMistouchPrevention:this.endPrevention}),this.onDispose(this.dispose)}onPointerDown=t=>{const e=this.DM.data.container.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?this.preventMt||this.startPrevention():this.preventMt&&(this.preventMistouch.initialX=t.clientX,this.preventMistouch.initialY=t.clientY,this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY,this.preventMistouch.record=!0)};onPointerMove=t=>{this.preventMistouch.record&&(this.preventMistouch.lastX=t.clientX,this.preventMistouch.lastY=t.clientY)};onPointerUp=()=>{this.preventMistouch.record&&(this.preventMistouch.record=!1,Math.abs(this.preventMistouch.lastX-this.preventMistouch.initialX)+Math.abs(this.preventMistouch.lastY-this.preventMistouch.initialY)<5&&this.endPrevention())};startPrevention=()=>{this.preventionContainer.classList.remove("JCV-hidden"),this.DM.data.container.classList.add("JCV-numb"),this.preventMt=!0};endPrevention=()=>{this.preventMt=!1,this.preventionContainer.classList.add("JCV-hidden"),setTimeout(()=>this.DM.data.container.classList.remove("JCV-numb"),50)};dispose=()=>{window.removeEventListener("pointerdown",this.onPointerDown),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),this.preventionContainer.remove(),this._preventionContainer=null}}export{s as default};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/modules/MistouchPreventer/index.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport { type BaseArgs, BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport utilities, { destroyError } from '$/utilities';\nimport style from './styles.scss?inline';\n\ninterface Options extends BaseOptions {\n\tpreventMistouchAtStart?: boolean;\n\tmistouchPreventerBannerText?: string;\n}\n\ninterface Augmentation {\n\tstartMistouchPrevention: MistouchPreventer['startPrevention'];\n\tendMistouchPrevention: MistouchPreventer['endPrevention'];\n}\n\nexport default class MistouchPreventer extends BaseModule<Options, Augmentation> {\n\tprivate _preventionContainer: HTMLDivElement | null = null;\n\tprivate preventMt: boolean = false;\n\tprivate DM: DataManager;\n\tprivate preventMistouch: {\n\t\trecord: boolean;\n\t\tlastX: number;\n\t\tlastY: number;\n\t\tinitialX: number;\n\t\tinitialY: number;\n\t} = {\n\t\trecord: false,\n\t\tlastX: 0,\n\t\tlastY: 0,\n\t\tinitialX: 0,\n\t\tinitialY: 0,\n\t};\n\n\tprivate get preventionContainer() {\n\t\tif (this._preventionContainer === null) throw destroyError;\n\t\treturn this._preventionContainer;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\n\t\tconst preventionBanner = document.createElement('div');\n\t\tpreventionBanner.className = 'JCV-prevention-banner JCV-border-shadow-bg';\n\t\tpreventionBanner.textContent =\n\t\t\tthis.options.mistouchPreventerBannerText ?? 'Click on to unlock.';\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._preventionContainer = document.createElement('div');\n\t\tthis._preventionContainer.className =\n\t\t\t'JCV-prevention-container JCV-hidden JCV-full JCV-flex-center';\n\n\t\tutilities.applyStyles(this._preventionContainer, style);\n\t\tthis._preventionContainer.appendChild(preventionBanner);\n\t\tthis.DM.data.container.appendChild(this._preventionContainer);\n\n\t\tif (this.options.preventMistouchAtStart) this.startPrevention();\n\n\t\twindow.addEventListener('pointerdown', this.onPointerDown);\n\t\twindow.addEventListener('pointermove', this.onPointerMove);\n\t\twindow.addEventListener('pointerup', this.onPointerUp);\n\n\t\tthis.augment({\n\t\t\tstartMistouchPrevention: this.startPrevention,\n\t\t\tendMistouchPrevention: this.endPrevention,\n\t\t});\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate onPointerDown = (e: PointerEvent) => {\n\t\tconst bounds = this.DM.data.container.getBoundingClientRect();\n\t\tif (\n\t\t\te.clientX < bounds.left ||\n\t\t\te.clientX > bounds.right ||\n\t\t\te.clientY < bounds.top ||\n\t\t\te.clientY > bounds.bottom\n\t\t) {\n\t\t\tif (!this.preventMt) this.startPrevention();\n\t\t} else if (this.preventMt) {\n\t\t\tthis.preventMistouch.initialX = e.clientX;\n\t\t\tthis.preventMistouch.initialY = e.clientY;\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t\tthis.preventMistouch.record = true;\n\t\t}\n\t};\n\n\tprivate onPointerMove = (e: PointerEvent) => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t}\n\t};\n\n\tprivate onPointerUp = () => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.record = false;\n\t\t\tif (\n\t\t\t\tMath.abs(this.preventMistouch.lastX - this.preventMistouch.initialX) +\n\t\t\t\t\tMath.abs(this.preventMistouch.lastY - this.preventMistouch.initialY) <\n\t\t\t\t5\n\t\t\t)\n\t\t\t\tthis.endPrevention();\n\t\t}\n\t};\n\n\tstartPrevention = () => {\n\t\tthis.preventionContainer.classList.remove('JCV-hidden');\n\t\tthis.DM.data.container.classList.add('JCV-numb');\n\t\tthis.preventMt = true;\n\t};\n\n\tendPrevention = () => {\n\t\tthis.preventMt = false;\n\t\tthis.preventionContainer.classList.add('JCV-hidden');\n\t\tsetTimeout(() => this.DM.data.container.classList.remove('JCV-numb'), 50); // minimum delay to prevent triggering undesired button touch\n\t};\n\n\tprivate dispose = () => {\n\t\twindow.removeEventListener('pointerdown', this.onPointerDown);\n\t\twindow.removeEventListener('pointermove', this.onPointerMove);\n\t\twindow.removeEventListener('pointerup', this.onPointerUp);\n\t\tthis.preventionContainer.remove();\n\t\tthis._preventionContainer = null;\n\t};\n}\n"],"names":["MistouchPreventer","BaseModule","_preventionContainer","preventMt","DM","preventMistouch","record","lastX","lastY","initialX","initialY","preventionContainer","this","destroyError","constructor","args","super","preventionBanner","document","createElement","className","textContent","options","mistouchPreventerBannerText","container","get","DataManager","utilities","applyStyles","style","appendChild","data","preventMistouchAtStart","startPrevention","window","addEventListener","onPointerDown","onPointerMove","onPointerUp","augment","startMistouchPrevention","endMistouchPrevention","endPrevention","onDispose","dispose","e","bounds","getBoundingClientRect","clientX","left","right","clientY","top","bottom","Math","abs","classList","remove","add","setTimeout","removeEventListener"],"mappings":"+LAgBA,MAAqBA,UAA0BC,EACtCC,qBAA8C,KAC9CC,WAAqB,EACrBC,GACAC,gBAMJ,CACHC,QAAQ,EACRC,MAAO,EACPC,MAAO,EACPC,SAAU,EACVC,SAAU,GAGX,uBAAYC,GACX,GAAkC,OAA9BC,KAAKV,qBAA+B,MAAMW,EAC9C,OAAOD,KAAKV,oBACb,CAEA,WAAAY,IAAeC,GACdC,SAASD,GAET,MAAME,EAAmBC,SAASC,cAAc,OAChDF,EAAiBG,UAAY,6CAC7BH,EAAiBI,YAChBT,KAAKU,QAAQC,6BAA+B,sBAC7CX,KAAKR,GAAKQ,KAAKY,UAAUC,IAAIC,GAC7Bd,KAAKV,qBAAuBgB,SAASC,cAAc,OACnDP,KAAKV,qBAAqBkB,UACzB,+DAEDO,EAAUC,YAAYhB,KAAKV,qBAAsB2B,GACjDjB,KAAKV,qBAAqB4B,YAAYb,GACtCL,KAAKR,GAAG2B,KAAKP,UAAUM,YAAYlB,KAAKV,sBAEpCU,KAAKU,QAAQU,wBAAwBpB,KAAKqB,kBAE9CC,OAAOC,iBAAiB,cAAevB,KAAKwB,eAC5CF,OAAOC,iBAAiB,cAAevB,KAAKyB,eAC5CH,OAAOC,iBAAiB,YAAavB,KAAK0B,aAE1C1B,KAAK2B,QAAQ,CACZC,wBAAyB5B,KAAKqB,gBAC9BQ,sBAAuB7B,KAAK8B,gBAE7B9B,KAAK+B,UAAU/B,KAAKgC,QACrB,CAEQR,cAAiBS,IACxB,MAAMC,EAASlC,KAAKR,GAAG2B,KAAKP,UAAUuB,wBAErCF,EAAEG,QAAUF,EAAOG,MACnBJ,EAAEG,QAAUF,EAAOI,OACnBL,EAAEM,QAAUL,EAAOM,KACnBP,EAAEM,QAAUL,EAAOO,OAEdzC,KAAKT,WAAWS,KAAKqB,kBAChBrB,KAAKT,YACfS,KAAKP,gBAAgBI,SAAWoC,EAAEG,QAClCpC,KAAKP,gBAAgBK,SAAWmC,EAAEM,QAClCvC,KAAKP,gBAAgBE,MAAQsC,EAAEG,QAC/BpC,KAAKP,gBAAgBG,MAAQqC,EAAEM,QAC/BvC,KAAKP,gBAAgBC,QAAS,IAIxB+B,cAAiBQ,IACpBjC,KAAKP,gBAAgBC,SACxBM,KAAKP,gBAAgBE,MAAQsC,EAAEG,QAC/BpC,KAAKP,gBAAgBG,MAAQqC,EAAEM,UAIzBb,YAAc,KACjB1B,KAAKP,gBAAgBC,SACxBM,KAAKP,gBAAgBC,QAAS,EAE7BgD,KAAKC,IAAI3C,KAAKP,gBAAgBE,MAAQK,KAAKP,gBAAgBI,UAC1D6C,KAAKC,IAAI3C,KAAKP,gBAAgBG,MAAQI,KAAKP,gBAAgBK,UAC5D,GAEAE,KAAK8B,kBAIRT,gBAAkB,KACjBrB,KAAKD,oBAAoB6C,UAAUC,OAAO,cAC1C7C,KAAKR,GAAG2B,KAAKP,UAAUgC,UAAUE,IAAI,YACrC9C,KAAKT,WAAY,GAGlBuC,cAAgB,KACf9B,KAAKT,WAAY,EACjBS,KAAKD,oBAAoB6C,UAAUE,IAAI,cACvCC,WAAW,IAAM/C,KAAKR,GAAG2B,KAAKP,UAAUgC,UAAUC,OAAO,YAAa,KAG/Db,QAAU,KACjBV,OAAO0B,oBAAoB,cAAehD,KAAKwB,eAC/CF,OAAO0B,oBAAoB,cAAehD,KAAKyB,eAC/CH,OAAO0B,oBAAoB,YAAahD,KAAK0B,aAC7C1B,KAAKD,oBAAoB8C,SACzB7C,KAAKV,qBAAuB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=".JSON-Canvas-Viewer.JCV-numb,.JSON-Canvas-Viewer.JCV-numb *{pointer-events:none!important}.JSON-Canvas-Viewer .JCV-prevention-container{overflow:visible;transition:background .2s,opacity .2s,box-shadow .2s,border .2s,filter .2s,backdrop-filter .2s}.JSON-Canvas-Viewer .JCV-prevention-container.JCV-hidden{pointer-events:none;opacity:0}.JSON-Canvas-Viewer .JCV-prevention-container .JCV-prevention-banner{border-radius:12px;padding:12px;margin:12px;font-size:calc(14px + .3vw);line-height:calc(17px + .3vw);text-align:center}";export{e as default};
|
|
2
|
+
//# sourceMappingURL=styles.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchCanvas.js","sources":["../../src/utilities/fetchCanvas.ts"],"sourcesContent":["import type { JSONCanvas } from '@repo/shared';\n\nexport default async function (path: `${string}.canvas` | `${string}.json`) {\n\treturn (await fetch(path).then((res) => res.json())) as JSONCanvas;\n}\n"],"names":["async","fetchCanvas","path","fetch","then","res","json"],"mappings":"AAEAA,eAAAC,EAA+BC,GAC9B,aAAcC,MAAMD,GAAME,KAAMC,GAAQA,EAAIC,OAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sources":["../../src/utilities/parser.ts"],"sourcesContent":["import purify from 'dompurify';\nimport { marked } from 'marked';\n\nexport default async function (markdown: string) {\n\treturn purify.sanitize(await marked(markdown));\n}\n"],"names":["async","parser","markdown","purify","sanitize","marked"],"mappings":"yDAGAA,eAAAC,EAA+BC,GAC9B,OAAOC,EAAOC,eAAeC,EAAOH,GACrC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
async function t(t){const a=async a=>await async function(t,a){switch(t.type){case"text":return await a(t.text);case"file":return await async function(t,a){if(t.file.match(/\.md$/i))return await async function(t,a){let e;try{const i=await fetch(t),n=await i.text(),r=n.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=r?await a(r[2]):await a(n)}catch{e="Failed to load content."}return e}(t.file,a);if(t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i))return`<img src="${t.file}" alt="${t.file.split("/").pop()}">`;if(t.file.match(/\.(mp3|wav)$/i))return`<audio src="${t.file}" controls></audio>`;return""}(t,a);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow">${t.url}</a>`;default:return""}}(a,t.
|
|
2
|
-
//# sourceMappingURL=renderToString
|
|
1
|
+
async function t(t){const a=async a=>await async function(t,a){switch(t.type){case"text":return await a(t.text);case"file":return await async function(t,a){if(t.file.match(/\.md$/i))return await async function(t,a){let e;try{const i=await fetch(t),n=await i.text(),r=n.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);e=r?await a(r[2]):await a(n)}catch{e="Failed to load content."}return e}(t.file,a);if(t.file.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i))return`<img src="${t.file}" alt="${t.file.split("/").pop()}">`;if(t.file.match(/\.(mp3|wav)$/i))return`<audio src="${t.file}" controls></audio>`;return""}(t,a);case"link":return`<a href="${t.url}" target="_blank" rel="nofollow">${t.url}</a>`;default:return""}}(a,t.parser??(t=>t)),e=t.canvas.nodes??[],i=t.attachmentDir??"./";e.forEach(a=>{if("file"===a.type&&!a.file.startsWith("http")){const e=a.file.split("/").pop()??"";t.attachments?.[e]?a.file=t.attachments[e]:a.file=i+e}});const n=[];return await Promise.all(e.map(async t=>n.push(await a(t)))),n.join("")}export{t as default};
|
|
2
|
+
//# sourceMappingURL=renderToString.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderToString.js","sources":["../../src/utilities/renderToString.ts"],"sourcesContent":["import type { JSONCanvas, JSONCanvasFileNode, JSONCanvasNode, Parser } from '@repo/shared';\n\nexport default async function (options: {\n\tcanvas: JSONCanvas;\n\tattachments?: Record<string, string>;\n\tattachmentDir?: string;\n\tparser?: Parser;\n}) {\n\tconst render = async (node: JSONCanvasNode) =>\n\t\tawait renderer(node, options.parser ?? ((markdown: string) => markdown));\n\tconst nodes = options.canvas.nodes ?? [];\n\tconst basePath = options.attachmentDir ?? './';\n\tnodes.forEach((node) => {\n\t\tif (node.type === 'file' && !node.file.startsWith('http')) {\n\t\t\tconst file = node.file.split('/');\n\t\t\tconst name = file.pop() ?? '';\n\t\t\tif (options.attachments?.[name]) node.file = options.attachments[name];\n\t\t\telse node.file = basePath + name;\n\t\t}\n\t});\n\tconst renderedContent: Array<string> = [];\n\tawait Promise.all(nodes.map(async (node) => renderedContent.push(await render(node))));\n\treturn renderedContent.join('');\n}\n\nasync function renderer(node: JSONCanvasNode, parse: Parser) {\n\tswitch (node.type) {\n\t\tcase 'text':\n\t\t\treturn await parse(node.text);\n\t\tcase 'file':\n\t\t\treturn await fileProcessor(node, parse);\n\t\tcase 'link':\n\t\t\treturn `<a href=\"${node.url}\" target=\"_blank\" rel=\"nofollow\">${node.url}</a>`;\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n\nasync function fileProcessor(node: JSONCanvasFileNode, parse: Parser) {\n\tif (node.file.match(/\\.md$/i)) return await loadMarkdown(node.file, parse);\n\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\treturn `<img src=\"${node.file}\" alt=\"${node.file.split('/').pop()}\">`;\n\telse if (node.file.match(/\\.(mp3|wav)$/i)) return `<audio src=\"${node.file}\" controls></audio>`;\n\treturn '';\n}\n\nasync function loadMarkdown(path: string, parse: Parser) {\n\tlet parsedContent: string;\n\ttry {\n\t\tconst response = await fetch(path);\n\t\tconst result = await response.text();\n\t\tconst frontmatterMatch = result.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n\t\tif (frontmatterMatch) parsedContent = await parse(frontmatterMatch[2]);\n\t\telse parsedContent = await parse(result);\n\t} catch {\n\t\tparsedContent = 'Failed to load content.';\n\t}\n\treturn parsedContent;\n}\n"],"names":["async","renderToString","options","render","node","parse","type","text","file","match","path","parsedContent","response","fetch","result","frontmatterMatch","loadMarkdown","split","pop","fileProcessor","url","renderer","parser","markdown","nodes","canvas","basePath","attachmentDir","forEach","startsWith","name","attachments","renderedContent","Promise","all","map","push","join"],"mappings":"AAEAA,eAAAC,EAA+BC,GAM9B,MAAMC,EAASH,MAAOI,SAiBvBJ,eAAwBI,EAAsBC,GAC7C,OAAQD,EAAKE,MACZ,IAAK,OACJ,aAAaD,EAAMD,EAAKG,MACzB,IAAK,OACJ,aAQHP,eAA6BI,EAA0BC,GACtD,GAAID,EAAKI,KAAKC,MAAM,uBAOrBT,eAA4BU,EAAcL,GACzC,IAAIM,EACJ,IACC,MAAMC,QAAiBC,MAAMH,GACvBI,QAAeF,EAASL,OACxBQ,EAAmBD,EAAOL,MAAM,qCAChBE,EAAlBI,QAAwCV,EAAMU,EAAiB,UACxCV,EAAMS,EAClC,CAAA,MACCH,EAAgB,yBACjB,CACA,OAAOA,CACR,CAnB6CK,CAAaZ,EAAKI,KAAMH,GAAK,GAChED,EAAKI,KAAKC,MAAM,mCACxB,MAAO,aAAaL,EAAKI,cAAcJ,EAAKI,KAAKS,MAAM,KAAKC,UAAK,GACzDd,EAAKI,KAAKC,MAAM,iBAAkB,MAAO,eAAeL,EAAKI,0BACtE,MAAO,EACR,CAdgBW,CAAcf,EAAMC,GAClC,IAAK,OACJ,MAAO,YAAYD,EAAKgB,uCAAuChB,EAAKgB,UACrE,QACC,MAAO,GAEV,CA3BQC,CAASjB,EAAMF,EAAQoB,QAAA,CAAYC,GAAqBA,IACzDC,EAAQtB,EAAQuB,OAAOD,OAAS,GAChCE,EAAWxB,EAAQyB,eAAiB,KAC1CH,EAAMI,QAASxB,IACd,GAAkB,SAAdA,EAAKE,OAAoBF,EAAKI,KAAKqB,WAAW,QAAS,CAC1D,MACMC,EADO1B,EAAKI,KAAKS,MAAM,KACXC,OAAS,GACvBhB,EAAQ6B,cAAcD,KAAYtB,KAAON,EAAQ6B,YAAYD,GAC5D1B,EAAKI,KAAOkB,EAAWI,CAC7B,IAED,MAAME,EAAiC,GAEvC,aADMC,QAAQC,IAAIV,EAAMW,IAAInC,MAAOI,GAAS4B,EAAgBI,WAAWjC,EAAOC,MACvE4B,EAAgBK,KAAK,GAC7B"}
|