json-canvas-viewer 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/chimp.js +396 -1
  2. package/dist/index.d.ts +29 -618
  3. package/dist/index.js +2 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/kernel/BaseModule.d.ts +27 -0
  6. package/dist/kernel/BaseModule.js +2 -2
  7. package/dist/kernel/BaseModule.js.map +1 -1
  8. package/dist/kernel/Controller.d.ts +30 -0
  9. package/dist/kernel/Controller.js +2 -2
  10. package/dist/kernel/Controller.js.map +1 -1
  11. package/dist/kernel/DataManager.d.ts +67 -0
  12. package/dist/kernel/DataManager.js +2 -2
  13. package/dist/kernel/DataManager.js.map +1 -1
  14. package/dist/kernel/InteractionHandler.d.ts +51 -0
  15. package/dist/kernel/InteractionHandler.js +2 -2
  16. package/dist/kernel/InteractionHandler.js.map +1 -1
  17. package/dist/kernel/OverlayManager.d.ts +62 -0
  18. package/dist/kernel/OverlayManager.js +2 -2
  19. package/dist/kernel/OverlayManager.js.map +1 -1
  20. package/dist/kernel/Renderer.d.ts +37 -0
  21. package/dist/kernel/Renderer.js +3 -2
  22. package/dist/kernel/Renderer.js.map +1 -1
  23. package/dist/kernel/StyleManager.d.ts +135 -0
  24. package/dist/kernel/StyleManager.js +2 -2
  25. package/dist/kernel/StyleManager.js.map +1 -1
  26. package/dist/kernel/index.d.ts +46 -0
  27. package/dist/kernel/index.js +2 -2
  28. package/dist/kernel/index.js.map +1 -1
  29. package/dist/kernel/styles.js +285 -0
  30. package/dist/kernel/styles.js.map +1 -0
  31. package/dist/kernel/types.d.ts +33 -0
  32. package/dist/kernel/utilities.d.ts +13 -0
  33. package/dist/kernel/utilities.js +2 -2
  34. package/dist/kernel/utilities.js.map +1 -1
  35. package/dist/modules/Controls/index.d.ts +42 -0
  36. package/dist/modules/Controls/index.js +2 -2
  37. package/dist/modules/Controls/index.js.map +1 -1
  38. package/dist/modules/Controls/styles.js +29 -0
  39. package/dist/modules/Controls/styles.js.map +1 -0
  40. package/dist/modules/DebugPanel/index.d.ts +14 -0
  41. package/dist/modules/DebugPanel/index.js +2 -2
  42. package/dist/modules/DebugPanel/index.js.map +1 -1
  43. package/dist/modules/DebugPanel/styles.js +13 -0
  44. package/dist/modules/DebugPanel/styles.js.map +1 -0
  45. package/dist/modules/Minimap/index.d.ts +36 -0
  46. package/dist/modules/Minimap/index.js +2 -2
  47. package/dist/modules/Minimap/index.js.map +1 -1
  48. package/dist/modules/Minimap/styles.js +56 -0
  49. package/dist/modules/Minimap/styles.js.map +1 -0
  50. package/dist/modules/MistouchPreventer/index.d.ts +29 -0
  51. package/dist/modules/MistouchPreventer/index.js +2 -2
  52. package/dist/modules/MistouchPreventer/index.js.map +1 -1
  53. package/dist/modules/MistouchPreventer/styles.js +21 -0
  54. package/dist/modules/MistouchPreventer/styles.js.map +1 -0
  55. package/dist/shared/index.d.ts +50 -0
  56. package/dist/utilities/fetch-canvas.d.ts +7 -0
  57. package/dist/utilities/fetch-canvas.js +2 -0
  58. package/dist/utilities/fetch-canvas.js.map +1 -0
  59. package/dist/utilities/parser.d.ts +5 -0
  60. package/dist/utilities/parser.js +2 -2
  61. package/dist/utilities/parser.js.map +1 -1
  62. package/dist/utilities/render-to-string.d.ts +12 -0
  63. package/dist/utilities/render-to-string.js +2 -0
  64. package/dist/utilities/render-to-string.js.map +1 -0
  65. package/package.json +8 -7
  66. package/dist/kernel/styles.scss.js +0 -2
  67. package/dist/kernel/styles.scss.js.map +0 -1
  68. package/dist/modules/Controls/styles.scss.js +0 -2
  69. package/dist/modules/Controls/styles.scss.js.map +0 -1
  70. package/dist/modules/DebugPanel/styles.scss.js +0 -2
  71. package/dist/modules/DebugPanel/styles.scss.js.map +0 -1
  72. package/dist/modules/Minimap/styles.scss.js +0 -2
  73. package/dist/modules/Minimap/styles.scss.js.map +0 -1
  74. package/dist/modules/MistouchPreventer/styles.scss.js +0 -2
  75. package/dist/modules/MistouchPreventer/styles.scss.js.map +0 -1
  76. package/dist/utilities/fetchCanvas.js +0 -2
  77. package/dist/utilities/fetchCanvas.js.map +0 -1
  78. package/dist/utilities/renderToString.js +0 -2
  79. package/dist/utilities/renderToString.js.map +0 -1
