json-canvas-viewer 3.1.0 → 3.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 (36) hide show
  1. package/README.md +47 -342
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/types/baseModule.d.ts +12 -0
  7. package/dist/types/canvasViewer.d.ts +21 -14
  8. package/dist/types/controller.d.ts +33 -0
  9. package/dist/types/{extensions/controls.d.ts → controls/index.d.ts} +12 -5
  10. package/dist/types/dataManager.d.ts +42 -22
  11. package/dist/types/debugPanel/index.d.ts +9 -0
  12. package/dist/types/declarations.d.ts +79 -0
  13. package/dist/types/index.d.ts +18 -0
  14. package/dist/types/interactionHandler.d.ts +26 -9
  15. package/dist/types/{extensions/minimap.d.ts → minimap/index.d.ts} +13 -7
  16. package/dist/types/mistouchPreventer/index.d.ts +22 -0
  17. package/dist/types/overlayManager.d.ts +22 -8
  18. package/dist/types/renderer.d.ts +5 -4
  19. package/dist/types/shared.d.ts +13 -0
  20. package/dist/types/utilities.d.ts +15 -12
  21. package/package.json +32 -67
  22. package/dist/cjs/controls.js +0 -1
  23. package/dist/cjs/debugPanel.js +0 -1
  24. package/dist/cjs/index.js +0 -1
  25. package/dist/cjs/minimap.js +0 -1
  26. package/dist/cjs/mistouchPreventer.js +0 -1
  27. package/dist/es/controls.js +0 -1
  28. package/dist/es/debugPanel.js +0 -1
  29. package/dist/es/index.js +0 -1
  30. package/dist/es/minimap.js +0 -1
  31. package/dist/es/mistouchPreventer.js +0 -1
  32. package/dist/types/extensions/debugPanel.d.ts +0 -8
  33. package/dist/types/extensions/mistouchPreventer.d.ts +0 -14
  34. package/dist/types/interactor.d.ts +0 -30
  35. package/dist/utilities-9mYNj6lG.js +0 -1
  36. package/dist/utilities-C1DbXNeO.cjs +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/baseModule.ts","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/utils.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/providers.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/tokens.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/decorators.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/factory.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/context.js","../node_modules/.pnpm/@needle-di+core@1.1.0/node_modules/@needle-di/core/dist/container.js","../src/shared.ts","../src/dataManager.ts","../src/controller.ts","../src/overlayManager.ts","../src/interactionHandler.ts","../src/renderer.ts","../src/utilities.ts","../src/canvasViewer.ts","../src/controls/index.ts","../src/debugPanel/index.ts","../src/minimap/index.ts","../src/mistouchPreventer/index.ts","../src/index.ts"],"sourcesContent":["import type { Container } from '@needle-di/core';\nimport type { DefaultOptions, Empty, GeneralFunction, GeneralObject, Utilities } from '@/declarations';\n\nexport type BaseArgs = [Container, GeneralObject, Utilities];\n\nexport type GeneralModuleCtor = typeof BaseModule<GeneralObject>;\nexport type GeneralModule = InstanceType<GeneralModuleCtor>;\n\nexport class BaseModule<O extends GeneralObject = Empty> {\n\tconstructor(\n\t\tprotected container: Container,\n\t\toptions: GeneralObject,\n\t\tprotected utilities: Utilities,\n\t) {\n\t\tObject.assign(this.options, options);\n\t}\n\n\toptions = {} as DefaultOptions & O;\n\n\tdispose?: GeneralFunction;\n}\n","/**\n * Type-guard to assert if the given object is an (abstract) class.\n *\n * @internal\n */\nexport function isClassLike(target) {\n return typeof target === \"function\";\n}\n/**\n * Returns all parent classes of a given class.\n *\n * @internal\n */\nexport function getParentClasses(target) {\n const parentClasses = [];\n let currentClass = target;\n while (Object.getPrototypeOf(currentClass).name) {\n const parentClass = Object.getPrototypeOf(currentClass);\n parentClasses.push(parentClass);\n currentClass = parentClass;\n }\n return parentClasses;\n}\n/**\n * Ensures a given value is not null or undefined.\n *\n * @internal\n */\nexport function assertPresent(value) {\n if (value === null || value === undefined) {\n throw Error(`Expected value to be not null or undefined`);\n }\n return value;\n}\nexport function windowedSlice(array, step = 2) {\n const result = [];\n array.some((_, i) => {\n if (i + step > array.length)\n return true;\n result.push(array.slice(i, i + step));\n });\n return result;\n}\n/**\n * Retries as long as it encounters any error that is instance of `errorClass`.\n * Awaits the result of the `onError` callback before retrying.\n *\n * @internal\n */\nexport async function retryOn(errorClass, block, onError) {\n while (true) {\n try {\n return await block();\n }\n catch (error) {\n if (!(error instanceof errorClass)) {\n throw error;\n }\n await onError(error);\n }\n }\n}\n/**\n * Assert that there is a single element in an array. Throws the error from error provider if not.\n *\n * @internal\n */\nexport function assertSingle(array, errorProvider) {\n if (array.length > 1) {\n throw errorProvider();\n }\n const first = array.at(0);\n if (first === undefined) {\n throw errorProvider();\n }\n return first;\n}\n/**\n * Type-guard for `never` types, can be used to create exhaustive branches.\n *\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function assertNever(_) {\n throw new Error(\"invalid state\");\n}\n/**\n * Executes a callback, wrapping its result in a Promise.\n * Static version of `Promise.try()` (currently stage 3).\n *\n * @internal\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/try\n */\nexport async function promiseTry(block) {\n return await new Promise((resolve) => resolve(block()));\n}\n/**\n * Simple function that returns a Promise with a certain delay.\n *\n * @internal\n */\nexport function delay(delayInMs) {\n return new Promise((resolve) => setTimeout(resolve, delayInMs));\n}\n//# sourceMappingURL=utils.js.map","import { isClassLike } from \"./utils.js\";\nexport function isConstructorProvider(provider) {\n return isClassLike(provider);\n}\nexport function isClassProvider(provider) {\n return \"provide\" in provider && \"useClass\" in provider;\n}\nexport function isValueProvider(provider) {\n return \"provide\" in provider && \"useValue\" in provider;\n}\nexport function isFactoryProvider(provider) {\n return \"provide\" in provider && \"useFactory\" in provider;\n}\nexport function isAsyncProvider(provider) {\n return isFactoryProvider(provider) && provider.async === true;\n}\nexport function isExistingProvider(provider) {\n return \"provide\" in provider && \"useExisting\" in provider;\n}\nexport function isMultiProvider(provider) {\n return \"provide\" in provider && \"multi\" in provider && provider.multi === true;\n}\n//# sourceMappingURL=providers.js.map","import { isClassLike } from \"./utils.js\";\nimport {} from \"./providers.js\";\nimport * as Guards from \"./providers.js\";\n/**\n * A unique injection token object, that is used by reference. Can hold a generic type.\n * Can optionally hold an (async) factory.\n */\nexport class InjectionToken {\n description;\n options;\n constructor(description, options) {\n this.description = description;\n this.options = options;\n }\n toString() {\n return `InjectionToken \"${String(this.description)}\"`;\n }\n}\n/**\n * Type-guard to check if a token is a class reference.\n *\n * @internal\n */\nexport function isClassToken(token) {\n return isClassLike(token);\n}\n/**\n * Type-guard to check if a token is an InjectionToken\n *\n * @internal\n */\nexport function isInjectionToken(token) {\n return token instanceof InjectionToken;\n}\n/**\n * Describes a token, useful for error messages.\n *\n * @internal\n */\nexport function toString(token) {\n if (isClassLike(token)) {\n return token.name;\n }\n else if (typeof token === \"symbol\") {\n return token.description ?? String(token);\n }\n else if (token instanceof InjectionToken) {\n return token.toString();\n }\n else {\n return token;\n }\n}\n/**\n * Returns the token for a provider.\n *\n * @internal\n */\nexport function getToken(provider) {\n return Guards.isConstructorProvider(provider) ? provider : provider.provide;\n}\n//# sourceMappingURL=tokens.js.map","import { getParentClasses } from \"./utils.js\";\n/**\n * The @injectable() decorator allows you to automatically bind a class as singleton service\n * when requesting it from a DI container.\n */\nexport function injectable() {\n return (target) => {\n getParentClasses(target).forEach((parentClass) => {\n if (!Object.getOwnPropertyDescriptor(parentClass, injectableSymbol)) {\n Object.defineProperty(parentClass, injectableSymbol, {\n value: [target],\n writable: true,\n enumerable: false,\n });\n }\n else {\n const injectableParentClass = parentClass;\n injectableParentClass[injectableSymbol] = [...injectableParentClass[injectableSymbol], target];\n }\n });\n Object.defineProperty(target, injectableSymbol, {\n value: [target],\n writable: true,\n });\n };\n}\nexport const injectableSymbol = Symbol(\"injectable\");\nexport function isInjectable(target) {\n // eslint-disable-next-line no-prototype-builtins\n return target.hasOwnProperty(injectableSymbol);\n}\nexport function getInjectableTargets(target) {\n return target[injectableSymbol];\n}\n//# sourceMappingURL=decorators.js.map","import {} from \"./providers.js\";\nimport { getToken, toString } from \"./tokens.js\";\nimport * as Guards from \"./providers.js\";\nimport { assertNever, retryOn } from \"./utils.js\";\nimport { Container } from \"./container.js\";\n/**\n * @internal\n */\nexport class Factory {\n container;\n underConstruction = [];\n constructor(container) {\n this.container = container;\n }\n construct(provider, token) {\n if (Guards.isAsyncProvider(provider)) {\n throw new AsyncProvidersInSyncInjectionContextError(token);\n }\n try {\n if (this.underConstruction.includes(provider)) {\n const dependencyGraph = [...this.underConstruction, provider].map(getToken).map(toString);\n throw new CircularDependencyError(dependencyGraph);\n }\n this.underConstruction.push(provider);\n return this.doConstruct(provider);\n }\n finally {\n this.underConstruction.pop();\n }\n }\n async constructAsync(provider) {\n try {\n if (this.underConstruction.includes(provider)) {\n const dependencyGraph = [...this.underConstruction, provider].map(getToken).map(toString);\n throw new CircularDependencyError(dependencyGraph);\n }\n this.underConstruction.push(provider);\n if (Guards.isAsyncProvider(provider)) {\n return [await provider.useFactory(this.container)];\n }\n // in class and constructor providers, we allow stuff to be synchronously injected,\n // by just retrying when we encounter an async dependency down the road.\n // todo: this feels like an ugly workaround, so let's create something nice for this.\n if (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider)) {\n const create = Guards.isConstructorProvider(provider)\n ? () => [new provider()]\n : () => [new provider.useClass()];\n return retryOn(AsyncProvidersInSyncInjectionContextError, async () => create(), async (error) => {\n await this.container.getAsync(error.token, { multi: true, optional: true });\n });\n }\n // all other types of providers are constructed synchronously anyway.\n return this.doConstruct(provider);\n }\n finally {\n this.underConstruction.pop();\n }\n }\n doConstruct(provider) {\n if (Guards.isConstructorProvider(provider)) {\n return [new provider()];\n }\n else if (Guards.isClassProvider(provider)) {\n return [new provider.useClass()];\n }\n else if (Guards.isValueProvider(provider)) {\n return [provider.useValue];\n }\n else if (Guards.isFactoryProvider(provider)) {\n return [provider.useFactory(this.container)];\n }\n else if (Guards.isExistingProvider(provider)) {\n return this.container.get(provider.useExisting, { multi: true });\n }\n return assertNever(provider);\n }\n}\n/**\n * An error that occurs when an async provider is requested in a synchronous context.\n *\n * @internal\n */\nclass AsyncProvidersInSyncInjectionContextError extends Error {\n token;\n constructor(token) {\n super(`Some providers for token ${toString(token)} are async, please use injectAsync() or container.getAsync() instead`);\n this.token = token;\n }\n}\nclass CircularDependencyError extends Error {\n constructor(graph) {\n super(`Detected circular dependency: ${graph.join(\" -> \")}. Please change your dependency graph or use lazy injection instead.`);\n }\n}\n//# sourceMappingURL=factory.js.map","import { Container } from \"./container.js\";\nexport function inject(token, options) {\n try {\n return _currentContext.run((container) => container.get(token, options));\n }\n catch (error) {\n if (error instanceof NeedsInjectionContextError && options?.optional === true) {\n return undefined;\n }\n throw error;\n }\n}\nexport function injectAsync(token, options) {\n try {\n if (options?.lazy) {\n return _currentContext.run((container) => container.getAsync(token, { ...options, lazy: true }));\n }\n return _currentContext.runAsync((container) => container.getAsync(token, { ...options, lazy: false }));\n }\n catch (error) {\n if (error instanceof NeedsInjectionContextError && options?.optional === true) {\n return Promise.resolve(undefined);\n }\n return Promise.reject(error);\n }\n}\n/**\n * The global context does not allow dependency injection.\n *\n * @internal\n */\nclass GlobalContext {\n run() {\n throw new NeedsInjectionContextError();\n }\n runAsync() {\n throw new NeedsInjectionContextError();\n }\n}\n/**\n * An injection context allows to perform dependency injection with `inject()` and `injectAsync()`.\n *\n * @internal\n */\nclass InjectionContext {\n container;\n constructor(container) {\n this.container = container;\n }\n run(block) {\n const originalContext = _currentContext;\n try {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n _currentContext = this;\n return block(this.container);\n }\n finally {\n _currentContext = originalContext;\n }\n }\n async runAsync(block) {\n const originalContext = _currentContext;\n try {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n _currentContext = this;\n return await block(this.container);\n }\n finally {\n _currentContext = originalContext;\n }\n }\n}\nlet _currentContext = new GlobalContext();\n/**\n * Creates a new injection context.\n *\n * @internal\n */\nexport function injectionContext(container) {\n return new InjectionContext(container);\n}\n/**\n * An error that occurs when `inject()` or `injectAsync()` is used outside an injection context.\n *\n * @internal\n */\nclass NeedsInjectionContextError extends Error {\n constructor() {\n super(`You can only invoke inject() or injectAsync() within an injection context`);\n }\n}\n//# sourceMappingURL=context.js.map","import { isClassToken, toString, isInjectionToken, getToken } from \"./tokens.js\";\nimport * as Guards from \"./providers.js\";\nimport { getInjectableTargets, isInjectable } from \"./decorators.js\";\nimport { assertPresent, assertSingle, getParentClasses, promiseTry, windowedSlice } from \"./utils.js\";\nimport { Factory } from \"./factory.js\";\nimport { injectionContext } from \"./context.js\";\n/**\n * A dependency injection (DI) container will keep track of all bindings\n * and hold the actual instances of your services.\n */\nexport class Container {\n providers = new Map();\n singletons = new Map();\n parent;\n factory;\n constructor(parent) {\n this.parent = parent;\n this.factory = new Factory(this);\n this.bind({\n provide: Container,\n useValue: this,\n });\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n bindAll(...providers) {\n providers.forEach((it) => this.bind(it));\n return this;\n }\n /**\n * Binds a provider to this container.\n *\n * {@link https://needle-di.io/concepts/binding.html#binding}\n */\n bind(provider) {\n const token = getToken(provider);\n // running some validations...\n if (Guards.isExistingProvider(provider) && provider.provide === provider.useExisting) {\n throw Error(`The provider for token ${toString(token)} with \"useExisting\" cannot refer to itself.`);\n }\n if (!Guards.isExistingProvider(provider) && this.singletons.has(token)) {\n throw Error(`Cannot bind a new provider for ${toString(token)}, since the existing provider was already constructed.`);\n }\n // ignore the new provider if it was already provided\n if (Guards.isExistingProvider(provider) &&\n Guards.isMultiProvider(provider) &&\n this.existingProviderAlreadyProvided(token, provider.useExisting)) {\n return this;\n }\n const providers = this.providers.get(token) ?? [];\n // validating multi-provider inconsistencies...\n const multi = Guards.isMultiProvider(provider);\n if (multi && providers.some((it) => !Guards.isMultiProvider(it))) {\n throw Error(`Cannot bind ${toString(token)} as multi-provider, since there is already a provider which is not a multi-provider.`);\n }\n else if (!multi && providers.some((it) => Guards.isMultiProvider(it))) {\n if (!providers.every(Guards.isExistingProvider)) {\n throw Error(`Cannot bind ${toString(token)} as provider, since there are already provider(s) that are multi-providers.`);\n }\n }\n // appending or replacing providers...\n this.providers.set(token, multi ? [...providers, provider] : [provider]);\n // inheritance support: also bind parent classes to their immediate child classes\n if (isClassToken(token) && (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider))) {\n windowedSlice([token, ...getParentClasses(token)]).forEach(([childClass, parentClass]) => {\n const parentProvider = {\n provide: parentClass,\n useExisting: childClass,\n multi: true,\n };\n const existingParentProviders = this.providers.get(parentClass) ?? [];\n if (!this.existingProviderAlreadyProvided(parentClass, childClass)) {\n this.providers.set(parentClass, [...existingParentProviders, parentProvider]);\n }\n });\n }\n return this;\n }\n /**\n * Unbinds a provider.\n *\n * {@link https://needle-di.io/concepts/binding.html#binding}\n */\n unbind(provider) {\n const token = getToken(provider);\n this.providers.delete(token);\n this.singletons.delete(token);\n return this;\n }\n /**\n * Unbinds all providers.\n *\n * {@link https://needle-di.io/concepts/binding.html#binding}\n */\n unbindAll() {\n this.providers.clear();\n this.singletons.clear();\n return this;\n }\n get(token, options) {\n const lazy = options?.lazy ?? false;\n if (lazy) {\n return () => this.get(token, { ...options, lazy: false });\n }\n this.autoBindIfNeeded(token);\n const optional = options?.optional ?? false;\n if (!this.providers.has(token)) {\n if (this.parent) {\n return this.parent.get(token, { ...options, lazy: false });\n }\n if (optional) {\n return undefined;\n }\n throw Error(`No provider(s) found for ${toString(token)}`);\n }\n const providers = assertPresent(this.providers.get(token));\n if (!this.singletons.has(token)) {\n injectionContext(this).run(() => {\n const values = providers.flatMap((provider) => this.factory.construct(provider, token));\n this.singletons.set(token, values);\n });\n }\n const singletons = assertPresent(this.singletons.get(token));\n const multi = options?.multi ?? false;\n if (multi) {\n return singletons;\n }\n else {\n return assertSingle(singletons, () => Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +\n `Consider passing \"{ multi: true }\" to inject all values, or adjust your bindings accordingly.`));\n }\n }\n getAsync(token, options) {\n const lazy = options?.lazy ?? false;\n if (lazy) {\n return () => this.getAsync(token, { ...options, lazy: false });\n }\n return promiseTry(async () => {\n this.autoBindIfNeeded(token);\n const optional = options?.optional ?? false;\n if (!this.providers.has(token)) {\n if (optional) {\n return undefined;\n }\n throw Error(`No provider(s) found for ${toString(token)}`);\n }\n const providers = assertPresent(this.providers.get(token));\n if (!this.singletons.has(token)) {\n await injectionContext(this).runAsync(async () => {\n const values = await Promise.all(providers.map((it) => this.factory.constructAsync(it)));\n this.singletons.set(token, values.flat());\n });\n }\n const singletons = assertPresent(this.singletons.get(token));\n const multi = options?.multi ?? false;\n if (multi) {\n return singletons;\n }\n else {\n return assertSingle(singletons, () => new Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +\n `Consider passing \"{ multi: true }\" to inject all values, or adjust your bindings accordingly.`));\n }\n });\n }\n /**\n * Creates a child container.\n *\n * {@link https://needle-di.io/advanced/child-containers.html}\n */\n createChild() {\n return new Container(this);\n }\n /**\n * Returns whether the container has one or more providers for this token.\n */\n has(token) {\n return this.providers.has(token) || (this.parent?.has(token) ?? false);\n }\n autoBindIfNeeded(token) {\n if (this.singletons.has(token)) {\n return;\n }\n if (isClassToken(token) && isInjectable(token)) {\n const targetClasses = getInjectableTargets(token);\n targetClasses\n .filter((targetClass) => !this.providers.has(targetClass))\n .forEach((targetClass) => {\n this.bind({\n provide: targetClass,\n useClass: targetClass,\n multi: true,\n });\n });\n }\n else if (!this.providers.has(token) && isInjectionToken(token) && token.options?.factory) {\n const async = token.options.async;\n if (!async) {\n this.bind({\n provide: token,\n async: false,\n useFactory: token.options.factory,\n });\n }\n else if (async) {\n this.bind({\n provide: token,\n async: true,\n useFactory: token.options.factory,\n });\n }\n }\n }\n existingProviderAlreadyProvided(token, existingToken) {\n return (this.providers.get(token) ?? []).some((it) => Guards.isExistingProvider(it) && it.provide === token && it.useExisting === existingToken);\n }\n}\n/**\n * Bootstraps a new container and obtains a service using the provided token.\n */\nexport function bootstrap(token) {\n return new Container().get(token);\n}\n/**\n * Bootstraps a new container and obtains a service asynchronously using the provided token.\n */\nexport function bootstrapAsync(token) {\n return new Container().getAsync(token);\n}\n//# sourceMappingURL=container.js.map","import type { GeneralArguments } from '@/declarations';\n\nexport const unexpectedError = new Error(\n\t'[JSONCanvasViewer] This error is unexpected, probably caused by canvas file corruption. If you assure the error is not by accident, please contact the developer and show how to reproduce.',\n);\nexport const destroyError = new Error(\"[JSONCanvasViewer] Resource hasn't been set up or has been disposed.\");\n\nexport interface RuntimeJSONCanvasNode extends JSONCanvasNode {\n\tmdContent?: string;\n\tmdFrontmatter?: Record<string, string>;\n}\n\nexport function makeHook<Args extends GeneralArguments = []>() {\n\ttype MatchingFunc = (...args: Args) => unknown;\n\ttype Hook = {\n\t\t(...args: Args): void;\n\t\tsubs: Set<MatchingFunc>;\n\t\tsubscribe(callback: MatchingFunc): void;\n\t\tunsubscribe(callback: MatchingFunc): void;\n\t};\n\tconst result: Hook = (...args: Args) => {\n\t\tresult.subs.forEach(callback => {\n\t\t\tcallback(...args);\n\t\t});\n\t};\n\tresult.subs = new Set();\n\tresult.subscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.add(callback);\n\t};\n\tresult.unsubscribe = (callback: MatchingFunc) => {\n\t\tresult.subs.delete(callback);\n\t};\n\treturn result;\n}\n","import type { Coordinates, NodeBounds } from '@/declarations';\nimport { makeHook, unexpectedError } from '@/shared';\nimport { BaseModule } from './baseModule';\n\nconst GRID_CELL_SIZE = 800;\nconst INITIAL_VIEWPORT_PADDING = 100;\n\nexport default class DataManager extends BaseModule {\n\tprivate spatialGrid: Record<string, Array<JSONCanvasNode>> | null = null;\n\thooks = {\n\t\tonToggleFullscreen: makeHook<[boolean]>(),\n\t\tonCanvasFetched: makeHook(),\n\t};\n\tdata = {\n\t\tcanvasData: undefined as unknown as JSONCanvas,\n\t\tnodeMap: {} as Record<string, JSONCanvasNode>,\n\t\tcanvasBaseDir: undefined as unknown as string,\n\t\tnodeBounds: undefined as unknown as NodeBounds,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\tscale: 1,\n\t\tcontainer: document.createElement('div'),\n\t};\n\n\tloadCanvas = async () => {\n\t\tconst path = this.options.canvasPath;\n\t\ttry {\n\t\t\tthis.resolvePath(path);\n\t\t\tthis.data.canvasData = await fetch(path).then(res => res.json());\n\t\t\tthis.data.canvasData.nodes.forEach((node: JSONCanvasNode) => {\n\t\t\t\tif (node.type === 'file' && node.file && !node.file.includes('http')) {\n\t\t\t\t\tconst file = node.file.split('/');\n\t\t\t\t\tnode.file = file[file.length - 1];\n\t\t\t\t}\n\t\t\t\tthis.data.nodeMap[node.id] = node;\n\t\t\t});\n\t\t\tthis.data.nodeBounds = this.calculateNodeBounds();\n\t\t\tthis.buildSpatialGrid();\n\t\t\tthis.hooks.onCanvasFetched();\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to load canvas data:', err);\n\t\t}\n\t};\n\n\tprivate resolvePath = (path: string) => {\n\t\tif (/^https?:\\/\\//.test(path)) this.data.canvasBaseDir = path.substring(0, path.lastIndexOf('/') + 1);\n\t\telse {\n\t\t\tconst lastSlash = path.lastIndexOf('/');\n\t\t\tthis.data.canvasBaseDir = lastSlash !== -1 ? path.substring(0, lastSlash + 1) : './';\n\t\t}\n\t};\n\n\tfindNodeAt = (screenCoords: Coordinates) => {\n\t\tconst { x, y } = this.C2W(this.C2C({ x: screenCoords.x, y: screenCoords.y }));\n\t\tlet candidates: Array<JSONCanvasNode> = [];\n\t\tif (!this.spatialGrid) candidates = this.data.canvasData.nodes;\n\t\telse {\n\t\t\tconst col = Math.floor(x / GRID_CELL_SIZE);\n\t\t\tconst row = Math.floor(y / GRID_CELL_SIZE);\n\t\t\tconst key = `${col},${row}`;\n\t\t\tcandidates = this.spatialGrid[key] || [];\n\t\t}\n\t\tfor (const node of candidates) {\n\t\t\tif (\n\t\t\t\tx < node.x ||\n\t\t\t\tx > node.x + node.width ||\n\t\t\t\ty < node.y ||\n\t\t\t\ty > node.y + node.height ||\n\t\t\t\tthis.judgeInteract(node) === 'non-interactive'\n\t\t\t)\n\t\t\t\tcontinue;\n\t\t\treturn node;\n\t\t}\n\t\treturn null;\n\t};\n\n\t// how should the app handle node interactions\n\tprivate judgeInteract = (node: JSONCanvasNode | null) => {\n\t\tconst type = !node ? 'default' : node.type;\n\t\tswitch (type) {\n\t\t\tcase 'text':\n\t\t\tcase 'link':\n\t\t\t\treturn 'select';\n\t\t\tcase 'file': {\n\t\t\t\tconst file = node?.file;\n\t\t\t\tif (!file) throw unexpectedError;\n\t\t\t\tif (file.match(/\\.(md|wav|mp3)$/i)) return 'select';\n\t\t\t\telse return 'non-interactive';\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn 'non-interactive';\n\t\t}\n\t};\n\n\tprivate calculateNodeBounds() {\n\t\tlet minX = Infinity,\n\t\t\tminY = Infinity,\n\t\t\tmaxX = -Infinity,\n\t\t\tmaxY = -Infinity;\n\t\tthis.data.canvasData.nodes.forEach(node => {\n\t\t\tminX = Math.min(minX, node.x);\n\t\t\tminY = Math.min(minY, node.y);\n\t\t\tmaxX = Math.max(maxX, node.x + node.width);\n\t\t\tmaxY = Math.max(maxY, node.y + node.height);\n\t\t});\n\t\tconst width = maxX - minX;\n\t\tconst height = maxY - minY;\n\t\tconst centerX = minX + width / 2;\n\t\tconst centerY = minY + height / 2;\n\t\treturn { minX, minY, maxX, maxY, width, height, centerX, centerY };\n\t}\n\n\tprivate buildSpatialGrid() {\n\t\tconst canvasData = this.data.canvasData;\n\t\tif (canvasData.nodes.length < 50) return;\n\t\tthis.spatialGrid = {};\n\t\tfor (const node of canvasData.nodes) {\n\t\t\tconst minCol = Math.floor(node.x / GRID_CELL_SIZE);\n\t\t\tconst maxCol = Math.floor((node.x + node.width) / GRID_CELL_SIZE);\n\t\t\tconst minRow = Math.floor(node.y / GRID_CELL_SIZE);\n\t\t\tconst maxRow = Math.floor((node.y + node.height) / GRID_CELL_SIZE);\n\t\t\tfor (let col = minCol; col <= maxCol; col++) {\n\t\t\t\tfor (let row = minRow; row <= maxRow; row++) {\n\t\t\t\t\tconst key = `${col},${row}`;\n\t\t\t\t\tif (!this.spatialGrid[key]) this.spatialGrid[key] = [];\n\t\t\t\t\tthis.spatialGrid[key].push(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tzoom = (factor: number, origin: Coordinates) => {\n\t\tconst newScale = this.data.scale * factor;\n\t\tthis.zoomToScale(newScale, origin);\n\t};\n\tzoomToScale = (newScale: number, origin: Coordinates) => {\n\t\tconst validNewScale = Math.max(Math.min(newScale, 20), 0.05);\n\t\tconst scale = this.data.scale;\n\t\tif (validNewScale === scale) return;\n\t\tconst canvasCoords = this.C2C(origin);\n\t\tthis.data.offsetX = origin.x - (canvasCoords.x * validNewScale) / scale;\n\t\tthis.data.offsetY = origin.y - (canvasCoords.y * validNewScale) / scale;\n\t\tthis.data.scale = validNewScale;\n\t};\n\tpan = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = this.data.offsetX + x;\n\t\tthis.data.offsetY = this.data.offsetY + y;\n\t};\n\tpanToCoords = ({ x, y }: Coordinates) => {\n\t\tthis.data.offsetX = x;\n\t\tthis.data.offsetY = y;\n\t};\n\tshiftFullscreen = (option: string = 'toggle') => {\n\t\tif (!document.fullscreenElement && (option === 'toggle' || option === 'enter')) {\n\t\t\tthis.data.container.requestFullscreen();\n\t\t\tthis.hooks.onToggleFullscreen(true);\n\t\t} else if (document.fullscreenElement && (option === 'toggle' || option === 'exit')) {\n\t\t\tdocument.exitFullscreen();\n\t\t\tthis.hooks.onToggleFullscreen(false);\n\t\t}\n\t};\n\tresetView = () => {\n\t\tconst bounds = this.data.nodeBounds;\n\t\tconst container = this.data.container;\n\t\tif (!bounds || !container) return;\n\t\tconst contentWidth = bounds.width + INITIAL_VIEWPORT_PADDING * 2;\n\t\tconst contentHeight = bounds.height + INITIAL_VIEWPORT_PADDING * 2;\n\t\t// Use logical dimensions for scaling calculations\n\t\tconst viewWidth = container.clientWidth;\n\t\tconst viewHeight = container.clientHeight;\n\t\tconst scaleX = viewWidth / contentWidth;\n\t\tconst scaleY = viewHeight / contentHeight;\n\t\tconst newScale = Math.round(Math.min(scaleX, scaleY) * 1000) / 1000;\n\t\tconst contentCenterX = bounds.centerX;\n\t\tconst contentCenterY = bounds.centerY;\n\t\tconst initialView = {\n\t\t\tscale: newScale,\n\t\t\toffsetX: viewWidth / 2 - contentCenterX * newScale,\n\t\t\toffsetY: viewHeight / 2 - contentCenterY * newScale,\n\t\t};\n\t\tthis.data.offsetX = initialView.offsetX;\n\t\tthis.data.offsetY = initialView.offsetY;\n\t\tthis.data.scale = initialView.scale;\n\t};\n\n\t// Container to Canvas\n\tprivate C2C = ({ x: containerX, y: containerY }: Coordinates) => ({\n\t\tx: containerX - this.data.offsetX,\n\t\ty: containerY - this.data.offsetY,\n\t});\n\t// Canvas to World\n\tprivate C2W = ({ x: canvasX, y: canvasY }: Coordinates) => ({\n\t\tx: canvasX / this.data.scale,\n\t\ty: canvasY / this.data.scale,\n\t});\n\n\tmiddleViewer = () => {\n\t\tconst container = this.data.container;\n\t\treturn {\n\t\t\tx: container.clientWidth / 2,\n\t\t\ty: container.clientHeight / 2,\n\t\t\twidth: container.clientWidth,\n\t\t\theight: container.clientHeight,\n\t\t};\n\t};\n\n\tdispose = () => {\n\t\tthis.data.container.remove();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport { makeHook } from '@/shared';\nimport style from '@/styles.scss?inline';\n\ntype Options = {\n\tnoShadow?: boolean;\n};\n\nexport default class Controller extends BaseModule<Options> {\n\tprivate animationId: null | number = null;\n\tprivate resizeAnimationId: null | number = null;\n\tprivate DM: DataManager;\n\tprivate perFrame: {\n\t\tlastScale: number;\n\t\tlastOffsets: { x: number; y: number };\n\t} = {\n\t\tlastScale: 1,\n\t\tlastOffsets: { x: 0, y: 0 },\n\t};\n\tprivate lastResizeCenter: {\n\t\tx: null | number;\n\t\ty: null | number;\n\t} = {\n\t\tx: null,\n\t\ty: null,\n\t};\n\n\thooks = {\n\t\tonResize: makeHook<[number, number]>(),\n\t\tonRefresh: makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\n\t\tconst parentContainer = this.options.container;\n\t\twhile (parentContainer.firstElementChild) parentContainer.firstElementChild.remove();\n\t\tparentContainer.innerHTML = '';\n\n\t\tconst noShadow = this.options.noShadow || false;\n\t\tconst realContainer = noShadow ? parentContainer : parentContainer.attachShadow({ mode: 'open' });\n\n\t\tthis.utilities.applyStyles(realContainer, style);\n\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tHTMLContainer.classList.add('container');\n\t\trealContainer.appendChild(HTMLContainer);\n\t}\n\n\tprivate onFetched = () => {\n\t\tthis.DM.resetView();\n\t\tthis.resizeObserver.observe(this.DM.data.container);\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate draw = () => {\n\t\tif (\n\t\t\tthis.perFrame.lastScale !== this.DM.data.scale ||\n\t\t\tthis.perFrame.lastOffsets.x !== this.DM.data.offsetX ||\n\t\t\tthis.perFrame.lastOffsets.y !== this.DM.data.offsetY\n\t\t)\n\t\t\tthis.refresh();\n\t\tthis.animationId = requestAnimationFrame(this.draw);\n\t};\n\n\tprivate refresh = () => {\n\t\tthis.perFrame.lastScale = this.DM.data.scale;\n\t\tthis.perFrame.lastOffsets = {\n\t\t\tx: this.DM.data.offsetX,\n\t\t\ty: this.DM.data.offsetY,\n\t\t};\n\t\tthis.hooks.onRefresh();\n\t};\n\n\tprivate onResize = () => {\n\t\tthis.resizeAnimationId = requestAnimationFrame(() => {\n\t\t\tconst center = this.DM.middleViewer();\n\t\t\tif (this.lastResizeCenter.x && this.lastResizeCenter.y) {\n\t\t\t\tthis.DM.data.offsetX = this.DM.data.offsetX + center.x - this.lastResizeCenter.x;\n\t\t\t\tthis.DM.data.offsetY = this.DM.data.offsetY + center.y - this.lastResizeCenter.y;\n\t\t\t}\n\t\t\tthis.lastResizeCenter.x = center.x;\n\t\t\tthis.lastResizeCenter.y = center.y;\n\t\t\tthis.hooks.onResize(center.width, center.height);\n\t\t\tthis.refresh();\n\t\t});\n\t};\n\tprivate resizeObserver: ResizeObserver = new ResizeObserver(this.onResize);\n\n\tdispose = () => {\n\t\tif (this.animationId) cancelAnimationFrame(this.animationId);\n\t\tif (this.resizeAnimationId) cancelAnimationFrame(this.resizeAnimationId);\n\t\tthis.resizeObserver.disconnect();\n\t};\n}\n","import Purify from 'dompurify';\nimport { micromark } from 'micromark';\nimport { gfm, gfmHtml } from 'micromark-extension-gfm';\nimport { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport InteractionHandler from '@/interactionHandler';\nimport { destroyError, makeHook, type RuntimeJSONCanvasNode, unexpectedError } from '@/shared';\n\nexport default class OverlayManager extends BaseModule {\n\tprivate _overlaysLayer: HTMLDivElement | null = document.createElement('div');\n\tprivate overlays: Record<string, HTMLDivElement> = {}; // { id: node } the overlays in viewport\n\tprivate selectedId: string | null = null;\n\tprivate eventListeners: Record<string, Array<EventListener | null>> = {};\n\tprivate DM: DataManager;\n\tprivate IH: () => InteractionHandler;\n\tprivate parser = (markdown: string) =>\n\t\tmicromark(markdown, { extensions: [gfm()], htmlExtensions: [gfmHtml()] });\n\n\tprivate get overlaysLayer() {\n\t\tif (!this._overlaysLayer) throw destroyError;\n\t\treturn this._overlaysLayer;\n\t}\n\n\thooks = {\n\t\tonInteractionStart: makeHook(),\n\t\tonInteractionEnd: makeHook(),\n\t};\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.IH = this.container.get(InteractionHandler, { lazy: true });\n\t\tconst controller = this.container.get(Controller);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\t\tcontroller.hooks.onRefresh.subscribe(this.updateOverlays);\n\n\t\tthis._overlaysLayer = document.createElement('div');\n\t\tthis._overlaysLayer.className = 'overlays';\n\t\tthis.DM.data.container.appendChild(this.overlaysLayer);\n\t}\n\n\tprivate onFetched = () => {\n\t\tthis.IH().onClick.subscribe(this.select);\n\t\tconst cbd = this.DM.data.canvasBaseDir;\n\t\tconst overlayCreators = {\n\t\t\ttext: (node: RuntimeJSONCanvasNode) => {\n\t\t\t\tif (!node.text) throw unexpectedError;\n\t\t\t\tthis.updateOrCreateOverlay(node, node.text, 'text');\n\t\t\t},\n\t\t\tfile: (node: RuntimeJSONCanvasNode) => {\n\t\t\t\tif (!node.file) throw unexpectedError;\n\t\t\t\tif (node.file.match(/\\.md$/i)) this.loadMarkdownForNode(node);\n\t\t\t\telse if (node.file.match(/\\.(png|jpg|jpeg|gif|svg|webp)$/i))\n\t\t\t\t\tthis.updateOrCreateOverlay(node, cbd + node.file, 'image');\n\t\t\t\telse if (node.file.match(/\\.(mp3|wav)$/i))\n\t\t\t\t\tthis.updateOrCreateOverlay(node, cbd + node.file, 'audio');\n\t\t\t},\n\t\t\tlink: (node: RuntimeJSONCanvasNode) => {\n\t\t\t\tif (!node.url) throw unexpectedError;\n\t\t\t\tthis.updateOrCreateOverlay(node, node.url, 'link');\n\t\t\t},\n\t\t\tgroup: () => {},\n\t\t};\n\t\tObject.values(this.DM.data.nodeMap).forEach(node => {\n\t\t\toverlayCreators[node.type](node);\n\t\t});\n\t};\n\n\tprivate select = (id: string | null) => {\n\t\tconst previous = !this.selectedId ? null : this.overlays[this.selectedId];\n\t\tconst current = !id ? null : this.overlays[id];\n\t\tif (previous) previous.classList.remove('active');\n\t\tif (current) {\n\t\t\tcurrent.classList.add('active');\n\t\t\tthis.hooks.onInteractionStart();\n\t\t} else this.hooks.onInteractionEnd();\n\t\tthis.selectedId = id;\n\t};\n\n\tprivate loadMarkdownForNode = async (node: RuntimeJSONCanvasNode) => {\n\t\tif (!node.mdContent) {\n\t\t\tnode.mdContent = 'Loading...';\n\t\t\tthis.updateOrCreateOverlay(node, node.mdContent, 'markdown');\n\t\t\ttry {\n\t\t\t\tif (!node.file) throw unexpectedError;\n\t\t\t\tconst response = await fetch(this.DM.data.canvasBaseDir + node.file);\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) {\n\t\t\t\t\tconst frontmatter = frontmatterMatch[1]\n\t\t\t\t\t\t.split('\\n')\n\t\t\t\t\t\t.reduce((acc: Record<string, string>, line) => {\n\t\t\t\t\t\t\tconst [key, value] = line.split(':').map(s => s.trim());\n\t\t\t\t\t\t\tacc[key] = value;\n\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t}, {});\n\t\t\t\t\tnode.mdContent = Purify.sanitize(this.parser(frontmatterMatch[2].trim()));\n\t\t\t\t\tnode.mdFrontmatter = frontmatter;\n\t\t\t\t} else node.mdContent = Purify.sanitize(this.parser(result));\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('[JSONCanvasViewer] Failed to load markdown:', err);\n\t\t\t\tnode.mdContent = 'Failed to load content.';\n\t\t\t}\n\t\t}\n\t\tthis.updateOrCreateOverlay(node, node.mdContent, 'markdown');\n\t};\n\n\tprivate updateOverlays = () => {\n\t\tconst data = this.DM.data;\n\t\tthis.overlaysLayer.style.transform = `translate(${data.offsetX}px, ${data.offsetY}px) scale(${data.scale})`;\n\t};\n\n\tprivate async updateOrCreateOverlay(node: RuntimeJSONCanvasNode, content: string, type: string) {\n\t\tlet element = this.overlays[node.id];\n\t\tif (!element) {\n\t\t\telement = await this.constructOverlay(node, content, type);\n\t\t\tthis.overlaysLayer.appendChild(element);\n\t\t\tthis.overlays[node.id] = element;\n\t\t\telement.style.left = `${node.x}px`;\n\t\t\telement.style.top = `${node.y}px`;\n\t\t\telement.style.width = `${node.width}px`;\n\t\t\telement.style.height = `${node.height}px`;\n\t\t}\n\t\tif (element.style.display === 'none') element.style.display = 'flex';\n\t\tif (type === 'markdown') {\n\t\t\tconst parsedContentContainer = element.getElementsByClassName('parsed-content-wrapper')[0];\n\t\t\tif (!node.mdContent) throw unexpectedError;\n\t\t\tif (parsedContentContainer.innerHTML !== node.mdContent)\n\t\t\t\tparsedContentContainer.innerHTML = node.mdContent;\n\t\t\tif (!element.classList.contains('rtl') && node.mdFrontmatter?.direction === 'rtl')\n\t\t\t\telement.classList.add('rtl');\n\t\t}\n\t}\n\n\tprivate async constructOverlay(node: RuntimeJSONCanvasNode, content: string, type: string) {\n\t\tconst color = this.utilities.getColor(node.color);\n\t\tconst overlay = document.createElement('div');\n\t\toverlay.classList.add('overlay-container');\n\t\toverlay.id = node.id;\n\t\toverlay.style.backgroundColor = color.background;\n\t\toverlay.style.setProperty('--active-color', color.active);\n\t\tswitch (type) {\n\t\t\tcase 'text':\n\t\t\tcase 'markdown': {\n\t\t\t\toverlay.classList.add('markdown-content');\n\t\t\t\tconst parsedContentWrapper = document.createElement('div');\n\t\t\t\tparsedContentWrapper.innerHTML = Purify.sanitize(this.parser(content || ''));\n\t\t\t\tparsedContentWrapper.classList.add('parsed-content-wrapper');\n\t\t\t\toverlay.appendChild(parsedContentWrapper);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'link': {\n\t\t\t\tconst iframe = document.createElement('iframe');\n\t\t\t\tiframe.src = content;\n\t\t\t\tiframe.sandbox = 'allow-scripts allow-same-origin';\n\t\t\t\tiframe.className = 'link-iframe';\n\t\t\t\tiframe.loading = 'lazy';\n\t\t\t\toverlay.appendChild(iframe);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'audio': {\n\t\t\t\tconst audio = document.createElement('audio');\n\t\t\t\taudio.className = 'audio';\n\t\t\t\taudio.src = content;\n\t\t\t\taudio.controls = true;\n\t\t\t\toverlay.appendChild(audio);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst img = document.createElement('img');\n\t\t\t\timg.src = content;\n\t\t\t\timg.loading = 'lazy';\n\t\t\t\toverlay.appendChild(img);\n\t\t\t}\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase 'link':\n\t\t\tcase 'audio': {\n\t\t\t\tconst clickLayer = document.createElement('div');\n\t\t\t\tclickLayer.className = 'click-layer';\n\t\t\t\toverlay.appendChild(clickLayer);\n\t\t\t}\n\t\t}\n\t\tconst overlayBorder = document.createElement('div');\n\t\toverlayBorder.className = 'overlay-border';\n\t\toverlayBorder.style.borderColor = color.border;\n\t\toverlay.appendChild(overlayBorder);\n\t\tconst onStart = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionStart();\n\t\t};\n\t\tconst onEnd = () => {\n\t\t\tif (node.id === this.selectedId) this.hooks.onInteractionEnd();\n\t\t};\n\t\toverlay.addEventListener('pointerenter', onStart);\n\t\toverlay.addEventListener('pointerleave', onEnd);\n\t\toverlay.addEventListener('touchstart', onStart);\n\t\toverlay.addEventListener('touchend', onEnd);\n\t\tthis.eventListeners[node.id] = [onStart, onEnd];\n\t\treturn overlay;\n\t}\n\n\tdispose = () => {\n\t\twhile (this.overlaysLayer.firstElementChild) {\n\t\t\tconst child = this.overlaysLayer.firstElementChild;\n\t\t\tif (this.eventListeners[child.id]) {\n\t\t\t\tconst onStart = this.eventListeners[child.id][0];\n\t\t\t\tconst onEnd = this.eventListeners[child.id][1];\n\t\t\t\tif (!onStart || !onEnd) throw destroyError;\n\t\t\t\tchild.removeEventListener('pointerenter', onStart);\n\t\t\t\tchild.removeEventListener('pointerleave', onEnd);\n\t\t\t\tchild.removeEventListener('touchstart', onStart);\n\t\t\t\tchild.removeEventListener('touchend', onEnd);\n\t\t\t\tthis.eventListeners[child.id][0] = null;\n\t\t\t\tthis.eventListeners[child.id][1] = null;\n\t\t\t}\n\t\t\tchild.remove();\n\t\t}\n\t\tthis.overlaysLayer.remove();\n\t\tthis._overlaysLayer = null;\n\t};\n}\n","import {\n\tClick,\n\ttype Ctors,\n\tDrag,\n\tMultitouchPanZoom,\n\tPointeract,\n\tPreventDefault,\n\ttype StdEvents,\n\tWheelPanZoom,\n} from 'pointeract';\nimport { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport OverlayManager from '@/overlayManager';\nimport { makeHook } from '@/shared';\n\ntype Options = {\n\tinteractions?: {\n\t\tproControlSchema?: boolean;\n\t\tzoomFactor?: number;\n\t\tlockControlSchema?: boolean;\n\t};\n};\n\nexport default class InteractionHandler extends BaseModule<Options> {\n\tprivate pointeract: Pointeract<Ctors<[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom]>>;\n\tprivate DM: DataManager;\n\tprivate OM: OverlayManager;\n\tonClick = makeHook<[string | null]>();\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.OM = this.container.get(OverlayManager);\n\t\tconst options = Object.assign(\n\t\t\t{ proControlSchema: false, zoomFactor: 0.1, lockControlSchema: false },\n\t\t\tthis.options.interactions || {},\n\t\t);\n\t\tthis.pointeract = new Pointeract(\n\t\t\tthis.DM.data.container,\n\t\t\t[Click, Drag, WheelPanZoom, PreventDefault, MultitouchPanZoom],\n\t\t\toptions,\n\t\t);\n\t\tthis.startInteraction = this.pointeract.start;\n\t\tthis.stopInteraction = this.pointeract.stop;\n\t\tconst OM = this.container.get(OverlayManager);\n\t\tOM.hooks.onInteractionStart.subscribe(this.stopInteraction);\n\t\tOM.hooks.onInteractionEnd.subscribe(this.startInteraction);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.onFetched);\n\t}\n\tstopInteraction: Pointeract['stop'];\n\tstartInteraction: Pointeract['start'];\n\n\tprivate onFetched = () => {\n\t\tthis.pointeract.on('pan', this.onPan);\n\t\tthis.pointeract.on('drag', this.onPan);\n\t\tthis.pointeract.on('zoom', this.onZoom);\n\t\tthis.pointeract.on('trueClick', this.onTrueClick);\n\t\tthis.pointeract.start();\n\t};\n\n\tprivate onPan = (event: StdEvents['pan']) => {\n\t\tthis.DM.pan(event.detail);\n\t};\n\tprivate onZoom = (event: StdEvents['zoom']) => {\n\t\tconst detail = event.detail;\n\t\tthis.DM.zoom(detail.factor, { x: detail.x, y: detail.y });\n\t};\n\n\tprivate onTrueClick = (e: StdEvents['trueClick']) => {\n\t\tconst detail = e.detail;\n\t\tfunction isUIControl(target: HTMLElement | null) {\n\t\t\tif (!target) return false;\n\t\t\treturn target.closest('.controls') || target.closest('button') || target.closest('input');\n\t\t}\n\t\tif (isUIControl(e.detail.target as HTMLElement | null)) return;\n\t\tconst node = this.DM.findNodeAt({ x: detail.x, y: detail.y });\n\t\tthis.onClick(node ? node.id : null);\n\t};\n\n\tdispose = () => {\n\t\tthis.pointeract.off('pan', this.onPan);\n\t\tthis.pointeract.off('zoom', this.onZoom);\n\t\tthis.pointeract.off('trueClick', this.onTrueClick);\n\t\tthis.pointeract.dispose();\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport { destroyError, unexpectedError } from '@/shared';\n\ninterface viewport {\n\tleft: number;\n\tright: number;\n\ttop: number;\n\tbottom: number;\n}\n\ninterface RuntimeJSONCanvasEdge extends JSONCanvasEdge {\n\tcontrolPoints?: Array<number>;\n}\n\nconst ARROW_LENGTH = 12;\nconst ARROW_WIDTH = 7;\nconst NODE_RADIUS = 12;\nconst FONT_COLOR = '#fff';\nconst CSS_ZOOM_REDRAW_INTERVAL = 500;\n\nexport default class Renderer extends BaseModule {\n\tprivate _canvas: HTMLCanvasElement | null;\n\tprivate ctx: CanvasRenderingContext2D;\n\tprivate DM: DataManager;\n\tprivate zoomInOptimize: {\n\t\tlastDrawnScale: number;\n\t\tlastDrawnViewport: viewport;\n\t\ttimeout: NodeJS.Timeout | null;\n\t\tlastCallTime: number;\n\t} = {\n\t\tlastDrawnScale: 0,\n\t\tlastDrawnViewport: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\ttop: 0,\n\t\t\tbottom: 0,\n\t\t},\n\t\ttimeout: null,\n\t\tlastCallTime: 0,\n\t};\n\n\tprivate get canvas() {\n\t\tif (this._canvas === null) throw destroyError;\n\t\treturn this._canvas;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst controller = this.container.get(Controller);\n\t\tcontroller.hooks.onRefresh.subscribe(this.redraw);\n\t\tcontroller.hooks.onResize.subscribe(this.optimizeDPR);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._canvas = document.createElement('canvas');\n\t\tthis._canvas.className = 'main-canvas';\n\t\tthis.ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis.DM.data.container.appendChild(this._canvas);\n\t}\n\n\tprivate optimizeDPR = () => {\n\t\tconst container = this.DM.data.container;\n\t\tthis.utilities.resizeCanvasForDPR(this.canvas, container.offsetWidth, container.offsetHeight);\n\t};\n\n\tprivate redraw = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst offsetX = this.DM.data.offsetX;\n\t\tconst offsetY = this.DM.data.offsetY;\n\t\tconst scale = this.DM.data.scale;\n\t\tconst currentViewport = this.getCurrentViewport(offsetX, offsetY, scale);\n\t\tif (\n\t\t\tthis.isViewportInside(currentViewport, this.zoomInOptimize.lastDrawnViewport) &&\n\t\t\tscale !== this.zoomInOptimize.lastDrawnScale\n\t\t) {\n\t\t\tconst timeSinceLast = now - this.zoomInOptimize.lastCallTime;\n\t\t\tif (timeSinceLast < CSS_ZOOM_REDRAW_INTERVAL) {\n\t\t\t\tthis.zoomInOptimize.timeout = setTimeout(() => {\n\t\t\t\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t\t\t\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\t\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t\t\t}, 60);\n\t\t\t\tthis.fakeRedraw(currentViewport, scale);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.zoomInOptimize.lastCallTime = now;\n\t\tthis.trueRedraw(offsetX, offsetY, scale, currentViewport);\n\t};\n\n\tprivate trueRedraw(offsetX: number, offsetY: number, scale: number, currentViewport: viewport) {\n\t\tthis.zoomInOptimize.lastDrawnViewport = currentViewport;\n\t\tthis.zoomInOptimize.lastDrawnScale = scale;\n\t\tthis.canvas.style.transform = '';\n\t\tthis.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(offsetX, offsetY);\n\t\tthis.ctx.scale(scale, scale);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tcanvasData.nodes.forEach(node => {\n\t\t\tswitch (node.type) {\n\t\t\t\tcase 'group':\n\t\t\t\t\tthis.drawGroup(node, scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'file':\n\t\t\t\t\tthis.drawFileNode(node);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\tcanvasData.edges.forEach(edge => {\n\t\t\tthis.drawEdge(edge);\n\t\t});\n\t\tthis.ctx.restore();\n\t}\n\n\tprivate fakeRedraw(currentViewport: viewport, scale: number) {\n\t\tconst cssScale = scale / this.zoomInOptimize.lastDrawnScale;\n\t\tconst currentOffsetX = (this.zoomInOptimize.lastDrawnViewport.left - currentViewport.left) * scale;\n\t\tconst currentOffsetY = (this.zoomInOptimize.lastDrawnViewport.top - currentViewport.top) * scale;\n\t\tthis.canvas.style.transform = `translate(${currentOffsetX}px, ${currentOffsetY}px) scale(${cssScale})`;\n\t}\n\n\tprivate isViewportInside = (inner: viewport, outer: viewport) =>\n\t\tinner.left > outer.left &&\n\t\tinner.top > outer.top &&\n\t\tinner.right < outer.right &&\n\t\tinner.bottom < outer.bottom;\n\n\tprivate getCurrentViewport = (offsetX: number, offsetY: number, scale: number) => {\n\t\tconst left = -offsetX / scale;\n\t\tconst top = -offsetY / scale;\n\t\tconst container = this.DM.data.container;\n\t\tconst right = left + container.clientWidth / scale;\n\t\tconst bottom = top + container.clientHeight / scale;\n\t\treturn { left, top, right, bottom };\n\t};\n\n\tprivate drawLabelBar = (x: number, y: number, label: string, color: string, scale: number) => {\n\t\tconst barHeight = 30 * scale;\n\t\tconst radius = 6 * scale;\n\t\tconst yOffset = 8 * scale;\n\t\tconst fontSize = 16 * scale;\n\t\tconst xPadding = 6 * scale;\n\t\tthis.ctx.save();\n\t\tthis.ctx.translate(x, y);\n\t\tthis.ctx.scale(1 / scale, 1 / scale);\n\t\tthis.ctx.font = `${fontSize}px 'Inter', sans-serif`;\n\t\tconst barWidth = this.ctx.measureText(label).width + 2 * xPadding;\n\t\tthis.ctx.translate(0, -barHeight - yOffset);\n\t\tthis.ctx.fillStyle = color;\n\t\tthis.ctx.beginPath();\n\t\tthis.ctx.moveTo(radius, 0);\n\t\tthis.ctx.lineTo(barWidth - radius, 0);\n\t\tthis.ctx.quadraticCurveTo(barWidth, 0, barWidth, radius);\n\t\tthis.ctx.lineTo(barWidth, barHeight - radius);\n\t\tthis.ctx.quadraticCurveTo(barWidth, barHeight, barWidth - radius, barHeight);\n\t\tthis.ctx.lineTo(radius, barHeight);\n\t\tthis.ctx.quadraticCurveTo(0, barHeight, 0, barHeight - radius);\n\t\tthis.ctx.lineTo(0, radius);\n\t\tthis.ctx.quadraticCurveTo(0, 0, radius, 0);\n\t\tthis.ctx.closePath();\n\t\tthis.ctx.fill();\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.fillText(label, xPadding, barHeight * 0.65);\n\t\tthis.ctx.restore();\n\t};\n\n\tprivate drawNodeBackground = (node: JSONCanvasNode) => {\n\t\tconst colors = this.utilities.getColor(node.color);\n\t\tconst radius = NODE_RADIUS;\n\t\tthis.ctx.globalAlpha = 1.0;\n\t\tthis.ctx.fillStyle = colors.background;\n\t\tthis.utilities.drawRoundRect(\n\t\t\tthis.ctx,\n\t\t\tnode.x + 1,\n\t\t\tnode.y + 1,\n\t\t\tnode.width - 2,\n\t\t\tnode.height - 2,\n\t\t\tradius,\n\t\t);\n\t\tthis.ctx.fill();\n\t\tthis.ctx.strokeStyle = colors.border;\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.utilities.drawRoundRect(this.ctx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawGroup = (node: JSONCanvasNode, scale: number) => {\n\t\tthis.drawNodeBackground(node);\n\t\tif (node.label)\n\t\t\tthis.drawLabelBar(node.x, node.y, node.label, this.utilities.getColor(node.color).border, scale);\n\t};\n\n\tprivate drawFileNode = (node: JSONCanvasNode) => {\n\t\tif (!node.file) throw unexpectedError;\n\t\tthis.ctx.fillStyle = FONT_COLOR;\n\t\tthis.ctx.font = '16px sans-serif';\n\t\tthis.ctx.fillText(node.file, node.x + 5, node.y - 10);\n\t};\n\n\tprivate drawEdge = (edge: RuntimeJSONCanvasEdge) => {\n\t\tconst { fromNode, toNode } = this.getEdgeNodes(edge);\n\t\tif (!fromNode || !toNode) throw unexpectedError;\n\t\tconst gac = this.utilities.getAnchorCoord;\n\t\tconst [startX, startY] = gac(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = gac(toNode, edge.toSide);\n\t\tlet [startControlX, startControlY, endControlX, endControlY] = [0, 0, 0, 0];\n\t\tif (!edge.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\tedge.controlPoints = [startControlX, startControlY, endControlX, endControlY];\n\t\t} else [startControlX, startControlY, endControlX, endControlY] = edge.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);\n\t\tthis.drawArrowhead(endX, endY, endControlX, endControlY);\n\t\tif (edge.label) {\n\t\t\tconst t = 0.5;\n\t\t\tconst x =\n\t\t\t\t(1 - t) ** 3 * startX +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlX +\n\t\t\t\t3 * (1 - t) * t * t * endControlX +\n\t\t\t\tt ** 3 * endX;\n\t\t\tconst y =\n\t\t\t\t(1 - t) ** 3 * startY +\n\t\t\t\t3 * (1 - t) ** 2 * t * startControlY +\n\t\t\t\t3 * (1 - t) * t * t * endControlY +\n\t\t\t\tt ** 3 * endY;\n\t\t\tthis.ctx.font = '18px sans-serif';\n\t\t\tconst metrics = this.ctx.measureText(edge.label);\n\t\t\tconst padding = 8;\n\t\t\tconst labelWidth = metrics.width + padding * 2;\n\t\t\tconst labelHeight = 20;\n\t\t\tthis.ctx.fillStyle = '#222';\n\t\t\tthis.ctx.beginPath();\n\t\t\tthis.utilities.drawRoundRect(\n\t\t\t\tthis.ctx,\n\t\t\t\tx - labelWidth / 2,\n\t\t\t\ty - labelHeight / 2 - 2,\n\t\t\t\tlabelWidth,\n\t\t\t\tlabelHeight,\n\t\t\t\t4,\n\t\t\t);\n\t\t\tthis.ctx.fill();\n\t\t\tthis.ctx.fillStyle = '#ccc';\n\t\t\tthis.ctx.textAlign = 'center';\n\t\t\tthis.ctx.textBaseline = 'middle';\n\t\t\tthis.ctx.fillText(edge.label, x, y - 2);\n\t\t\tthis.ctx.textAlign = 'left';\n\t\t\tthis.ctx.textBaseline = 'alphabetic';\n\t\t}\n\t};\n\n\tprivate getEdgeNodes = (edge: JSONCanvasEdge) => ({\n\t\tfromNode: this.DM.data.nodeMap[edge.fromNode],\n\t\ttoNode: this.DM.data.nodeMap[edge.toNode],\n\t});\n\n\tprivate getControlPoints = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tfromSide: string,\n\t\ttoSide: string,\n\t) => {\n\t\tconst distanceX = endX - startX;\n\t\tconst distanceY = endY - startY;\n\t\tconst realDistance =\n\t\t\tMath.min(Math.abs(distanceX), Math.abs(distanceY)) +\n\t\t\t0.3 * Math.max(Math.abs(distanceX), Math.abs(distanceY));\n\t\tconst clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));\n\t\tconst PADDING = clamp(realDistance * 0.5, 60, 300);\n\t\tlet startControlX = startX;\n\t\tlet startControlY = startY;\n\t\tlet endControlX = endX;\n\t\tlet endControlY = endY;\n\t\tswitch (fromSide) {\n\t\t\tcase 'top':\n\t\t\t\tstartControlY = startY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tstartControlY = startY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tstartControlX = startX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tstartControlX = startX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (toSide) {\n\t\t\tcase 'top':\n\t\t\t\tendControlY = endY - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'bottom':\n\t\t\t\tendControlY = endY + PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'left':\n\t\t\t\tendControlX = endX - PADDING;\n\t\t\t\tbreak;\n\t\t\tcase 'right':\n\t\t\t\tendControlX = endX + PADDING;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn [startControlX, startControlY, endControlX, endControlY];\n\t};\n\n\tprivate drawCurvedPath = (\n\t\tstartX: number,\n\t\tstartY: number,\n\t\tendX: number,\n\t\tendY: number,\n\t\tc1x: number,\n\t\tc1y: number,\n\t\tc2x: number,\n\t\tc2y: number,\n\t) => {\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 = '#ccc';\n\t\tthis.ctx.lineWidth = 2;\n\t\tthis.ctx.stroke();\n\t};\n\n\tprivate drawArrowhead = (tipX: number, tipY: number, fromX: number, fromY: number) => {\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 = '#ccc';\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\tdispose = () => {\n\t\tif (this.zoomInOptimize.timeout) {\n\t\t\tclearTimeout(this.zoomInOptimize.timeout);\n\t\t\tthis.zoomInOptimize.timeout = null;\n\t\t}\n\t\tthis.canvas.remove();\n\t\tthis._canvas = null;\n\t};\n}\n","import { unexpectedError } from '@/shared';\n\nexport default {\n\tround,\n\tresizeCanvasForDPR,\n\tapplyStyles,\n\tdrawRoundRect,\n\tgetAnchorCoord,\n\tgetColor,\n};\n\nfunction applyStyles(container: HTMLElement | ShadowRoot, styleString: string) {\n\tconst style = document.createElement('style');\n\tstyle.innerHTML = styleString;\n\tcontainer.appendChild(style);\n}\n\nfunction drawRoundRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n) {\n\tctx.beginPath();\n\tctx.moveTo(x + radius, y);\n\tctx.lineTo(x + width - radius, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\tctx.lineTo(x + width, y + height - radius);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\tctx.lineTo(x + radius, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\tctx.lineTo(x, y + radius);\n\tctx.quadraticCurveTo(x, y, x + radius, y);\n\tctx.closePath();\n}\n\nfunction getAnchorCoord(node: JSONCanvasNode, side: 'top' | 'bottom' | 'left' | 'right') {\n\tconst midX = node.x + node.width / 2;\n\tconst midY = node.y + node.height / 2;\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn [midX, node.y];\n\t\tcase 'bottom':\n\t\t\treturn [midX, node.y + node.height];\n\t\tcase 'left':\n\t\t\treturn [node.x, midY];\n\t\tcase 'right':\n\t\t\treturn [node.x + node.width, midY];\n\t\tdefault:\n\t\t\treturn [midX, midY];\n\t}\n}\n\nfunction getColor(colorIndex: string = '0') {\n\tlet themeColor = null;\n\n\tfunction hexToRgb(hex: string) {\n\t\tconst cleanHex = hex.replace('#', '');\n\t\tconst r = parseInt(cleanHex.substring(0, 2), 16);\n\t\tconst g = parseInt(cleanHex.substring(2, 4), 16);\n\t\tconst b = parseInt(cleanHex.substring(4, 6), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (colorIndex.length === 1) {\n\t\tswitch (colorIndex) {\n\t\t\tcase '1':\n\t\t\t\tthemeColor = 'rgba(255, 120, 129, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '2':\n\t\t\t\tthemeColor = 'rgba(251, 187, 131, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '3':\n\t\t\t\tthemeColor = 'rgba(255, 232, 139, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '4':\n\t\t\t\tthemeColor = 'rgba(124, 211, 124, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '5':\n\t\t\t\tthemeColor = 'rgba(134, 223, 226, ?)';\n\t\t\t\tbreak;\n\t\t\tcase '6':\n\t\t\t\tthemeColor = 'rgba(203, 158, 255, ?)';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthemeColor = 'rgba(140, 140, 140, ?)';\n\t\t}\n\t} else {\n\t\tconst rgb = hexToRgb(colorIndex);\n\t\tthemeColor = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ?)`;\n\t}\n\treturn {\n\t\tborder: themeColor.replace('?', '0.75'),\n\t\tbackground: themeColor.replace('?', '0.1'),\n\t\tactive: themeColor.replace('?', '1'),\n\t};\n}\n\nfunction resizeCanvasForDPR(canvas: HTMLCanvasElement, width: number, height: number) {\n\tconst dpr = window.devicePixelRatio || 1;\n\tconst ctx = canvas.getContext('2d');\n\tif (!ctx) throw unexpectedError;\n\tcanvas.width = Math.round(width * dpr);\n\tcanvas.height = Math.round(height * dpr);\n\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\tctx.scale(dpr, dpr);\n}\n\nfunction round(roundedNum: number, digits: number) {\n\tconst factor = 10 ** digits;\n\treturn Math.round(roundedNum * factor) / factor;\n}\n","import { Container } from '@needle-di/core';\nimport type { GeneralModuleCtor } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport type { ModuleInput, Options } from '@/declarations';\nimport InteractionHandler from '@/interactionHandler';\nimport OverlayManager from '@/overlayManager';\nimport Renderer from '@/renderer';\nimport utilities from '@/utilities';\n\ntype InternalModules = [\n\ttypeof DataManager,\n\ttypeof Controller,\n\ttypeof OverlayManager,\n\ttypeof InteractionHandler,\n\ttypeof Renderer,\n];\n\nexport class JSONCanvasViewer<M extends ModuleInput = []> {\n\tprivate options: Options<[...InternalModules, ...M]>;\n\tprivate allModules: ModuleInput;\n\tcontainer: Container;\n\n\tconstructor(options: Options<[...InternalModules, ...M]>, modules?: M) {\n\t\tthis.container = new Container();\n\t\tthis.options = options;\n\t\tconst bind = (Class: GeneralModuleCtor) => {\n\t\t\tthis.container.bind({\n\t\t\t\tprovide: Class,\n\t\t\t\tuseFactory: () => new Class(this.container, this.options, utilities),\n\t\t\t});\n\t\t};\n\t\tthis.allModules = [\n\t\t\tDataManager,\n\t\t\tController,\n\t\t\tOverlayManager,\n\t\t\tInteractionHandler,\n\t\t\tRenderer,\n\t\t\t...(modules || []),\n\t\t];\n\n\t\tthis.allModules.forEach(bind);\n\t\tthis.allModules.forEach(Module => {\n\t\t\tthis.container.get(Module);\n\t\t});\n\t\tthis.container.get(DataManager).loadCanvas();\n\t}\n\n\tdispose = () => {\n\t\tconst container = this.options.container;\n\t\twhile (container.firstChild) container.firstChild.remove();\n\t\tthis.allModules.reverse();\n\t\tthis.allModules.forEach(Module => {\n\t\t\tconst module = this.container.get(Module);\n\t\t\tif (module.dispose) module.dispose();\n\t\t});\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport { destroyError } from '@/shared';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tcontrolsCollapsed?: boolean;\n};\n\nexport default class Controls extends BaseModule<Options> {\n\tprivate _controlsPanel: HTMLDivElement | null = null;\n\tprivate _toggleCollapseBtn: HTMLButtonElement | null = null;\n\tprivate _toggleFullscreenBtn: HTMLButtonElement | null = null;\n\tprivate _zoomOutBtn: HTMLButtonElement | null = null;\n\tprivate _zoomSlider: HTMLInputElement | null = null;\n\tprivate _zoomInBtn: HTMLButtonElement | null = null;\n\tprivate _resetViewBtn: HTMLButtonElement | null = null;\n\tprivate DM: DataManager;\n\tprivate collapsed: boolean;\n\n\tprivate get controlsPanel() {\n\t\tif (this._controlsPanel === null) throw destroyError;\n\t\treturn this._controlsPanel;\n\t}\n\tprivate get toggleCollapseBtn() {\n\t\tif (this._toggleCollapseBtn === null) throw destroyError;\n\t\treturn this._toggleCollapseBtn;\n\t}\n\tprivate get toggleFullscreenBtn() {\n\t\tif (this._toggleFullscreenBtn === null) throw destroyError;\n\t\treturn this._toggleFullscreenBtn;\n\t}\n\tprivate get zoomOutBtn() {\n\t\tif (this._zoomOutBtn === null) throw destroyError;\n\t\treturn this._zoomOutBtn;\n\t}\n\tprivate get zoomSlider() {\n\t\tif (this._zoomSlider === null) throw destroyError;\n\t\treturn this._zoomSlider;\n\t}\n\tprivate get zoomInBtn() {\n\t\tif (this._zoomInBtn === null) throw destroyError;\n\t\treturn this._zoomInBtn;\n\t}\n\tprivate get resetViewBtn() {\n\t\tif (this._resetViewBtn === null) throw destroyError;\n\t\treturn this._resetViewBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.controlsCollapsed || false;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onToggleFullscreen.subscribe(this.updateFullscreenBtn);\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.updateSlider);\n\n\t\tthis._controlsPanel = document.createElement('div');\n\t\tthis._controlsPanel.className = 'controls';\n\t\tthis._controlsPanel.classList.toggle('collapsed', this.collapsed);\n\n\t\tthis.utilities.applyStyles(this._controlsPanel, style);\n\n\t\tthis._toggleCollapseBtn = document.createElement('button');\n\t\tthis._toggleCollapseBtn.className = 'collapse-button';\n\t\tthis._toggleCollapseBtn.innerHTML =\n\t\t\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\t\tthis._controlsPanel.appendChild(this._toggleCollapseBtn);\n\n\t\tconst controlsContent = document.createElement('div');\n\t\tcontrolsContent.className = 'controls-content';\n\n\t\tthis._toggleFullscreenBtn = document.createElement('button');\n\t\tthis._toggleFullscreenBtn.innerHTML = `<svg viewBox=\"-5.28 -5.28 34.56 34.56\" fill=\"none\"><path d=\"M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15\" stroke-width=\"2.4\" stroke-linecap=\"round\"/></svg>`;\n\t\tcontrolsContent.appendChild(this._toggleFullscreenBtn);\n\n\t\tthis._zoomOutBtn = document.createElement('button');\n\t\tthis._zoomOutBtn.innerHTML =\n\t\t\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\n\t\tcontrolsContent.appendChild(this._zoomOutBtn);\n\n\t\tthis._zoomSlider = document.createElement('input');\n\t\tthis._zoomSlider.type = 'range';\n\t\tthis._zoomSlider.className = 'zoom-slider';\n\t\tthis._zoomSlider.min = '-30';\n\t\tthis._zoomSlider.max = '30';\n\t\tthis._zoomSlider.value = '0';\n\t\tcontrolsContent.appendChild(this._zoomSlider);\n\n\t\tthis._zoomInBtn = document.createElement('button');\n\t\tthis._zoomInBtn.innerHTML =\n\t\t\t'<svg viewBox=\"-1.2 -1.2 26.4 26.4\"><path d=\"M6 12h12m-6-6v12\" stroke-width=\"2\" stroke-linecap=\"round\" /></svg>';\n\t\tcontrolsContent.appendChild(this._zoomInBtn);\n\n\t\tthis._resetViewBtn = document.createElement('button');\n\t\tthis._resetViewBtn.innerHTML =\n\t\t\t'<svg viewBox=\"-6 -6 30 30\" stroke-width=\".08\"><path d=\"m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813Z\" /></svg>';\n\t\tcontrolsContent.appendChild(this._resetViewBtn);\n\n\t\tthis._controlsPanel.appendChild(controlsContent);\n\n\t\tthis.DM.data.container.appendChild(this._controlsPanel);\n\n\t\tthis._toggleCollapseBtn.addEventListener('click', this.toggleCollapse);\n\t\tthis._zoomInBtn.addEventListener('click', this.zoomIn);\n\t\tthis._zoomOutBtn.addEventListener('click', this.zoomOut);\n\t\tthis._zoomSlider.addEventListener('input', this.slide);\n\t\tthis._resetViewBtn.addEventListener('click', this.DM.resetView);\n\t\tthis._toggleFullscreenBtn.addEventListener('click', this.toggleFullscreen);\n\t}\n\ttoggleCollapse = () => this.controlsPanel.classList.toggle('collapsed');\n\tprivate zoomIn = () => this.DM.zoom(1.1, this.DM.middleViewer());\n\tprivate zoomOut = () => this.DM.zoom(1 / 1.1, this.DM.middleViewer());\n\tprivate slide = () => this.DM.zoomToScale(1.1 ** Number(this.zoomSlider.value), this.DM.middleViewer());\n\n\tprivate updateFullscreenBtn = (enter: boolean) => {\n\t\tif (enter)\n\t\t\tthis.toggleFullscreenBtn.innerHTML = `<svg viewBox=\"-5.28 -5.28 34.56 34.56\" fill=\"none\"><path d=\"M4 9V5.6c0-.56 0-.84.109-1.054a1 1 0 0 1 .437-.437C4.76 4 5.04 4 5.6 4H9M4 15v3.4c0 .56 0 .84.109 1.054a1 1 0 0 0 .437.437C4.76 20 5.04 20 5.6 20H9m6-16h3.4c.56 0 .84 0 1.054.109a1 1 0 0 1 .437.437C20 4.76 20 5.04 20 5.6V9m0 6v3.4c0 .56 0 .84-.109 1.054a1 1 0 0 1-.437.437C19.24 20 18.96 20 18.4 20H15\" stroke-width=\"2.4\" stroke-linecap=\"round\"/></svg>`;\n\t\telse\n\t\t\tthis.toggleFullscreenBtn.innerHTML = `<svg viewBox=\"-40.32 -40.32 176.64 176.64\"><path d=\"M30 60H6a6 6 0 0 0 0 12h18v18a6 6 0 0 0 12 0V66a5.997 5.997 0 0 0-6-6Zm60 0H66a5.997 5.997 0 0 0-6 6v24a6 6 0 0 0 12 0V72h18a6 6 0 0 0 0-12ZM66 36h24a6 6 0 0 0 0-12H72V6a6 6 0 0 0-12 0v24a5.997 5.997 0 0 0 6 6ZM30 0a5.997 5.997 0 0 0-6 6v18H6a6 6 0 0 0 0 12h24a5.997 5.997 0 0 0 6-6V6a5.997 5.997 0 0 0-6-6Z\"/></svg>`;\n\t};\n\tprivate toggleFullscreen = () => this.DM.shiftFullscreen('toggle');\n\n\tprivate updateSlider = () => {\n\t\tthis.zoomSlider.value = String(this.scaleToSlider(this.DM.data.scale));\n\t};\n\tprivate scaleToSlider = (scale: number) => Math.log(scale) / Math.log(1.1);\n\n\tdispose = () => {\n\t\tthis.toggleCollapseBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.zoomInBtn.removeEventListener('click', this.zoomIn);\n\t\tthis.zoomOutBtn.removeEventListener('click', this.zoomOut);\n\t\tthis.zoomSlider.removeEventListener('input', this.slide);\n\t\tthis.resetViewBtn.removeEventListener('click', this.DM.resetView);\n\t\tthis.toggleFullscreenBtn.removeEventListener('click', this.toggleFullscreen);\n\t\tthis.controlsPanel.remove();\n\t\tthis._controlsPanel = null;\n\t\tthis._toggleCollapseBtn = null;\n\t\tthis._zoomInBtn = null;\n\t\tthis._zoomOutBtn = null;\n\t\tthis._zoomSlider = null;\n\t\tthis._resetViewBtn = null;\n\t\tthis._toggleFullscreenBtn = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport { destroyError } from '@/shared';\nimport style from './styles.scss?inline';\n\nexport default class DebugPanel extends BaseModule {\n\tprivate _debugPanel: HTMLDivElement | null = null;\n\tprivate DM: DataManager;\n\n\tprivate get debugPanel() {\n\t\tif (!this._debugPanel) throw destroyError;\n\t\treturn this._debugPanel;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.update);\n\t\tthis._debugPanel = document.createElement('div');\n\t\tthis._debugPanel.className = 'debug-panel';\n\t\tconst HTMLContainer = this.DM.data.container;\n\t\tthis.utilities.applyStyles(HTMLContainer, style);\n\t\tHTMLContainer.appendChild(this._debugPanel);\n\t}\n\n\tprivate update = () => {\n\t\tconst round = this.utilities.round;\n\t\tconst data = this.DM.data;\n\t\tthis.debugPanel.innerHTML = `<p>Scale: ${round(data.scale, 3)}</p><p>Offset: ${round(data.offsetX, 1)}, ${round(data.offsetY, 1)}</p>`;\n\t};\n\n\tdispose = () => {\n\t\tthis.debugPanel.remove();\n\t\tthis._debugPanel = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport { destroyError } from '@/shared';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tminimapCollapsed?: boolean;\n};\n\nexport default class Minimap extends BaseModule<Options> {\n\tprivate _minimapCtx: CanvasRenderingContext2D | null = null;\n\tprivate _viewportRectangle: HTMLDivElement | null = null;\n\tprivate _minimap: HTMLDivElement | null = null;\n\tprivate _minimapContainer: HTMLDivElement | null = null;\n\tprivate _toggleMinimapBtn: HTMLButtonElement | null = null;\n\tprivate minimapCache: { scale: number; centerX: number; centerY: number } = {\n\t\tscale: 1,\n\t\tcenterX: 0,\n\t\tcenterY: 0,\n\t};\n\tprivate DM: DataManager;\n\tprivate collapsed: boolean;\n\n\tprivate get minimap() {\n\t\tif (this._minimap === null) throw destroyError;\n\t\treturn this._minimap;\n\t}\n\tprivate get minimapCtx() {\n\t\tif (this._minimapCtx === null) throw destroyError;\n\t\treturn this._minimapCtx;\n\t}\n\tprivate get viewportRectangle() {\n\t\tif (this._viewportRectangle === null) throw destroyError;\n\t\treturn this._viewportRectangle;\n\t}\n\tprivate get minimapContainer() {\n\t\tif (this._minimapContainer === null) throw destroyError;\n\t\treturn this._minimapContainer;\n\t}\n\tprivate get toggleMinimapBtn() {\n\t\tif (this._toggleMinimapBtn === null) throw destroyError;\n\t\treturn this._toggleMinimapBtn;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tthis.collapsed = this.options.minimapCollapsed || false;\n\t\tthis.container.get(Controller).hooks.onRefresh.subscribe(this.updateViewportRectangle);\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis.DM.hooks.onCanvasFetched.subscribe(this.drawMinimap);\n\n\t\tthis._minimapContainer = document.createElement('div');\n\t\tthis._minimapContainer.className = 'minimap-container';\n\n\t\tthis.utilities.applyStyles(this._minimapContainer, style);\n\n\t\tthis._toggleMinimapBtn = document.createElement('button');\n\t\tthis._toggleMinimapBtn.className = 'toggle-minimap collapse-button';\n\t\tthis._toggleMinimapBtn.innerHTML =\n\t\t\t'<svg viewBox=\"-3.6 -3.6 31.2 31.2\" stroke-width=\".4\"><path d=\"M15.707 4.293a1 1 0 0 1 0 1.414L9.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414l-7-7a1 1 0 0 1 0-1.414l7-7a1 1 0 0 1 1.414 0Z\" /></svg>';\n\t\tthis._minimapContainer.appendChild(this._toggleMinimapBtn);\n\n\t\tthis._minimap = document.createElement('div');\n\t\tthis._minimap.className = 'minimap';\n\t\tconst minimapCanvas = document.createElement('canvas');\n\t\tminimapCanvas.className = 'minimap-canvas';\n\t\tminimapCanvas.width = 200;\n\t\tminimapCanvas.height = 150;\n\n\t\tthis._minimap.appendChild(minimapCanvas);\n\t\tthis._minimapCtx = minimapCanvas.getContext('2d') as CanvasRenderingContext2D;\n\t\tthis._viewportRectangle = document.createElement('div');\n\t\tthis._viewportRectangle.className = 'viewport-rectangle';\n\t\tthis._minimap.appendChild(this._viewportRectangle);\n\t\tthis._minimapContainer.appendChild(this._minimap);\n\n\t\tthis.DM.data.container.appendChild(this._minimapContainer);\n\n\t\tthis._minimapContainer.classList.toggle('collapsed', this.collapsed);\n\n\t\tthis._toggleMinimapBtn.addEventListener('click', this.toggleCollapse);\n\t\tthis.utilities.resizeCanvasForDPR(minimapCanvas, minimapCanvas.width, minimapCanvas.height);\n\t}\n\n\ttoggleCollapse = () => {\n\t\tthis.collapsed = !this.collapsed;\n\t\tthis.minimapContainer.classList.toggle('collapsed', this.collapsed);\n\t\tif (!this.collapsed) this.updateViewportRectangle();\n\t};\n\n\tprivate drawMinimap = () => {\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tif (!bounds) return;\n\t\tconst displayWidth = this.minimap.clientWidth;\n\t\tconst displayHeight = this.minimap.clientHeight;\n\t\tconst scaleX = displayWidth / bounds.width;\n\t\tconst scaleY = displayHeight / bounds.height;\n\t\tthis.minimapCache.scale = Math.min(scaleX, scaleY) * 0.9;\n\t\tthis.minimapCache.centerX = displayWidth / 2;\n\t\tthis.minimapCache.centerY = displayHeight / 2;\n\t\tthis.minimapCtx.clearRect(0, 0, displayWidth, displayHeight);\n\t\tthis.minimapCtx.save();\n\t\tthis.minimapCtx.translate(this.minimapCache.centerX, this.minimapCache.centerY);\n\t\tthis.minimapCtx.scale(this.minimapCache.scale, this.minimapCache.scale);\n\t\tthis.minimapCtx.translate(-bounds.centerX, -bounds.centerY);\n\t\tconst canvasData = this.DM.data.canvasData;\n\t\tfor (const edge of canvasData.edges) this.drawMinimapEdge(edge);\n\t\tfor (const node of canvasData.nodes) this.drawMinimapNode(node);\n\t\tthis.minimapCtx.restore();\n\t};\n\n\tprivate drawMinimapNode = (node: JSONCanvasNode) => {\n\t\tconst colors = this.utilities.getColor(node.color);\n\t\tconst radius = 25;\n\t\tthis.minimapCtx.fillStyle = colors.border;\n\t\tthis.minimapCtx.globalAlpha = 0.3;\n\t\tthis.utilities.drawRoundRect(this.minimapCtx, node.x, node.y, node.width, node.height, radius);\n\t\tthis.minimapCtx.fill();\n\t\tthis.minimapCtx.globalAlpha = 1.0;\n\t};\n\n\tprivate drawMinimapEdge = (edge: JSONCanvasEdge) => {\n\t\tconst nodeMap = this.DM.data.nodeMap;\n\t\tconst fromNode = nodeMap[edge.fromNode];\n\t\tconst toNode = nodeMap[edge.toNode];\n\t\tif (!fromNode || !toNode) return;\n\t\tconst [startX, startY] = this.utilities.getAnchorCoord(fromNode, edge.fromSide);\n\t\tconst [endX, endY] = this.utilities.getAnchorCoord(toNode, edge.toSide);\n\t\tthis.minimapCtx.beginPath();\n\t\tthis.minimapCtx.moveTo(startX, startY);\n\t\tthis.minimapCtx.lineTo(endX, endY);\n\t\tthis.minimapCtx.strokeStyle = '#555';\n\t\tthis.minimapCtx.lineWidth = 10;\n\t\tthis.minimapCtx.stroke();\n\t};\n\n\tprivate updateViewportRectangle = () => {\n\t\tif (this.collapsed) return;\n\t\tconst bounds = this.DM.data.nodeBounds;\n\t\tconst container = this.DM.data.container;\n\t\tconst scale = this.DM.data.scale;\n\t\tif (!bounds) return;\n\t\tconst viewWidth = container.clientWidth / scale;\n\t\tconst viewHeight = container.clientHeight / scale;\n\t\tconst viewportCenterX = -this.DM.data.offsetX / scale + container.clientWidth / (2 * scale);\n\t\tconst viewportCenterY = -this.DM.data.offsetY / scale + container.clientHeight / (2 * scale);\n\t\tconst viewRectX =\n\t\t\tthis.minimapCache.centerX +\n\t\t\t(viewportCenterX - viewWidth / 2 - bounds.centerX) * this.minimapCache.scale;\n\t\tconst viewRectY =\n\t\t\tthis.minimapCache.centerY +\n\t\t\t(viewportCenterY - viewHeight / 2 - bounds.centerY) * this.minimapCache.scale;\n\t\tconst viewRectWidth = viewWidth * this.minimapCache.scale;\n\t\tconst viewRectHeight = viewHeight * this.minimapCache.scale;\n\t\tthis.viewportRectangle.style.left = `${viewRectX}px`;\n\t\tthis.viewportRectangle.style.top = `${viewRectY}px`;\n\t\tthis.viewportRectangle.style.width = `${viewRectWidth}px`;\n\t\tthis.viewportRectangle.style.height = `${viewRectHeight}px`;\n\t};\n\n\tdispose = () => {\n\t\tthis.toggleMinimapBtn.removeEventListener('click', this.toggleCollapse);\n\t\tthis.minimapCtx.clearRect(0, 0, this.minimap.clientWidth, this.minimap.clientHeight);\n\t\tthis.minimapContainer.remove();\n\t\tthis._minimapContainer = null;\n\t\tthis._toggleMinimapBtn = null;\n\t\tthis._viewportRectangle = null;\n\t\tthis._minimap = null;\n\t};\n}\n","import { type BaseArgs, BaseModule } from '@/baseModule';\nimport DataManager from '@/dataManager';\nimport { destroyError } from '@/shared';\nimport style from './styles.scss?inline';\n\ntype Options = {\n\tmistouchPreventer?: {\n\t\tpreventAtStart?: boolean;\n\t\tlabelText?: string;\n\t};\n};\n\nexport default class MistouchPreventer extends BaseModule<Options> {\n\tprivate _preventionContainer: HTMLDivElement | null = null;\n\tprivate preventMt: boolean = false;\n\tprivate DM: DataManager;\n\tprivate preventMistouch: {\n\t\trecord: boolean;\n\t\tlastX: number;\n\t\tlastY: number;\n\t\tinitialX: number;\n\t\tinitialY: number;\n\t} = {\n\t\trecord: false,\n\t\tlastX: 0,\n\t\tlastY: 0,\n\t\tinitialX: 0,\n\t\tinitialY: 0,\n\t};\n\n\tprivate get preventionContainer() {\n\t\tif (this._preventionContainer === null) throw destroyError;\n\t\treturn this._preventionContainer;\n\t}\n\n\tconstructor(...args: BaseArgs) {\n\t\tsuper(...args);\n\t\tconst options = Object.assign(\n\t\t\t{\n\t\t\t\tpreventAtStart: true,\n\t\t\t\tlabelText: 'Click on to unlock.',\n\t\t\t},\n\t\t\tthis.options.mistouchPreventer || {},\n\t\t);\n\n\t\tconst preventionBanner = document.createElement('div');\n\t\tpreventionBanner.className = 'prevention-banner';\n\t\tpreventionBanner.textContent = options.labelText;\n\t\tthis.DM = this.container.get(DataManager);\n\t\tthis._preventionContainer = document.createElement('div');\n\t\tthis._preventionContainer.className = 'prevention-container hidden';\n\n\t\tthis.utilities.applyStyles(this._preventionContainer, style);\n\t\tthis._preventionContainer.appendChild(preventionBanner);\n\t\tthis.DM.data.container.appendChild(this._preventionContainer);\n\n\t\tif (options.preventAtStart) this.startPrevention();\n\n\t\twindow.addEventListener('pointerdown', this.onPointerDown);\n\t\twindow.addEventListener('pointermove', this.onPointerMove);\n\t\twindow.addEventListener('pointerup', this.onPointerUp);\n\t}\n\n\tprivate onPointerDown = (e: PointerEvent) => {\n\t\tconst bounds = this.DM.data.container.getBoundingClientRect();\n\t\tif (\n\t\t\te.clientX < bounds.left ||\n\t\t\te.clientX > bounds.right ||\n\t\t\te.clientY < bounds.top ||\n\t\t\te.clientY > bounds.bottom\n\t\t) {\n\t\t\tif (!this.preventMt) this.startPrevention();\n\t\t} else if (this.preventMt) {\n\t\t\tthis.preventMistouch.initialX = e.clientX;\n\t\t\tthis.preventMistouch.initialY = e.clientY;\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t\tthis.preventMistouch.record = true;\n\t\t}\n\t};\n\n\tprivate onPointerMove = (e: PointerEvent) => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.lastX = e.clientX;\n\t\t\tthis.preventMistouch.lastY = e.clientY;\n\t\t}\n\t};\n\n\tprivate onPointerUp = () => {\n\t\tif (this.preventMistouch.record) {\n\t\t\tthis.preventMistouch.record = false;\n\t\t\tif (\n\t\t\t\tMath.abs(this.preventMistouch.lastX - this.preventMistouch.initialX) +\n\t\t\t\t\tMath.abs(this.preventMistouch.lastY - this.preventMistouch.initialY) <\n\t\t\t\t5\n\t\t\t)\n\t\t\t\tthis.endPrevention();\n\t\t}\n\t};\n\n\tstartPrevention = () => {\n\t\tthis.preventionContainer.classList.remove('hidden');\n\t\tthis.DM.data.container.classList.add('numb');\n\t\tthis.preventMt = true;\n\t};\n\n\tendPrevention = () => {\n\t\tthis.preventMt = false;\n\t\tthis.preventionContainer.classList.add('hidden');\n\t\tsetTimeout(() => this.DM.data.container.classList.remove('numb'), 50); // minimum delay to prevent triggering undesired button touch\n\t};\n\n\tdispose = () => {\n\t\twindow.removeEventListener('pointerdown', this.onPointerDown);\n\t\twindow.removeEventListener('pointermove', this.onPointerMove);\n\t\twindow.removeEventListener('pointerup', this.onPointerUp);\n\t\tthis.preventionContainer.remove();\n\t\tthis._preventionContainer = null;\n\t};\n}\n","export { type BaseArgs, BaseModule } from '@/baseModule';\nexport { JSONCanvasViewer } from '@/canvasViewer';\nexport { default as Controls } from '@/controls';\nexport { default as DebugPanel } from '@/debugPanel';\nexport { default as Minimap } from '@/minimap';\nexport { default as MistouchPreventer } from '@/mistouchPreventer';\n\nimport Controller from '@/controller';\nimport DataManager from '@/dataManager';\nimport InteractionHandler from '@/interactionHandler';\nimport OverlayManager from '@/overlayManager';\nimport Renderer from '@/renderer';\nexport const developerSuite = {\n\tController,\n\tDataManager,\n\tInteractionHandler,\n\tRenderer,\n\tOverlayManager,\n};\n"],"names":["BaseModule","constructor","container","options","utilities","this","Object","assign","dispose","isClassLike","target","getParentClasses","parentClasses","currentClass","getPrototypeOf","name","parentClass","push","assertPresent","value","Error","assertSingle","array","errorProvider","length","first","at","isConstructorProvider","provider","isClassProvider","isFactoryProvider","isAsyncProvider","async","isExistingProvider","isMultiProvider","multi","InjectionToken","description","toString","String","isClassToken","token","getToken","Guards.isConstructorProvider","provide","injectableSymbol","Factory","underConstruction","construct","Guards.isAsyncProvider","AsyncProvidersInSyncInjectionContextError","includes","dependencyGraph","map","CircularDependencyError","doConstruct","pop","constructAsync","useFactory","Guards.isClassProvider","create","useClass","errorClass","block","onError","error","retryOn","getAsync","optional","Guards.isValueProvider","useValue","Guards.isFactoryProvider","Guards.isExistingProvider","get","useExisting","assertNever","super","graph","join","InjectionContext","run","originalContext","_currentContext","runAsync","NeedsInjectionContextError","injectionContext","Container","providers","Map","singletons","parent","factory","bind","bindAll","forEach","it","has","Guards.isMultiProvider","existingProviderAlreadyProvided","some","every","set","step","result","_","i","slice","windowedSlice","childClass","parentProvider","existingParentProviders","unbind","delete","unbindAll","clear","lazy","autoBindIfNeeded","values","flatMap","Promise","resolve","promiseTry","all","flat","createChild","hasOwnProperty","targetClasses","getInjectableTargets","filter","targetClass","isInjectionToken","existingToken","unexpectedError","destroyError","makeHook","args","subs","callback","Set","subscribe","add","unsubscribe","GRID_CELL_SIZE","DataManager","spatialGrid","hooks","onToggleFullscreen","onCanvasFetched","data","canvasData","nodeMap","canvasBaseDir","nodeBounds","offsetX","offsetY","scale","document","createElement","loadCanvas","path","canvasPath","resolvePath","fetch","then","res","json","nodes","node","type","file","split","id","calculateNodeBounds","buildSpatialGrid","err","console","test","substring","lastIndexOf","lastSlash","findNodeAt","screenCoords","x","y","C2W","C2C","candidates","key","Math","floor","width","height","judgeInteract","match","minX","Infinity","minY","maxX","maxY","min","max","centerX","centerY","minCol","maxCol","minRow","maxRow","col","row","zoom","factor","origin","newScale","zoomToScale","validNewScale","canvasCoords","pan","panToCoords","shiftFullscreen","option","fullscreenElement","exitFullscreen","requestFullscreen","resetView","bounds","contentWidth","INITIAL_VIEWPORT_PADDING","contentHeight","viewWidth","clientWidth","viewHeight","clientHeight","scaleX","scaleY","round","initialView","containerX","containerY","canvasX","canvasY","middleViewer","remove","Controller","animationId","resizeAnimationId","DM","perFrame","lastScale","lastOffsets","lastResizeCenter","onResize","onRefresh","onFetched","parentContainer","firstElementChild","innerHTML","realContainer","noShadow","attachShadow","mode","applyStyles","HTMLContainer","classList","appendChild","resizeObserver","observe","requestAnimationFrame","draw","refresh","center","ResizeObserver","cancelAnimationFrame","disconnect","OverlayManager","_overlaysLayer","overlays","selectedId","eventListeners","IH","parser","markdown","micromark","extensions","gfm","htmlExtensions","gfmHtml","overlaysLayer","onInteractionStart","onInteractionEnd","InteractionHandler","controller","updateOverlays","className","onClick","select","cbd","overlayCreators","text","updateOrCreateOverlay","loadMarkdownForNode","link","url","group","previous","current","mdContent","response","frontmatterMatch","frontmatter","reduce","acc","line","s","trim","Purify","sanitize","mdFrontmatter","style","transform","content","element","constructOverlay","left","top","display","parsedContentContainer","getElementsByClassName","contains","direction","color","getColor","overlay","backgroundColor","background","setProperty","active","parsedContentWrapper","iframe","src","sandbox","loading","audio","controls","img","clickLayer","overlayBorder","borderColor","border","onStart","onEnd","addEventListener","child","removeEventListener","pointeract","OM","proControlSchema","zoomFactor","lockControlSchema","interactions","Pointeract","Click","Drag","WheelPanZoom","PreventDefault","MultitouchPanZoom","startInteraction","start","stopInteraction","stop","on","onPan","onZoom","onTrueClick","event","detail","e","closest","off","FONT_COLOR","Renderer","_canvas","ctx","zoomInOptimize","lastDrawnScale","lastDrawnViewport","right","bottom","timeout","lastCallTime","canvas","redraw","optimizeDPR","getContext","resizeCanvasForDPR","offsetWidth","offsetHeight","clearTimeout","now","Date","currentViewport","getCurrentViewport","isViewportInside","setTimeout","trueRedraw","fakeRedraw","clearRect","save","translate","drawGroup","drawFileNode","edges","edge","drawEdge","restore","cssScale","currentOffsetX","currentOffsetY","inner","outer","drawLabelBar","label","barHeight","radius","yOffset","fontSize","xPadding","font","barWidth","measureText","fillStyle","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","fill","fillText","drawNodeBackground","colors","globalAlpha","drawRoundRect","strokeStyle","lineWidth","stroke","fromNode","toNode","getEdgeNodes","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","abs","PADDING","val","c1x","c1y","c2x","c2y","bezierCurveTo","tipX","tipY","fromX","fromY","dx","dy","sqrt","unitX","unitY","leftX","leftY","rightX","rightY","roundedNum","digits","dpr","window","devicePixelRatio","setTransform","styleString","side","midX","midY","colorIndex","themeColor","rgb","hex","cleanHex","replace","r","parseInt","g","b","hexToRgb","JSONCanvasViewer","allModules","modules","Class","Module","firstChild","reverse","module","Controls","_controlsPanel","_toggleCollapseBtn","_toggleFullscreenBtn","_zoomOutBtn","_zoomSlider","_zoomInBtn","_resetViewBtn","collapsed","controlsPanel","toggleCollapseBtn","toggleFullscreenBtn","zoomOutBtn","zoomSlider","zoomInBtn","resetViewBtn","controlsCollapsed","updateFullscreenBtn","updateSlider","toggle","controlsContent","toggleCollapse","zoomIn","zoomOut","slide","toggleFullscreen","Number","enter","scaleToSlider","log","DebugPanel","_debugPanel","debugPanel","update","Minimap","_minimapCtx","_viewportRectangle","_minimap","_minimapContainer","_toggleMinimapBtn","minimapCache","minimap","minimapCtx","viewportRectangle","minimapContainer","toggleMinimapBtn","minimapCollapsed","updateViewportRectangle","drawMinimap","minimapCanvas","displayWidth","displayHeight","drawMinimapEdge","drawMinimapNode","viewportCenterX","viewportCenterY","viewRectX","viewRectY","viewRectWidth","viewRectHeight","MistouchPreventer","_preventionContainer","preventMt","preventMistouch","record","lastX","lastY","initialX","initialY","preventionContainer","preventAtStart","labelText","mistouchPreventer","preventionBanner","textContent","startPrevention","onPointerDown","onPointerMove","onPointerUp","getBoundingClientRect","clientX","clientY","endPrevention","developerSuite"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7]}