@@ -1 +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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"}
1
+ {"version":3,"file":"OverlayManager.js","names":[],"sources":["../../src/kernel/OverlayManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { WithBorderWidth as Color } from '$/StyleManager';\nimport type { Hook } from '$/utilities';\nimport type {\n\tJSONCanvasFileNode,\n\tJSONCanvasLinkNode,\n\tJSONCanvasNode,\n\tJSONCanvasTextNode,\n\tParser,\n} from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport InteractionHandler from '$/InteractionHandler';\nimport StyleManager from '$/StyleManager';\nimport { destroyError, makeHook } from '$/utilities';\n\ntype Options = {\n\tparser?: Parser;\n\tnodeComponents?: Partial<ComponentDict>;\n} & BaseOptions;\n\ntype Augmentation = {\n\tonNodeActive: OverlayManager['onNodeActive'];\n\tonNodeLosesActive: OverlayManager['onNodeLosesActive'];\n};\n\nconst fileRegex = {\n\taudio: /\\.(mp3|wav|ogg|opus|aac|m4a|flac)$/i,\n\timage: /\\.(png|jpg|jpeg|gif|svg|webp|avif|bmp|ico|heic|heif)$/i,\n\tmarkdown: /\\.(md|mdx|markdown|txt)$/i,\n\tvideo: /\\.(mp4|webm|ogv|mov|m3u8|mpd)$/i,\n};\n\ntype NodeComponentHook<N extends JSONCanvasNode> = (options: {\n\tcontainer: HTMLDivElement;\n\tcontent: string;\n\tnode: N;\n\tonBeforeUnmount: Hook;\n\tonActive: Hook;\n\tonLoseActive: Hook;\n}) => void | Promise<void>;\n\ntype CreateOverlayArgs =\n\t| [ComponentNodeMap['text'], string, 'text']\n\t| [ComponentNodeMap['markdown'], string, 'markdown']\n\t| [ComponentNodeMap['image'], string, 'image']\n\t| [ComponentNodeMap['audio'], string, 'audio']\n\t| [ComponentNodeMap['video'], string, 'video']\n\t| [ComponentNodeMap['link'], string, 'link'];\n\ntype ComponentNodeMap = {\n\ttext: JSONCanvasTextNode;\n\tmarkdown: JSONCanvasFileNode;\n\timage: JSONCanvasFileNode;\n\taudio: JSONCanvasFileNode;\n\tvideo: JSONCanvasFileNode;\n\tlink: JSONCanvasLinkNode;\n};\n\ntype ComponentDict = {\n\t[K in keyof ComponentNodeMap]: NodeComponentHook<ComponentNodeMap[K]>;\n};\n\nconst supportedTypes = ['markdown', 'image', 'audio', 'video'] as const;\n\nexport default class OverlayManager extends BaseModule<Options, Augmentation> {\n\tprivate _overlaysLayer: HTMLDivElement | undefined = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | undefined;\n\tprivate aborted = false;\n\tprivate eventListeners: Record<string, Array<EventListener | undefined>> = {};\n\tprivate readonly DM: DataManager;\n\tprivate readonly SM: StyleManager;\n\tprivate readonly parse: Parser;\n\tprivate readonly componentDict: ComponentDict = {\n\t\taudio: ({ container, content }) => {\n\t\t\tconst audio = document.createElement('audio');\n\t\t\taudio.className = 'JCV-audio';\n\t\t\taudio.src = content;\n\t\t\taudio.controls = true;\n\t\t\tcontainer.appendChild(audio);\n\t\t},\n\t\timage: ({ container, content }) => {\n\t\t\tconst img = document.createElement('img');\n\t\t\timg.className = 'JCV-img';\n\t\t\timg.src = content;\n\t\t\timg.loading = 'lazy';\n\t\t\tcontainer.appendChild(img);\n\t\t},\n\t\tlink: ({ container, content }) => {\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tiframe.src = content;\n\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\tiframe.className = 'JCV-link-iframe';\n\t\t\tiframe.loading = 'lazy';\n\t\t\tcontainer.appendChild(iframe);\n\t\t},\n\t\tmarkdown: async ({ container, content }) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.textContent = 'Loading...';\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t\tlet parsedContent: string;\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(content);\n\t\t\t\tconst result = await response.text();\n\t\t\t\tconst frontmatterMatch = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/.exec(result);\n\t\t\t\tparsedContent = await this.parse(frontmatterMatch ? frontmatterMatch[2] : result);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[JSON Canvas Viewer] Failed to load markdown:', error);\n\t\t\t\tparsedContent = 'Failed to load content.';\n\t\t\t}\n\t\t\tparsedContentWrapper.innerHTML = parsedContent;\n\t\t},\n\t\ttext: ({ container, content }) => {\n\t\t\tcontainer.classList.add('JCV-markdown-content');\n\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\tparsedContentWrapper.innerHTML = content;\n\t\t\tparsedContentWrapper.classList.add('JCV-parsed-content-wrapper');\n\t\t\tcontainer.appendChild(parsedContentWrapper);\n\t\t},\n\t\tvideo: ({ container, content }) => {\n\t\t\tconst video = document.createElement('video');\n\t\t\tvideo.className = 'JCV-video';\n\t\t\tvideo.src = content;\n\t\t\tvideo.controls = true;\n\t\t\tcontainer.appendChild(video);\n\t\t},\n\t};\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\tonInteractionStart = makeHook();\n\tonInteractionEnd = makeHook();\n\tonNodeActive = makeHook<[JSONCanvasNode]>();\n\tonNodeLosesActive = makeHook<[JSONCanvasNode]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.parse = this.options.parser ?? ((markdown: string) => markdown);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.SM = this.container.get(StyleManager);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.onRefresh.subscribe(this.updateOverlays);\n\t\tthis.SM.onChangeTheme.subscribe(this.themeChanged);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'JCV-overlays';\n\t\tthis._overlaysLayer.id = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\n\t\tconst components = this.options.nodeComponents;\n\t\tif (components) Object.assign(this.componentDict, components);\n\n\t\tthis.augment({\n\t\t\tonNodeActive: this.onNodeActive,\n\t\t\tonNodeLosesActive: this.onNodeLosesActive,\n\t\t});\n\t\tthis.onStart(this.start);\n\t\tthis.onRestart(this.restart);\n\t\tthis.onDispose(this.dispose);\n\t}\n\n\tprivate readonly start = () => {\n\t\tthis.container.get(InteractionHandler).onClick.subscribe(this.select);\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly restart = () => {\n\t\tthis.clearOverlays();\n\t\tthis.renderOverlays();\n\t};\n\n\tprivate readonly renderOverlays = () => {\n\t\tconst overlayMatcher = async (node: JSONCanvasNode) => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'text': {\n\t\t\t\t\tthis.createOverlay(node, await this.parse(node.text), 'text');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'file': {\n\t\t\t\t\tfor (const type of supportedTypes) {\n\t\t\t\t\t\tif (!node.file.match(fileRegex[type])) continue;\n\t\t\t\t\t\tthis.createOverlay(node, node.file, type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'link': {\n\t\t\t\t\tthis.createOverlay(node, node.url, 'link');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(async (node) => {\n\t\t\tawait overlayMatcher(node.ref);\n\t\t});\n\t};\n\n\tprivate readonly themeChanged = () => {\n\t\tObject.values(this.overlays).forEach((overlay) => {\n\t\t\tconst node = this.DM.data.nodeMap[overlay.id].ref;\n\t\t\tconst color = this.SM.getColor(node.color);\n\t\t\tthis.setOverlayColor(overlay, color);\n\t\t});\n\t};\n\n\tprivate readonly select = (id?: string) => {\n\t\tconst previousId = this.selectedId;\n\t\tconst previous = !previousId ? undefined : this.overlays[previousId];\n\t\tconst current = !id ? undefined : 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 readonly updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate readonly createOverlay = (...args: CreateOverlayArgs) => {\n\t\tif (this.aborted) return;\n\t\tconst node = args[0];\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = this.constructOverlay(...args);\n\t\t\tif (this.aborted) return;\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t}\n\t};\n\n\tprivate readonly constructOverlay = (...args: CreateOverlayArgs) => {\n\t\tconst node = args[0];\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('JCV-overlay-container');\n\t\toverlay.id = node.id;\n\t\tthis.setOverlayColor(overlay, this.SM.getColor(node.color));\n\t\tconst contentWrapper = document.createElement('div');\n\t\tcontentWrapper.classList.add('JCV-content');\n\t\toverlay.appendChild(contentWrapper);\n\t\tconst clickLayer = document.createElement('div');\n\t\tclickLayer.className = 'JCV-click-layer';\n\t\toverlay.appendChild(clickLayer);\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'JCV-overlay-border';\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst nodeItem = this.DM.data.nodeMap[node.id];\n\n\t\tnodeItem.onActive = makeHook();\n\t\tnodeItem.onLoseActive = makeHook();\n\t\tnodeItem.onBeforeUnmount = makeHook();\n\n\t\tvoid this.componentDict[args[2]]({\n\t\t\tcontainer: contentWrapper,\n\t\t\tcontent: args[1],\n\t\t\tnode: args[0] as never,\n\t\t\tonActive: nodeItem.onActive,\n\t\t\tonBeforeUnmount: nodeItem.onBeforeUnmount,\n\t\t\tonLoseActive: nodeItem.onLoseActive,\n\t\t});\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t};\n\n\tprivate readonly setOverlayColor = (overlay: HTMLDivElement, color: Color) => {\n\t\tObject.entries(color).forEach(([key, value]) => {\n\t\t\toverlay.style.setProperty(`--overlay-${key}`, value);\n\t\t});\n\t};\n\n\tprivate readonly clearOverlays = () => {\n\t\tObject.entries(this.overlays).forEach(([id, overlay]) => {\n\t\t\tthis.DM.data.nodeMap[id].onBeforeUnmount?.();\n\t\t\tif (this.eventListeners[id]) {\n\t\t\t\tconst onStart = this.eventListeners[id][0];\n\t\t\t\tconst onEnd = this.eventListeners[id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\toverlay.removeEventListener('pointerenter', onStart);\n\t\t\t\toverlay.removeEventListener('pointerleave', onEnd);\n\t\t\t\toverlay.removeEventListener('touchstart', onStart);\n\t\t\t\toverlay.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[id][0] = undefined;\n\t\t\t\tthis.eventListeners[id][1] = undefined;\n\t\t\t}\n\t\t\toverlay.remove();\n\t\t\tdelete this.overlays[id];\n\t\t});\n\t};\n\n\tprivate readonly dispose = () => {\n\t\tthis.aborted = true;\n\t\tthis.clearOverlays();\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = undefined;\n\t};\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { BaseArgs, BaseModule } from "./BaseModule.js";
2
+ import { BaseOptions } from "./index.js";
3
+
4
+ //#region src/kernel/Renderer.d.ts
5
+ type Options = {
6
+ zoomInOptimization?: boolean;
7
+ } & BaseOptions;
8
+ declare class Renderer extends BaseModule<Options> {
9
+ private _canvas;
10
+ private readonly ctx;
11
+ private readonly DM;
12
+ private readonly SM;
13
+ private readonly zoomInOptimize;
14
+ private get canvas();
15
+ constructor(...args: BaseArgs);
16
+ private readonly optimizeDPR;
17
+ private readonly redraw;
18
+ private trueRedraw;
19
+ private fakeRedraw;
20
+ private readonly isInside;
21
+ private readonly isOutside;
22
+ private readonly getCurrentViewport;
23
+ private readonly drawLabelBar;
24
+ private readonly drawNodeBackground;
25
+ private readonly drawGroup;
26
+ private readonly drawFile;
27
+ private readonly drawEdge;
28
+ private readonly drawEdgeLabel;
29
+ private readonly getControlPoints;
30
+ private readonly drawGridDots;
31
+ private readonly drawCurvedPath;
32
+ private readonly drawArrowhead;
33
+ private readonly dispose;
34
+ }
35
+ //#endregion
36
+ export { Renderer };
37
+ //# sourceMappingURL=Renderer.d.ts.map
@@ -1,2 +1,3 @@
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
1
+ import{BaseModule as e}from"./BaseModule.js";import{destroyError as t,drawRoundRect as n,getAnchorCoord as r,resizeCanvasForDPR as i}from"./utilities.js";import a from"./DataManager.js";import o from"./StyleManager.js";import s from"./Controller.js";var c=class extends e{_canvas;ctx;DM;SM;zoomInOptimize={lastCallTime:0,lastDrawnScale:0,lastDrawnViewport:{bottom:0,left:0,right:0,top:0},timeout:void 0};get canvas(){if(!this._canvas)throw t;return this._canvas}constructor(...e){super(...e);let t=this.container.get(s);this.SM=this.container.get(o),t.onRefresh.subscribe(this.redraw),t.onResize.subscribe(this.optimizeDPR),this.DM=this.container.get(a),this._canvas=document.createElement(`canvas`),this._canvas.className=`JCV-main-canvas`,this.ctx=this._canvas.getContext(`2d`),this.DM.data.container.appendChild(this._canvas),this.onDispose(this.dispose)}optimizeDPR=()=>{let e=this.DM.data.container;i(this.canvas,e.offsetWidth,e.offsetHeight)};redraw=()=>{let e=this.DM.data.offsetX,t=this.DM.data.offsetY,n=this.DM.data.scale,r=this.getCurrentViewport(e,t,n);if(!this.options.zoomInOptimization){this.trueRedraw(e,t,n,r);return}this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=void 0);let i=Date.now();if(this.isInside(r,this.zoomInOptimize.lastDrawnViewport)&&n!==this.zoomInOptimize.lastDrawnScale&&i-this.zoomInOptimize.lastCallTime<500){this.zoomInOptimize.timeout=window.setTimeout(()=>{this.trueRedraw(e,t,n,r),this.zoomInOptimize.lastCallTime=i,this.zoomInOptimize.timeout=void 0},60),this.fakeRedraw(r,n);return}this.zoomInOptimize.lastCallTime=i,this.trueRedraw(e,t,n,r)};trueRedraw(e,t,n,r){this.zoomInOptimize.lastDrawnViewport=r,this.zoomInOptimize.lastDrawnScale=n,this.canvas.style.transform=``,this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.save(),this.drawGridDots(n,e,t),this.ctx.translate(e,t),this.ctx.scale(n,n),Object.values(this.DM.data.nodeMap).forEach(e=>{if(this.isOutside(e.box,r))return;let t=e.ref;t.type===`file`?this.drawFile(e):t.type===`group`&&this.drawGroup(t,n)}),Object.values(this.DM.data.edgeMap).forEach(e=>{this.isOutside(e.box,r)||this.drawEdge(e)}),this.ctx.restore()}fakeRedraw(e,t){let n=t/this.zoomInOptimize.lastDrawnScale,r=(this.zoomInOptimize.lastDrawnViewport.left-e.left)*t,i=(this.zoomInOptimize.lastDrawnViewport.top-e.top)*t;this.canvas.style.transform=`translate(${r}px, ${i}px) scale(${n})`}isInside=(e,t)=>e.left>t.left&&e.top>t.top&&e.right<t.right&&e.bottom<t.bottom;isOutside=(e,t)=>e.right<t.left||e.bottom<t.top||e.left>t.right||e.top>t.bottom;getCurrentViewport=(e,t,n)=>{let r=-e/n,i=-t/n,a=this.DM.data.container,o=r+a.clientWidth/n;return{bottom:i+a.clientHeight/n,left:r,right:o,top:i}};drawLabelBar=(e,t,n,r,i,a)=>{let o=30*a,s=6*a,c=8*a,l=16*a,u=6*a;this.ctx.save(),this.ctx.translate(e,t),this.ctx.scale(1/a,1/a),this.ctx.font=`${l}px 'Inter', sans-serif`;let d=this.ctx.measureText(n).width+2*u;this.ctx.translate(0,-o-c),this.ctx.fillStyle=r,this.ctx.beginPath(),this.ctx.moveTo(s,0),this.ctx.lineTo(d-s,0),this.ctx.quadraticCurveTo(d,0,d,s),this.ctx.lineTo(d,o-s),this.ctx.quadraticCurveTo(d,o,d-s,o),this.ctx.lineTo(s,o),this.ctx.quadraticCurveTo(0,o,0,o-s),this.ctx.lineTo(0,s),this.ctx.quadraticCurveTo(0,0,s,0),this.ctx.closePath(),this.ctx.fill(),this.ctx.fillStyle=i,this.ctx.fillText(n,u,o*.65),this.ctx.restore()};drawNodeBackground=e=>{let t=this.SM.getColor(e.color);this.ctx.globalAlpha=1,this.ctx.fillStyle=t.background,n(this.ctx,e.x+1,e.y+1,e.width-2,e.height-2,12),this.ctx.fill(),this.ctx.strokeStyle=t.border,this.ctx.lineWidth=2,n(this.ctx,e.x,e.y,e.width,e.height,12),this.ctx.stroke()};drawGroup=(e,t)=>{if(this.drawNodeBackground(e),e.label){let n=this.SM.getColor(e.color);this.drawLabelBar(e.x,e.y,e.label,n.active,n.text,t)}};drawFile=e=>{this.ctx.fillStyle=this.SM.getColor().text;let t=e.ref;this.ctx.font=`16px sans-serif`,this.ctx.fillText(e.fileName??``,t.x+5,t.y-10)};drawEdge=e=>{let t=e.ref,n=this.DM.data.nodeMap[t.fromNode].ref,i=this.DM.data.nodeMap[t.toNode].ref,{x:a,y:o}=r(n,t.fromSide),{x:s,y:c}=r(i,t.toSide),l=this.SM.getColor(t.color),u,d,f,p;e.controlPoints?[u,d,f,p]=e.controlPoints:([u,d,f,p]=this.getControlPoints(a,o,s,c,t.fromSide,t.toSide),e.controlPoints=[u,d,f,p]),this.drawCurvedPath(a,o,s,c,u,d,f,p,l.active),this.drawArrowhead(s,c,f,p,l.active),t.label&&this.drawEdgeLabel(a,o,s,c,u,d,f,p,t.label,l.active,l.text)};drawEdgeLabel=(e,t,r,i,a,o,s,c,l,u,d)=>{let f=.5,p=(1-f)**3*e+3*(1-f)**2*f*a+3*(1-f)*f*f*s+f**3*r,m=(1-f)**3*t+3*(1-f)**2*f*o+3*(1-f)*f*f*c+f**3*i;this.ctx.font=`18px sans-serif`;let h=l.split(`
2
+ `),g=0;for(let e of h){let t=this.ctx.measureText(e).width;t>g&&(g=t)}let _=g+16,v=h.length*17+6;this.ctx.fillStyle=u,this.ctx.beginPath(),n(this.ctx,p-_/2,m-v/2-2,_,v,4),this.ctx.fill(),this.ctx.fillStyle=d,this.ctx.textAlign=`center`,this.ctx.textBaseline=`middle`;for(let e=0;e<h.length;e++){let t=(e-(h.length-1)/2)*17;this.ctx.fillText(h[e],p,m-2+t)}this.ctx.textAlign=`left`,this.ctx.textBaseline=`alphabetic`};getControlPoints=(e,t,n,r,i,a)=>{let o=n-e,s=r-t,c=((e,t,n)=>Math.max(t,Math.min(n,e)))((Math.min(Math.abs(o),Math.abs(s))+.3*Math.max(Math.abs(o),Math.abs(s)))*.5,60,300),l=e,u=t,d=n,f=r;switch(i){case`top`:u=t-c;break;case`bottom`:u=t+c;break;case`left`:l=e-c;break;case`right`:l=e+c;break}switch(a){case`top`:f=r-c;break;case`bottom`:f=r+c;break;case`left`:d=n-c;break;case`right`:d=n+c;break}return[l,u,d,f]};drawGridDots=(e,t,n)=>{let r=10*2**-Math.floor(Math.log2(e))*e,i=this.canvas.width,a=this.canvas.height,o=t%r,s=n%r;this.ctx.fillStyle=this.SM.getNamedColor(`dots`);for(let e=o;e<=i;e+=r)for(let t=s;t<=a;t+=r)this.ctx.beginPath(),this.ctx.arc(e,t,1,0,2*Math.PI),this.ctx.fill()};drawCurvedPath=(e,t,n,r,i,a,o,s,c)=>{this.ctx.beginPath(),this.ctx.moveTo(e,t),this.ctx.bezierCurveTo(i,a,o,s,n,r),this.ctx.strokeStyle=c,this.ctx.lineWidth=2,this.ctx.stroke()};drawArrowhead=(e,t,n,r,i)=>{let a=e-n,o=t-r,s=Math.sqrt(a*a+o*o);if(s===0)return;let c=a/s,l=o/s,u=e-c*12-l*4,d=t-l*12+c*4,f=e-c*12+l*4,p=t-l*12-c*4;this.ctx.beginPath(),this.ctx.fillStyle=i,this.ctx.moveTo(e,t),this.ctx.lineTo(u,d),this.ctx.lineTo(f,p),this.ctx.closePath(),this.ctx.fill()};dispose=()=>{this.zoomInOptimize.timeout&&(clearTimeout(this.zoomInOptimize.timeout),this.zoomInOptimize.timeout=void 0),this.canvas.remove(),this._canvas=void 0}};export{c as default};
3
+ //# sourceMappingURL=Renderer.js.map
@@ -1 +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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"}
1
+ {"version":3,"file":"Renderer.js","names":[],"sources":["../../src/kernel/Renderer.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { EdgeItem, NodeItem } from '$/DataManager';\nimport type { Box } from '$/types';\nimport type { JSONCanvasGroupNode, JSONCanvasNode } from '@repo/shared';\nimport { BaseModule } from '$/BaseModule';\nimport Controller from '$/Controller';\nimport DataManager from '$/DataManager';\nimport StyleManager from '$/StyleManager';\nimport { destroyError, drawRoundRect, getAnchorCoord, resizeCanvasForDPR } 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\ntype Options = {\n\tzoomInOptimization?: boolean;\n} & BaseOptions;\n\nexport default class Renderer extends BaseModule<Options> {\n\tprivate _canvas: HTMLCanvasElement | undefined;\n\tprivate readonly ctx: CanvasRenderingContext2D;\n\tprivate readonly DM: DataManager;\n\tprivate readonly SM: StyleManager;\n\tprivate readonly zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: Box;\n\t\ttimeout: number | undefined;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastCallTime: 0,\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tbottom: 0,\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t},\n\t\ttimeout: undefined,\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 readonly optimizeDPR = () => {\n\t\tconst container = this.DM.data.container;\n\t\tresizeCanvasForDPR(this.canvas, container.offsetWidth, container.offsetHeight);\n\t};\n\n\tprivate readonly 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 = undefined;\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 = window.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 = undefined;\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 readonly 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 readonly 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 readonly 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 { bottom, left, right, top };\n\t};\n\n\tprivate readonly 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 readonly drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = this.SM.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tdrawRoundRect(\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\tdrawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate readonly 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 readonly 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 readonly 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 { x: startX, y: startY } = getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst { x: endX, y: endY } = getAnchorCoord(toNode, edge.toSide);\n\t\tconst color = this.SM.getColor(edge.color);\n\t\tlet startControlX, startControlY, endControlX, endControlY: number;\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\tthis.drawEdgeLabel(\n\t\t\t\tstartX,\n\t\t\t\tstartY,\n\t\t\t\tendX,\n\t\t\t\tendY,\n\t\t\t\tstartControlX,\n\t\t\t\tstartControlY,\n\t\t\t\tendControlX,\n\t\t\t\tendControlY,\n\t\t\t\tedge.label,\n\t\t\t\tcolor.active,\n\t\t\t\tcolor.text,\n\t\t\t);\n\t};\n\n\tprivate readonly drawEdgeLabel = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tstartControlX: number,\n\t\tstartControlY: number,\n\t\tendControlX: number,\n\t\tendControlY: number,\n\t\tlabel: string,\n\t\tcolor: string,\n\t\ttextColor: string,\n\t) => {\n\t\tconst t = 0.5;\n\t\tconst x =\n\t\t\t(1 - t) ** 3 * startX +\n\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\tt ** 3 * endX;\n\t\tconst y =\n\t\t\t(1 - t) ** 3 * startY +\n\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\tt ** 3 * endY;\n\t\tthis.ctx.font = '18px sans-serif';\n\t\tconst lines = label.split('\\n');\n\t\tconst lineHeight = 17;\n\t\tlet maxWidth = 0;\n\t\tfor (const line of lines) {\n\t\t\tconst w = this.ctx.measureText(line).width;\n\t\t\tif (w > maxWidth) maxWidth = w;\n\t\t}\n\t\tconst paddingX = 8;\n\t\tconst paddingY = 3;\n\t\tconst labelWidth = maxWidth + paddingX * 2;\n\t\tconst labelHeight = lines.length * lineHeight + paddingY * 2; // Dynamic height\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tdrawRoundRect(\n\t\t\tthis.ctx,\n\t\t\tx - labelWidth / 2,\n\t\t\ty - labelHeight / 2 - 2,\n\t\t\tlabelWidth,\n\t\t\tlabelHeight,\n\t\t\t4,\n\t\t);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = textColor;\n\t\tthis.ctx.textAlign = 'center';\n\t\tthis.ctx.textBaseline = 'middle';\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst offsetY = (i - (lines.length - 1) / 2) * lineHeight;\n\t\t\tthis.ctx.fillText(lines[i], x, y - 2 + offsetY);\n\t\t}\n\t\tthis.ctx.textAlign = 'left';\n\t\tthis.ctx.textBaseline = 'alphabetic';\n\t};\n\n\tprivate readonly 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\t}\n\t\t\tcase 'bottom': {\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'left': {\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'right': {\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t\t}\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\t}\n\t\t\tcase 'bottom': {\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'left': {\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'right': {\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate readonly 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};\n\n\tprivate readonly 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 readonly 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 readonly dispose = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = undefined;\n\t\t}\n\t\tthis.canvas.remove();\n\t\tthis._canvas = undefined;\n\t};\n}\n"],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { Hook } from "./utilities.js";
2
+ import { BaseArgs, BaseModule } from "./BaseModule.js";
3
+ import { BaseOptions } from "./index.js";
4
+
5
+ //#region src/kernel/StyleManager.d.ts
6
+ type Color = {
7
+ border: string;
8
+ background: string;
9
+ active: string;
10
+ text: string;
11
+ card: string;
12
+ };
13
+ type WithBorderWidth = {
14
+ 'border-width': string;
15
+ } & Color;
16
+ type ColorOptions = { [K in keyof (StyleManager['definedColors']['light'] & StyleManager['namedColors']['light'])]?: string };
17
+ type Options = {
18
+ theme?: 'dark' | 'light';
19
+ colors?: {
20
+ light?: ColorOptions;
21
+ dark?: ColorOptions;
22
+ };
23
+ } & BaseOptions;
24
+ type Augmentation = {
25
+ changeTheme: StyleManager['changeTheme'];
26
+ onChangeTheme: StyleManager['onChangeTheme'];
27
+ };
28
+ declare class StyleManager extends BaseModule<Options, Augmentation> {
29
+ theme: 'dark' | 'light';
30
+ onChangeTheme: Hook<["light" | "dark"], false>;
31
+ definedColors: {
32
+ dark: {
33
+ '0': {
34
+ hue: number;
35
+ lightness: number;
36
+ saturation: number;
37
+ };
38
+ '1': {
39
+ hue: number;
40
+ lightness: number;
41
+ saturation: number;
42
+ };
43
+ '2': {
44
+ hue: number;
45
+ lightness: number;
46
+ saturation: number;
47
+ };
48
+ '3': {
49
+ hue: number;
50
+ lightness: number;
51
+ saturation: number;
52
+ };
53
+ '4': {
54
+ hue: number;
55
+ lightness: number;
56
+ saturation: number;
57
+ };
58
+ '5': {
59
+ hue: number;
60
+ lightness: number;
61
+ saturation: number;
62
+ };
63
+ '6': {
64
+ hue: number;
65
+ lightness: number;
66
+ saturation: number;
67
+ };
68
+ };
69
+ light: {
70
+ '0': {
71
+ hue: number;
72
+ lightness: number;
73
+ saturation: number;
74
+ };
75
+ '1': {
76
+ hue: number;
77
+ lightness: number;
78
+ saturation: number;
79
+ };
80
+ '2': {
81
+ hue: number;
82
+ lightness: number;
83
+ saturation: number;
84
+ };
85
+ '3': {
86
+ hue: number;
87
+ lightness: number;
88
+ saturation: number;
89
+ };
90
+ '4': {
91
+ hue: number;
92
+ lightness: number;
93
+ saturation: number;
94
+ };
95
+ '5': {
96
+ hue: number;
97
+ lightness: number;
98
+ saturation: number;
99
+ };
100
+ '6': {
101
+ hue: number;
102
+ lightness: number;
103
+ saturation: number;
104
+ };
105
+ };
106
+ };
107
+ namedColors: {
108
+ dark: {
109
+ background: string;
110
+ 'background-secondary': string;
111
+ border: string;
112
+ dots: string;
113
+ shadow: string;
114
+ text: string;
115
+ };
116
+ light: {
117
+ background: string;
118
+ 'background-secondary': string;
119
+ border: string;
120
+ dots: string;
121
+ shadow: string;
122
+ text: string;
123
+ };
124
+ };
125
+ private readonly colorCache;
126
+ constructor(...args: BaseArgs);
127
+ private readonly hslProcessor;
128
+ private readonly parseColor;
129
+ getColor: (colorIndex?: string) => WithBorderWidth;
130
+ getNamedColor: (name: keyof typeof this.namedColors.light) => string;
131
+ changeTheme: (theme?: "dark" | "light") => void;
132
+ }
133
+ //#endregion
134
+ export { StyleManager };
135
+ //# sourceMappingURL=StyleManager.d.ts.map
@@ -1,2 +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
1
+ import{BaseModule as e}from"./BaseModule.js";import{makeHook as t}from"./utilities.js";import n from"./DataManager.js";import{parseHex as r,parseHsl as i,parseRgb as a,rgbToHsl as o,toHslString as s}from"@ahmedsemih/color-fns";var c=class extends e{theme=`light`;onChangeTheme=t();definedColors={dark:{0:{hue:0,lightness:40,saturation:0},1:{hue:358,lightness:65,saturation:100},2:{hue:23,lightness:63,saturation:86},3:{hue:39,lightness:70,saturation:91},4:{hue:153,lightness:45,saturation:80},5:{hue:217,lightness:62,saturation:100},6:{hue:259,lightness:75,saturation:100}},light:{0:{hue:0,lightness:72,saturation:0},1:{hue:358,lightness:55,saturation:81},2:{hue:19,lightness:58,saturation:87},3:{hue:41,lightness:52,saturation:79},4:{hue:150,lightness:37,saturation:100},5:{hue:221,lightness:59,saturation:100},6:{hue:257,lightness:62,saturation:81}}};namedColors={dark:{background:`rgb(30, 30, 30)`,"background-secondary":`rgb(37, 37, 40)`,border:`hsla(0, 0%, 30%, 0.7)`,dots:`hsla(0, 0%, 40%, 0.3)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.2)`,text:`rgb(242, 242, 242)`},light:{background:`rgb(250, 250, 250)`,"background-secondary":`rgb(255, 255, 255)`,border:`hsla(0, 0%, 82%, 0.7)`,dots:`hsla(0, 0%, 72%, 0.4)`,shadow:`0px 0px 8px rgb(0, 0, 0, 0.1)`,text:`rgb(30, 30, 30)`}};colorCache={dark:{},light:{}};constructor(...e){super(...e);let t=this.options.colors;t&&[`light`,`dark`].forEach(e=>{if(!(e in t))return;let n=t[e];n&&Object.entries(n).forEach(([t,n])=>{if(!n)return;let r=this.namedColors[e],i=this.definedColors[e];if(t in r)r[t]=n;else if(t in i){let e=this.parseColor(n);if(!e){console.warn(`[JSON Canvas Viewer] Color ${n} unsupported.`);return}i[t]=e}})}),this.changeTheme(this.options.theme??`light`),this.augment({changeTheme:this.changeTheme,onChangeTheme:this.onChangeTheme})}hslProcessor=e=>{let{hue:t,saturation:n,lightness:r}=e,i=this.theme===`dark`?{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:{hue:t,lightness:r/3,saturation:n/3},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`}:{active:e,background:{...e,alpha:.1},border:{...e,alpha:.7},card:t===0?{hue:t,lightness:100,saturation:n}:{hue:t,lightness:90,saturation:n*.4},text:e.lightness>=70?`rgb(30, 30, 30)`:`rgb(242, 242, 242)`};return{active:s(i.active),background:s(i.background),border:s(i.border),card:s(i.card),text:i.text}};parseColor=e=>{if(e.startsWith(`rgb`))return o(a(e));if(e.startsWith(`#`))return o(r(e));if(e.startsWith(`hsl`))return i(e)};getColor=(e=`0`)=>{let t=this.theme,n;if(this.colorCache[t][e])return this.colorCache[t][e];n=e in this.definedColors[t]?this.hslProcessor(this.definedColors[t][e]):this.hslProcessor(o(r(e)));let i={...n,"border-width":e===`0`?`1px`:`2px`};return this.colorCache[t][e]=i,i};getNamedColor=e=>this.namedColors[this.theme][e];changeTheme=e=>{this.theme=e??this.theme===`dark`?`light`:`dark`;let t=this.container.get(n).data.container;Object.entries(this.namedColors[this.theme]).forEach(([e,n])=>{t.style.setProperty(`--${e}`,n)}),this.onChangeTheme(this.theme)}};export{c as default};
2
+ //# sourceMappingURL=StyleManager.js.map
@@ -1 +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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"}
1
+ {"version":3,"file":"StyleManager.js","names":[],"sources":["../../src/kernel/StyleManager.ts"],"sourcesContent":["import type { BaseOptions } from '$';\nimport type { BaseArgs } from '$/BaseModule';\nimport type { HslColor } from '@ahmedsemih/color-fns';\nimport { BaseModule } from '$/BaseModule';\nimport DataManager from '$/DataManager';\nimport { makeHook } from '$/utilities';\nimport { parseHex, toHslString, rgbToHsl, parseHsl, parseRgb } from '@ahmedsemih/color-fns';\n\ntype Color = {\n\tborder: string;\n\tbackground: string;\n\tactive: string;\n\ttext: string;\n\tcard: string;\n};\n\nexport type WithBorderWidth = {\n\t'border-width': string;\n} & Color;\n\ntype ColorOptions = {\n\t[K in keyof (StyleManager['definedColors']['light'] &\n\t\tStyleManager['namedColors']['light'])]?: string;\n};\n\ntype Options = {\n\ttheme?: 'dark' | 'light';\n\tcolors?: {\n\t\tlight?: ColorOptions;\n\t\tdark?: ColorOptions;\n\t};\n} & BaseOptions;\n\ntype 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 = makeHook<['light' | 'dark']>();\n\tdefinedColors = {\n\t\tdark: {\n\t\t\t'0': { hue: 0, lightness: 40, saturation: 0 },\n\t\t\t'1': { hue: 358, lightness: 65, saturation: 100 },\n\t\t\t'2': { hue: 23, lightness: 63, saturation: 86 },\n\t\t\t'3': { hue: 39, lightness: 70, saturation: 91 },\n\t\t\t'4': { hue: 153, lightness: 45, saturation: 80 },\n\t\t\t'5': { hue: 217, lightness: 62, saturation: 100 },\n\t\t\t'6': { hue: 259, lightness: 75, saturation: 100 },\n\t\t},\n\t\tlight: {\n\t\t\t'0': { hue: 0, lightness: 72, saturation: 0 },\n\t\t\t'1': { hue: 358, lightness: 55, saturation: 81 },\n\t\t\t'2': { hue: 19, lightness: 58, saturation: 87 },\n\t\t\t'3': { hue: 41, lightness: 52, saturation: 79 },\n\t\t\t'4': { hue: 150, lightness: 37, saturation: 100 },\n\t\t\t'5': { hue: 221, lightness: 59, saturation: 100 },\n\t\t\t'6': { hue: 257, lightness: 62, saturation: 81 },\n\t\t},\n\t};\n\n\tnamedColors = {\n\t\tdark: {\n\t\t\tbackground: 'rgb(30, 30, 30)',\n\t\t\t'background-secondary': 'rgb(37, 37, 40)',\n\t\t\tborder: 'hsla(0, 0%, 30%, 0.7)',\n\t\t\tdots: 'hsla(0, 0%, 40%, 0.3)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.2)',\n\t\t\ttext: 'rgb(242, 242, 242)',\n\t\t},\n\t\tlight: {\n\t\t\tbackground: 'rgb(250, 250, 250)',\n\t\t\t'background-secondary': 'rgb(255, 255, 255)',\n\t\t\tborder: 'hsla(0, 0%, 82%, 0.7)',\n\t\t\tdots: 'hsla(0, 0%, 72%, 0.4)',\n\t\t\tshadow: '0px 0px 8px rgb(0, 0, 0, 0.1)',\n\t\t\ttext: 'rgb(30, 30, 30)',\n\t\t},\n\t};\n\n\tprivate readonly colorCache: {\n\t\tdark: Record<string, WithBorderWidth>;\n\t\tlight: Record<string, WithBorderWidth>;\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 readonly hslProcessor = (color: HslColor) => {\n\t\tconst { hue, saturation, lightness } = color;\n\t\tconst result =\n\t\t\tthis.theme === 'dark'\n\t\t\t\t? {\n\t\t\t\t\t\tactive: color,\n\t\t\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\t\t\tcard: { hue, lightness: lightness / 3, saturation: saturation / 3 },\n\t\t\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tactive: color,\n\t\t\t\t\t\tbackground: { ...color, alpha: 0.1 },\n\t\t\t\t\t\tborder: { ...color, alpha: 0.7 },\n\t\t\t\t\t\tcard:\n\t\t\t\t\t\t\thue === 0\n\t\t\t\t\t\t\t\t? { hue, lightness: 100, saturation }\n\t\t\t\t\t\t\t\t: { hue, lightness: 90, saturation: saturation * 0.4 },\n\t\t\t\t\t\ttext: color.lightness >= 70 ? 'rgb(30, 30, 30)' : 'rgb(242, 242, 242)',\n\t\t\t\t\t};\n\t\treturn {\n\t\t\tactive: toHslString(result.active),\n\t\t\tbackground: toHslString(result.background),\n\t\t\tborder: toHslString(result.border),\n\t\t\tcard: toHslString(result.card),\n\t\t\ttext: result.text,\n\t\t};\n\t};\n\n\tprivate readonly 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 = '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\tconst withBorderWidth: WithBorderWidth = {\n\t\t\t...color,\n\t\t\t'border-width': colorIndex === '0' ? '1px' : '2px',\n\t\t};\n\t\tthis.colorCache[theme][colorIndex] = withBorderWidth;\n\t\treturn withBorderWidth;\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 ?? 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"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { JSONCanvas } from "../shared/index.js";
2
+ import { Hook } from "./utilities.js";
3
+ import { Augmentation, ModuleInput, ModuleInputCtor, Options } from "./BaseModule.js";
4
+ import { DataManager } from "./DataManager.js";
5
+ import { InteractionHandler } from "./InteractionHandler.js";
6
+ import { OverlayManager } from "./OverlayManager.js";
7
+ import { Renderer } from "./Renderer.js";
8
+ import { StyleManager } from "./StyleManager.js";
9
+ import { Controller } from "./Controller.js";
10
+ import { Container } from "@needle-di/core";
11
+
12
+ //#region src/kernel/index.d.ts
13
+ type BaseOptions = {
14
+ container: HTMLElement;
15
+ loading?: 'normal' | 'lazy' | 'none';
16
+ };
17
+ declare const internalModules: (typeof Controller | typeof DataManager | typeof InteractionHandler | typeof OverlayManager | typeof Renderer | typeof StyleManager)[];
18
+ type InternalModules = typeof internalModules;
19
+ type AllOptions<M extends ModuleInput = []> = Options<M> & Options<InternalModules>;
20
+ type AllAugmentation<M extends ModuleInput = []> = Augmentation<M> & Augmentation<InternalModules>;
21
+ declare class JSONCanvasViewer<M extends ModuleInputCtor> {
22
+ private readonly allModules;
23
+ private IO;
24
+ private started;
25
+ private disposed;
26
+ options: AllOptions<M>;
27
+ container: Container;
28
+ onDispose: Hook<[], false>;
29
+ onStart: Hook<[], false>;
30
+ onRestart: Hook<[], false>;
31
+ constructor(options: AllOptions<M>, modules?: M);
32
+ private readonly onVisibilityCheck;
33
+ private readonly augment;
34
+ load: (options?: {
35
+ canvas?: JSONCanvas;
36
+ attachmentDir?: string;
37
+ attachments?: Record<string, string>;
38
+ }) => void;
39
+ dispose: () => void;
40
+ }
41
+ type JSONCanvasViewerType = new <M extends ModuleInputCtor = []>(...args: ConstructorParameters<typeof JSONCanvasViewer<M>>) => JSONCanvasViewer<M> & AllAugmentation<M>;
42
+ type JSONCanvasViewerInterface<M extends ModuleInput = []> = JSONCanvasViewer<never> & AllAugmentation<M>;
43
+ declare const _default: JSONCanvasViewerType;
44
+ //#endregion
45
+ export { AllOptions, BaseOptions, JSONCanvasViewerInterface, _default };
46
+ //# sourceMappingURL=index.d.ts.map
@@ -1,2 +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
1
+ import{makeHook as e}from"./utilities.js";import t from"./DataManager.js";import n from"./StyleManager.js";import r from"./Controller.js";import i from"./OverlayManager.js";import a from"./InteractionHandler.js";import o from"./Renderer.js";import{Container as s}from"@needle-di/core";const c=[t,n,r,i,a,o];var l=class{allModules;IO;started=!1;disposed=!1;options;container;onDispose=e(!0);onStart=e();onRestart=e();constructor(e,t){this.container=new s,this.options=e;let n=e=>{this.container.bind({provide:e,useFactory:()=>new e(this.container,this.options,this.onStart,this.onDispose,this.onRestart,this.augment)})};this.allModules=[...c,...t??[]],this.allModules.forEach(n),this.allModules.forEach(e=>{this.container.get(e)});let r=this.options.loading??`normal`;r===`normal`?this.load():r===`lazy`&&(this.IO=new IntersectionObserver(this.onVisibilityCheck,{rootMargin:`50px`,threshold:0}),this.IO.observe(this.options.container))}onVisibilityCheck=e=>{e.forEach(e=>{if(e.isIntersecting){this.load(),this.IO?.disconnect(),this.IO=void 0;return}})};augment=e=>{let t=Object.getOwnPropertyDescriptors(e);Object.defineProperties(this,t)};load=e=>{this.disposed||(e&&Object.assign(this.options,e),this.started?this.onRestart():(this.onStart(),this.started=!0))};dispose=()=>{if(!this.started||this.disposed)return;this.IO?.disconnect(),this.IO=void 0;let e=this.options.container;for(;e.firstChild;)e.firstChild.remove();this.onDispose(),this.container.unbindAll(),this.disposed=!0}};export{l as default};
2
+ //# sourceMappingURL=index.js.map