@@ -0,0 +1,12 @@
1
+ import type { Container } from '@needle-di/core';
2
+ import type { DefaultOptions, Empty, GeneralFunction, GeneralObject, Utilities } from './declarations';
3
+ export type BaseArgs = [Container, GeneralObject, Utilities];
4
+ export type GeneralModuleCtor = typeof BaseModule<GeneralObject>;
5
+ export type GeneralModule = InstanceType<GeneralModuleCtor>;
6
+ export declare class BaseModule<O extends GeneralObject = Empty> {
7
+ protected container: Container;
8
+ protected utilities: Utilities;
9
+ constructor(container: Container, options: GeneralObject, utilities: Utilities);
10
+ options: DefaultOptions & O;
11
+ dispose?: GeneralFunction;
12
+ }
@@ -1,15 +1,22 @@
1
- export default class canvasViewer {
2
- private animationId;
3
- private resizeAnimationId;
4
- private resizeObserver;
5
- private perFrame;
6
- private lastResizeCenter;
7
- private data;
8
- private registry;
9
- constructor(container: HTMLElement, userRegistry?: registry);
10
- private draw;
11
- private refresh;
12
- private onResize;
13
- loadCanvas(path: string): Promise<void>;
14
- dispose(): void;
1
+ import { Container } from '@needle-di/core';
2
+ import Controller from './controller';
3
+ import DataManager from './dataManager';
4
+ import type { ModuleInput, Options } from './declarations';
5
+ import InteractionHandler from './interactionHandler';
6
+ import OverlayManager from './overlayManager';
7
+ import Renderer from './renderer';
8
+ type InternalModules = [
9
+ typeof DataManager,
10
+ typeof Controller,
11
+ typeof OverlayManager,
12
+ typeof InteractionHandler,
13
+ typeof Renderer
14
+ ];
15
+ export declare class JSONCanvasViewer<M extends ModuleInput = []> {
16
+ private options;
17
+ private allModules;
18
+ container: Container;
19
+ constructor(options: Options<[...InternalModules, ...M]>, modules?: M);
20
+ dispose: () => void;
15
21
  }
22
+ export {};
@@ -0,0 +1,33 @@
1
+ import { type BaseArgs, BaseModule } from './baseModule';
2
+ type Options = {
3
+ noShadow?: boolean;
4
+ };
5
+ export default class Controller extends BaseModule<Options> {
6
+ private animationId;
7
+ private resizeAnimationId;
8
+ private DM;
9
+ private perFrame;
10
+ private lastResizeCenter;
11
+ hooks: {
12
+ onResize: {
13
+ (args_0: number, args_1: number): void;
14
+ subs: Set<(args_0: number, args_1: number) => unknown>;
15
+ subscribe(callback: (args_0: number, args_1: number) => unknown): void;
16
+ unsubscribe(callback: (args_0: number, args_1: number) => unknown): void;
17
+ };
18
+ onRefresh: {
19
+ (): void;
20
+ subs: Set<() => unknown>;
21
+ subscribe(callback: () => unknown): void;
22
+ unsubscribe(callback: () => unknown): void;
23
+ };
24
+ };
25
+ constructor(...args: BaseArgs);
26
+ private onFetched;
27
+ private draw;
28
+ private refresh;
29
+ private onResize;
30
+ private resizeObserver;
31
+ dispose: () => void;
32
+ }
33
+ export {};
@@ -1,4 +1,8 @@
1
- export default class controls {
1
+ import { type BaseArgs, BaseModule } from '../baseModule';
2
+ type Options = {
3
+ controlsCollapsed?: boolean;
4
+ };
5
+ export default class Controls extends BaseModule<Options> {
2
6
  private _controlsPanel;
3
7
  private _toggleCollapseBtn;
4
8
  private _toggleFullscreenBtn;
@@ -6,7 +10,8 @@ export default class controls {
6
10
  private _zoomSlider;
7
11
  private _zoomInBtn;
8
12
  private _resetViewBtn;
9
- private registry;
13
+ private DM;
14
+ private collapsed;
10
15
  private get controlsPanel();
11
16
  private get toggleCollapseBtn();
12
17
  private get toggleFullscreenBtn();
@@ -14,13 +19,15 @@ export default class controls {
14
19
  private get zoomSlider();
15
20
  private get zoomInBtn();
16
21
  private get resetViewBtn();
17
- constructor(data: runtimeData, registry: registry);
18
- private toggleCollapse;
22
+ constructor(...args: BaseArgs);
23
+ toggleCollapse: () => boolean;
19
24
  private zoomIn;
20
25
  private zoomOut;
21
26
  private slide;
22
27
  private updateFullscreenBtn;
28
+ private toggleFullscreen;
23
29
  private updateSlider;
24
30
  private scaleToSlider;
25
- private dispose;
31
+ dispose: () => void;
26
32
  }
33
+ export {};
@@ -1,30 +1,50 @@
1
- export default class dataManager {
2
- data: runtimeData;
3
- registry: registry;
4
- spatialGrid: Record<string, Array<JSONCanvasNode>> | null;
5
- acceleration: {
6
- pan: {
7
- x: number;
8
- y: number;
1
+ import type { Coordinates, NodeBounds } from './declarations';
2
+ import { BaseModule } from './baseModule';
3
+ export default class DataManager extends BaseModule {
4
+ private spatialGrid;
5
+ hooks: {
6
+ onToggleFullscreen: {
7
+ (args_0: boolean): void;
8
+ subs: Set<(args_0: boolean) => unknown>;
9
+ subscribe(callback: (args_0: boolean) => unknown): void;
10
+ unsubscribe(callback: (args_0: boolean) => unknown): void;
9
11
  };
10
- zoom: number;
12
+ onCanvasFetched: {
13
+ (): void;
14
+ subs: Set<() => unknown>;
15
+ subscribe(callback: () => unknown): void;
16
+ unsubscribe(callback: () => unknown): void;
17
+ };
18
+ };
19
+ data: {
20
+ canvasData: JSONCanvas;
21
+ nodeMap: Record<string, JSONCanvasNode>;
22
+ canvasBaseDir: string;
23
+ nodeBounds: NodeBounds;
24
+ offsetX: number;
25
+ offsetY: number;
26
+ scale: number;
27
+ container: HTMLDivElement;
11
28
  };
12
- animationId: number | null;
13
- constructor(data: runtimeData, registry: registry);
14
- loadCanvas: (path: string) => Promise<void>;
15
- private findNodeAtMousePosition;
29
+ loadCanvas: () => Promise<void>;
30
+ private resolvePath;
31
+ findNodeAt: (screenCoords: Coordinates) => JSONCanvasNode | null;
16
32
  private judgeInteract;
17
33
  private calculateNodeBounds;
18
34
  private buildSpatialGrid;
19
- private zoom;
20
- private zoomToScale;
21
- private pan;
22
- private panToCoords;
23
- private shiftFullscreen;
24
- private resetView;
35
+ zoom: (factor: number, origin: Coordinates) => void;
36
+ zoomToScale: (newScale: number, origin: Coordinates) => void;
37
+ pan: ({ x, y }: Coordinates) => void;
38
+ panToCoords: ({ x, y }: Coordinates) => void;
39
+ shiftFullscreen: (option?: string) => void;
40
+ resetView: () => void;
25
41
  private C2C;
26
42
  private C2W;
27
- private middleViewer;
28
- private animator;
29
- private dispose;
43
+ middleViewer: () => {
44
+ x: number;
45
+ y: number;
46
+ width: number;
47
+ height: number;
48
+ };
49
+ dispose: () => void;
30
50
  }
@@ -0,0 +1,9 @@
1
+ import { type BaseArgs, BaseModule } from '../baseModule';
2
+ export default class DebugPanel extends BaseModule {
3
+ private _debugPanel;
4
+ private DM;
5
+ private get debugPanel();
6
+ constructor(...args: BaseArgs);
7
+ private update;
8
+ dispose: () => void;
9
+ }
@@ -0,0 +1,79 @@
1
+ import type { GeneralModuleCtor } from './baseModule';
2
+ import type utilities from './utilities';
3
+ declare global {
4
+ interface JSONCanvasNode {
5
+ id: string;
6
+ type: 'group' | 'file' | 'text' | 'link';
7
+ x: number;
8
+ y: number;
9
+ width: number;
10
+ height: number;
11
+ label?: string;
12
+ background?: string;
13
+ backgroundStyle?: 'cover' | 'ratio' | 'repeat';
14
+ styleAttributes?: Record<string, string>;
15
+ color?: string;
16
+ text?: string;
17
+ file?: string;
18
+ subpath?: string;
19
+ url?: string;
20
+ }
21
+ interface JSONCanvasEdge {
22
+ id: string;
23
+ fromNode: string;
24
+ toNode: string;
25
+ fromSide: 'right' | 'left' | 'top' | 'bottom';
26
+ toSide: 'right' | 'left' | 'top' | 'bottom';
27
+ toEnd?: 'arrow' | 'none';
28
+ label?: string;
29
+ styleAttributes?: Record<string, string>;
30
+ color?: string;
31
+ }
32
+ interface JSONCanvas {
33
+ nodes: Array<JSONCanvasNode>;
34
+ edges: Array<JSONCanvasEdge>;
35
+ metadata: {
36
+ version: string;
37
+ frontmatter: Record<string, string>;
38
+ };
39
+ }
40
+ }
41
+ export type Coordinates = {
42
+ x: number;
43
+ y: number;
44
+ };
45
+ export type RuntimeData = {
46
+ offsetX: number;
47
+ offsetY: number;
48
+ scale: number;
49
+ canvasData: JSONCanvas;
50
+ nodeMap: Record<string, JSONCanvasNode>;
51
+ canvasBaseDir: string;
52
+ nodeBounds: NodeBounds;
53
+ container: HTMLDivElement;
54
+ };
55
+ export type NodeBounds = {
56
+ minX: number;
57
+ minY: number;
58
+ maxX: number;
59
+ maxY: number;
60
+ width: number;
61
+ height: number;
62
+ centerX: number;
63
+ centerY: number;
64
+ };
65
+ export type GeneralArguments = Array<any>;
66
+ export type GeneralObject = Record<Indexable, any>;
67
+ export type GeneralFunction = (...args: GeneralArguments) => any;
68
+ export type Empty = {};
69
+ type Indexable = string | number | symbol;
70
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
71
+ type AllModuleInstances<T extends ModuleInput> = InstanceType<T[number]>;
72
+ export type DefaultOptions = {
73
+ container: HTMLElement;
74
+ canvasPath: string;
75
+ };
76
+ export type Utilities = typeof utilities;
77
+ export type ModuleInput = Array<GeneralModuleCtor>;
78
+ export type Options<T extends ModuleInput> = Omit<UnionToIntersection<AllModuleInstances<T>['options']>, keyof DefaultOptions> & DefaultOptions;
79
+ export {};