velo-plot 3.0.0 → 4.0.0-alpha.1

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 (191) hide show
  1. package/README.md +22 -15
  2. package/dist/ChartCore-KYG2HTcK.js +7474 -0
  3. package/dist/ChartCore-KYG2HTcK.js.map +1 -0
  4. package/dist/GpuChartRenderer-Dxc0hrQA.js +75 -0
  5. package/dist/GpuChartRenderer-Dxc0hrQA.js.map +1 -0
  6. package/dist/{index.core-BmZe2jRQ.js → PluginRegistry-CDf_jcnp.js} +19 -33
  7. package/dist/PluginRegistry-CDf_jcnp.js.map +1 -0
  8. package/dist/SVGDocumentBuilder-C-uLkcFW.js +83 -0
  9. package/dist/SVGDocumentBuilder-C-uLkcFW.js.map +1 -0
  10. package/dist/angular-hooks.js +1 -1
  11. package/dist/angular.js +8 -8
  12. package/dist/{axisFormat-CzumxpCL.js → axisFormat-Sz4WIJfQ.js} +2 -2
  13. package/dist/{axisFormat-CzumxpCL.js.map → axisFormat-Sz4WIJfQ.js.map} +1 -1
  14. package/dist/{chartSyncBridge-DbWrwtyP.js → chartSyncBridge-C1uRy0ZS.js} +12 -11
  15. package/dist/{chartSyncBridge-DbWrwtyP.js.map → chartSyncBridge-C1uRy0ZS.js.map} +1 -1
  16. package/dist/core/ChartStatistics.d.ts +1 -1
  17. package/dist/core/chart/ChartCore.d.ts +19 -20
  18. package/dist/core/chart/ChartFeatureHooks.d.ts +7 -0
  19. package/dist/core/chart/ChartRenderLoop.d.ts +5 -0
  20. package/dist/core/chart/ChartRenderer.d.ts +9 -0
  21. package/dist/core/chart/ChartSetup.d.ts +1 -0
  22. package/dist/core/chart/chartExportPatch.d.ts +2 -0
  23. package/dist/core/chart/exporter/SVGExporter.d.ts +9 -7
  24. package/dist/core/chart/exporter/svg/SVGDocumentBuilder.d.ts +27 -0
  25. package/dist/core/chart/exporter/svg/SVGExportContext.d.ts +147 -0
  26. package/dist/core/chart/exporter/svg/SVGOrchestrator.d.ts +3 -0
  27. package/dist/core/chart/exporter/svg/SVGThemeAdapter.d.ts +22 -0
  28. package/dist/core/chart/exporter/svg/__tests__/testFixtures.d.ts +46 -0
  29. package/dist/core/chart/exporter/svg/__tests__/visualTestUtils.d.ts +12 -0
  30. package/dist/core/chart/exporter/svg/overlay/axes.d.ts +4 -0
  31. package/dist/core/chart/exporter/svg/overlay/border.d.ts +4 -0
  32. package/dist/core/chart/exporter/svg/overlay/errorBars.d.ts +7 -0
  33. package/dist/core/chart/exporter/svg/overlay/grid.d.ts +4 -0
  34. package/dist/core/chart/exporter/svg/overlay/index.d.ts +12 -0
  35. package/dist/core/chart/exporter/svg/overlay/legend.d.ts +4 -0
  36. package/dist/core/chart/exporter/svg/overlay/pluginCharts.d.ts +6 -0
  37. package/dist/core/chart/exporter/svg/overlay/polarGrid.d.ts +4 -0
  38. package/dist/core/chart/exporter/svg/overlay/specialChart.d.ts +15 -0
  39. package/dist/core/chart/exporter/svg/overlay/title.d.ts +4 -0
  40. package/dist/core/chart/exporter/svg/plugins/annotations.d.ts +5 -0
  41. package/dist/core/chart/exporter/svg/plugins/brokenAxis.d.ts +20 -0
  42. package/dist/core/chart/exporter/svg/plugins/latex.d.ts +9 -0
  43. package/dist/core/chart/exporter/svg/plugins/register.d.ts +8 -0
  44. package/dist/core/chart/exporter/svg/plugins/regression.d.ts +33 -0
  45. package/dist/core/chart/exporter/svg/plugins/roi.d.ts +12 -0
  46. package/dist/core/chart/exporter/svg/plugins/tradeMarkers.d.ts +3 -0
  47. package/dist/core/chart/exporter/svg/plugins/types.d.ts +28 -0
  48. package/dist/core/chart/exporter/svg/plugins/watermark.d.ts +13 -0
  49. package/dist/core/chart/exporter/svg/series/band.d.ts +6 -0
  50. package/dist/core/chart/exporter/svg/series/bar.d.ts +6 -0
  51. package/dist/core/chart/exporter/svg/series/boxplot.d.ts +6 -0
  52. package/dist/core/chart/exporter/svg/series/candlestick.d.ts +6 -0
  53. package/dist/core/chart/exporter/svg/series/finitePoints.d.ts +6 -0
  54. package/dist/core/chart/exporter/svg/series/gauge.d.ts +5 -0
  55. package/dist/core/chart/exporter/svg/series/heatmap.d.ts +6 -0
  56. package/dist/core/chart/exporter/svg/series/indicator.d.ts +6 -0
  57. package/dist/core/chart/exporter/svg/series/line.d.ts +12 -0
  58. package/dist/core/chart/exporter/svg/series/polar.d.ts +6 -0
  59. package/dist/core/chart/exporter/svg/series/radar.d.ts +5 -0
  60. package/dist/core/chart/exporter/svg/series/registry.d.ts +10 -0
  61. package/dist/core/chart/exporter/svg/series/sankey.d.ts +5 -0
  62. package/dist/core/chart/exporter/svg/series/scatter.d.ts +1 -0
  63. package/dist/core/chart/exporter/svg/series/ternary.d.ts +7 -0
  64. package/dist/core/chart/exporter/svg/series/waterfall.d.ts +6 -0
  65. package/dist/core/chart/exporter/svg/seriesAtTimestamp.d.ts +4 -0
  66. package/dist/core/chart/exporter/svg/seriesUtils.d.ts +3 -0
  67. package/dist/core/chart/exporter/svg/symbols.d.ts +5 -0
  68. package/dist/core/chart/exporter/svg/tickUtils.d.ts +9 -0
  69. package/dist/core/chart/mountSVGString.d.ts +5 -0
  70. package/dist/core/chart/overlaySeriesRegistry.d.ts +7 -0
  71. package/dist/core/chart/series/SeriesActions.d.ts +1 -0
  72. package/dist/core/chart/series/SeriesBufferLite.d.ts +13 -0
  73. package/dist/core/chart/series/seriesOptionsRegistry.d.ts +8 -0
  74. package/dist/core/chart/series/seriesTypeRegistry.d.ts +5 -0
  75. package/dist/core/chart/types.d.ts +2 -2
  76. package/dist/core/stacked/StackSVGComposer.d.ts +14 -0
  77. package/dist/core/stacked/index.d.ts +3 -2
  78. package/dist/core/stacked/types.d.ts +12 -4
  79. package/dist/createStackedChart-DjA3aJAu.js +2761 -0
  80. package/dist/createStackedChart-DjA3aJAu.js.map +1 -0
  81. package/dist/{hooks-CYPCxoZx.js → hooks-4wQH27r9.js} +7 -7
  82. package/dist/{hooks-CYPCxoZx.js.map → hooks-4wQH27r9.js.map} +1 -1
  83. package/dist/{index-qunX30Xu.js → index-B7PTX94B.js} +2133 -2133
  84. package/dist/index-B7PTX94B.js.map +1 -0
  85. package/dist/{index-BMiZoKmm.js → index-BgrvqltV.js} +67 -67
  86. package/dist/index-BgrvqltV.js.map +1 -0
  87. package/dist/index-Bj-xyXY6.js +582 -0
  88. package/dist/index-Bj-xyXY6.js.map +1 -0
  89. package/dist/index-qhscKTDy.js.map +1 -1
  90. package/dist/index.core.d.ts +8 -6
  91. package/dist/index.d.ts +1 -14
  92. package/dist/plugins/3d.js +3 -1
  93. package/dist/plugins/3d.js.map +1 -1
  94. package/dist/plugins/PluginManager.d.ts +5 -0
  95. package/dist/plugins/analysis.js.map +1 -1
  96. package/dist/plugins/annotations.js +8 -7
  97. package/dist/plugins/annotations.js.map +1 -1
  98. package/dist/plugins/broken-axis.js +198 -152
  99. package/dist/plugins/broken-axis.js.map +1 -1
  100. package/dist/plugins/createPlugin.d.ts +8 -0
  101. package/dist/plugins/debug.js +32 -32
  102. package/dist/plugins/debug.js.map +1 -1
  103. package/dist/plugins/forecasting.js +273 -258
  104. package/dist/plugins/forecasting.js.map +1 -1
  105. package/dist/plugins/gpu.js +2033 -209
  106. package/dist/plugins/gpu.js.map +1 -1
  107. package/dist/plugins/i18n.js +286 -23
  108. package/dist/plugins/i18n.js.map +1 -1
  109. package/dist/plugins/latex.js +766 -207
  110. package/dist/plugins/latex.js.map +1 -1
  111. package/dist/plugins/loading/index.d.ts +1 -2
  112. package/dist/plugins/loading.js +3 -4
  113. package/dist/plugins/ml-integration.js +107 -93
  114. package/dist/plugins/ml-integration.js.map +1 -1
  115. package/dist/plugins/offscreen.js +11 -10
  116. package/dist/plugins/offscreen.js.map +1 -1
  117. package/dist/plugins/radar/types.d.ts +11 -0
  118. package/dist/plugins/radar.js +64 -53
  119. package/dist/plugins/radar.js.map +1 -1
  120. package/dist/plugins/regression.js +254 -256
  121. package/dist/plugins/regression.js.map +1 -1
  122. package/dist/plugins/roi/index.d.ts +2 -0
  123. package/dist/plugins/roi.js +184 -145
  124. package/dist/plugins/roi.js.map +1 -1
  125. package/dist/plugins/snapshot.js +20 -15
  126. package/dist/plugins/snapshot.js.map +1 -1
  127. package/dist/plugins/streaming.js +1 -1
  128. package/dist/plugins/tools.js +1 -1
  129. package/dist/plugins/types.d.ts +4 -0
  130. package/dist/react.js +55 -58
  131. package/dist/react.js.map +1 -1
  132. package/dist/regression-HNdyk1Dm.js +28 -0
  133. package/dist/regression-HNdyk1Dm.js.map +1 -0
  134. package/dist/renderer/ChartSeriesRenderer.d.ts +3 -2
  135. package/dist/renderer/NativeWebGLRenderer.d.ts +2 -1
  136. package/dist/renderer/SVGChartRenderer.d.ts +15 -0
  137. package/dist/renderer/SankeyRenderer.d.ts +1 -0
  138. package/dist/renderer/native/NativeWebGLRenderer.d.ts +5 -1
  139. package/dist/renderer/native/draw.d.ts +2 -47
  140. package/dist/renderer/native/drawCore.d.ts +27 -0
  141. package/dist/renderer/native/drawExtended.d.ts +29 -0
  142. package/dist/renderer/native/frameRenderExtended.d.ts +1 -0
  143. package/dist/renderer/native/frameRenderRegistry.d.ts +27 -0
  144. package/dist/renderer/native/programFactoryCore.d.ts +6 -0
  145. package/dist/renderer/native/programFactoryExtended.d.ts +4 -0
  146. package/dist/renderer/native/utils.d.ts +3 -29
  147. package/dist/renderer/native/utilsCore.d.ts +14 -0
  148. package/dist/renderer/native/utilsExtended.d.ts +17 -0
  149. package/dist/renderer/overlaySeriesExtended.d.ts +1 -0
  150. package/dist/renderer/registerExtendedSeries.d.ts +1 -0
  151. package/dist/renderer/registerSVG.d.ts +5 -0
  152. package/dist/renderer/registerWebGPU.d.ts +2 -0
  153. package/dist/renderer/sankeyLayout.d.ts +29 -0
  154. package/dist/renderer/seriesBufferExtended.d.ts +4 -0
  155. package/dist/scientific/index.d.ts +1 -5
  156. package/dist/scientific/registerScientific.d.ts +1 -0
  157. package/dist/scientific.js +41 -41
  158. package/dist/solid.js +56 -59
  159. package/dist/solid.js.map +1 -1
  160. package/dist/svelte.js +26 -29
  161. package/dist/svelte.js.map +1 -1
  162. package/dist/tickUtils-B_X-ha13.js +41 -0
  163. package/dist/tickUtils-B_X-ha13.js.map +1 -0
  164. package/dist/trading/index.d.ts +1 -4
  165. package/dist/trading/registerTrading.d.ts +3 -0
  166. package/dist/trading.js +42 -42
  167. package/dist/types.d.ts +5 -4
  168. package/dist/velo-plot.full.js +1951 -1275
  169. package/dist/velo-plot.full.js.map +1 -1
  170. package/dist/velo-plot.js +33 -28
  171. package/dist/velo-plot.js.map +1 -1
  172. package/dist/vue/VeloPlot.vue.d.ts +1 -1
  173. package/dist/vue/index.d.ts +33 -33
  174. package/dist/vue.js +17 -20
  175. package/dist/vue.js.map +1 -1
  176. package/package.json +14 -1
  177. package/dist/ChartCore-BpzRvN4Y.js +0 -8467
  178. package/dist/ChartCore-BpzRvN4Y.js.map +0 -1
  179. package/dist/createStackedChart-Dm-YqUT7.js +0 -756
  180. package/dist/createStackedChart-Dm-YqUT7.js.map +0 -1
  181. package/dist/gpuRenderer-BpaMYz-k.js +0 -1848
  182. package/dist/gpuRenderer-BpaMYz-k.js.map +0 -1
  183. package/dist/index-BMiZoKmm.js.map +0 -1
  184. package/dist/index-qunX30Xu.js.map +0 -1
  185. package/dist/index-x4stH3jD.js +0 -282
  186. package/dist/index-x4stH3jD.js.map +0 -1
  187. package/dist/index.core-BmZe2jRQ.js.map +0 -1
  188. package/dist/mockDatafeed-DHIDPcpX.js +0 -515
  189. package/dist/mockDatafeed-DHIDPcpX.js.map +0 -1
  190. package/dist/symbols-DT0eLlpW.js +0 -568
  191. package/dist/symbols-DT0eLlpW.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"offscreen.js","sources":["../../src/plugins/offscreen/pool.ts","../../src/plugins/offscreen/index.ts"],"sourcesContent":["/**\n * @fileoverview Worker Pool Manager for Offscreen Rendering\n * @module plugins/offscreen/pool\n */\n\nexport interface WorkerTask {\n id: string;\n priority: number;\n timestamp: number;\n resolve: (value: ImageBitmap) => void;\n reject: (error: Error) => void;\n}\n\nexport class WorkerPool {\n private workers: Worker[] = [];\n private availableWorkers: Set<number> = new Set();\n private taskQueue: WorkerTask[] = [];\n private activeJobs: Map<string, number> = new Map(); // taskId => workerIndex\n\n constructor(private size: number) {\n this.initialize();\n }\n\n private initialize(): void {\n const workerCode = `\n // Simple offscreen worker\n self.onmessage = (e) => {\n const { type, width, height, dpr } = e.data;\n \n if (type === 'render') {\n // Echo back - actual rendering logic would go here\n self.postMessage({ type: 'response', taskId: e.data.taskId });\n }\n };\n `;\n\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n\n for (let i = 0; i < this.size; i++) {\n try {\n const worker = new Worker(workerUrl);\n worker.onmessage = (e) => this.handleWorkerMessage(i, e);\n worker.onerror = (e) => this.handleWorkerError(i, e);\n this.workers.push(worker);\n this.availableWorkers.add(i);\n } catch (error) {\n console.error(`Failed to create worker ${i}:`, error);\n }\n }\n\n URL.revokeObjectURL(workerUrl);\n }\n\n private handleWorkerMessage(workerIndex: number, event: MessageEvent): void {\n const { type, taskId, imageData, error } = event.data;\n\n if (type === 'response') {\n const task = this.findTask(taskId);\n if (task) {\n if (error) {\n task.reject(new Error(error));\n } else if (imageData) {\n task.resolve(imageData);\n }\n this.activeJobs.delete(taskId);\n this.availableWorkers.add(workerIndex);\n this.processQueue();\n }\n }\n }\n\n private handleWorkerError(workerIndex: number, error: ErrorEvent): void {\n console.error(`Worker ${workerIndex} error:`, error);\n // Find and reject any active task for this worker\n for (const [taskId, wIndex] of this.activeJobs.entries()) {\n if (wIndex === workerIndex) {\n const task = this.findTask(taskId);\n if (task) {\n task.reject(new Error(`Worker error: ${error.message}`));\n this.activeJobs.delete(taskId);\n }\n }\n }\n this.availableWorkers.add(workerIndex);\n this.processQueue();\n }\n\n private findTask(taskId: string): WorkerTask | undefined {\n return this.taskQueue.find(t => t.id === taskId);\n }\n\n private processQueue(): void {\n while (this.availableWorkers.size > 0 && this.taskQueue.length > 0) {\n // Sort by priority and timestamp\n this.taskQueue.sort((a, b) => {\n if (a.priority !== b.priority) return b.priority - a.priority;\n return a.timestamp - b.timestamp;\n });\n\n const task = this.taskQueue.shift();\n if (!task) break;\n\n const workerIndex = Array.from(this.availableWorkers)[0];\n this.availableWorkers.delete(workerIndex);\n this.activeJobs.set(task.id, workerIndex);\n\n // Send task to worker\n this.workers[workerIndex].postMessage({\n type: 'render',\n taskId: task.id,\n });\n }\n }\n\n public submit(priority: number = 0): Promise<ImageBitmap> {\n return new Promise((resolve, reject) => {\n const task: WorkerTask = {\n id: Math.random().toString(36).substring(7),\n priority,\n timestamp: Date.now(),\n resolve,\n reject,\n };\n\n this.taskQueue.push(task);\n this.processQueue();\n });\n }\n\n public getStats() {\n return {\n total: this.workers.length,\n active: this.activeJobs.size,\n idle: this.availableWorkers.size,\n queued: this.taskQueue.length,\n };\n }\n\n public destroy(): void {\n for (const worker of this.workers) {\n worker.terminate();\n }\n this.workers = [];\n this.availableWorkers.clear();\n this.taskQueue = [];\n this.activeJobs.clear();\n }\n}\n","/**\n * @fileoverview Offscreen rendering plugin (skeleton with stats + feature detection)\n * @module plugins/offscreen\n */\n\nimport type {\n PluginOffscreenConfig,\n OffscreenAPI,\n OffscreenStats,\n} from \"./types\";\nimport type { ChartPlugin, PluginContext, PluginManifest } from \"../types\";\n\nconst manifest: PluginManifest = {\n name: \"velo-plot-offscreen\",\n version: \"1.0.0\",\n description: \"Offscreen rendering support with worker-ready scaffolding\",\n provides: [\"performance\", \"offscreen\"],\n tags: [\"performance\", \"offscreen\", \"worker\"],\n};\n\nconst DEFAULT_CONFIG: Required<PluginOffscreenConfig> = {\n enabled: false,\n mode: \"auto\",\n workerPool: 1,\n transfer: \"offscreen\",\n fallback: \"main-thread\",\n debug: false,\n};\n\nimport { WorkerPool } from \"./pool\";\n\nexport function PluginOffscreen(\n userConfig: Partial<PluginOffscreenConfig> = {}\n): ChartPlugin<PluginOffscreenConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n let pool: WorkerPool | null = null;\n let stats: OffscreenStats = {\n enabled: config.enabled,\n frames: 0,\n lastFrameTime: 0,\n lastFrameTimestamp: 0,\n };\n\n function log(message: string, ...args: unknown[]) {\n if (config.debug && ctx) {\n ctx.log.info(`[Offscreen] ${message}`, ...args);\n }\n }\n\n function isSupported(): boolean {\n return typeof (globalThis as any).OffscreenCanvas !== \"undefined\";\n }\n\n function enable(): void {\n if (!isSupported()) {\n log(\"OffscreenCanvas not supported. Falling back to main thread.\");\n if (config.fallback === \"disable\") {\n stats.enabled = false;\n return;\n }\n }\n \n if (!pool) {\n pool = new WorkerPool(config.workerPool || 1);\n }\n \n stats.enabled = true;\n config.enabled = true;\n }\n\n function disable(): void {\n if (pool) {\n pool.destroy();\n pool = null;\n }\n stats.enabled = false;\n config.enabled = false;\n }\n\n function updateConfig(newConfig: Partial<PluginOffscreenConfig>): void {\n Object.assign(config, newConfig);\n if (config.enabled) enable();\n else disable();\n stats.enabled = !!config.enabled;\n }\n\n function getStats(): OffscreenStats {\n const poolStats = pool?.getStats();\n return { \n ...stats,\n activeWorkers: poolStats?.active || 0,\n queuedTasks: poolStats?.queued || 0\n } as any;\n }\n\n function flush(): void {\n ctx?.requestRender();\n }\n\n const api: OffscreenAPI & Record<string, unknown> = {\n enable,\n disable,\n isEnabled: () => stats.enabled,\n updateConfig,\n getStats,\n flush,\n };\n\n return {\n manifest,\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n (ctx.chart as any).offscreen = api;\n if (config.enabled) enable();\n log(`Initialized (pool=${config.workerPool})`);\n },\n onDestroy(pluginCtx: PluginContext) {\n disable();\n delete (pluginCtx.chart as any).offscreen;\n ctx = null;\n },\n onAfterRender(_ctx, event) {\n stats.frames += 1;\n stats.lastFrameTime = event.renderTime;\n stats.lastFrameTimestamp = event.timestamp;\n \n if (config.enabled && pool) {\n // In a real implementation, we would offload the next render piece here\n // For now, we just track that we could have used the pool\n }\n },\n api,\n };\n}\n\nexport default PluginOffscreen;\n\n// Type exports\nexport type {\n PluginOffscreenConfig,\n OffscreenAPI,\n OffscreenStats,\n OffscreenMode,\n OffscreenTransferMode,\n OffscreenFallbackMode,\n} from \"./types\";\n"],"names":["WorkerPool","size","__publicField","workerCode","blob","workerUrl","i","worker","e","error","workerIndex","event","type","taskId","imageData","task","wIndex","t","a","b","priority","resolve","reject","manifest","DEFAULT_CONFIG","PluginOffscreen","userConfig","config","ctx","pool","stats","log","message","args","isSupported","enable","disable","updateConfig","newConfig","getStats","poolStats","flush","api","pluginCtx","_ctx"],"mappings":"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"}
1
+ {"version":3,"file":"offscreen.js","sources":["../../src/plugins/offscreen/pool.ts","../../src/plugins/offscreen/index.ts"],"sourcesContent":["/**\n * @fileoverview Worker Pool Manager for Offscreen Rendering\n * @module plugins/offscreen/pool\n */\n\nexport interface WorkerTask {\n id: string;\n priority: number;\n timestamp: number;\n resolve: (value: ImageBitmap) => void;\n reject: (error: Error) => void;\n}\n\nexport class WorkerPool {\n private workers: Worker[] = [];\n private availableWorkers: Set<number> = new Set();\n private taskQueue: WorkerTask[] = [];\n private activeJobs: Map<string, number> = new Map(); // taskId => workerIndex\n\n constructor(private size: number) {\n this.initialize();\n }\n\n private initialize(): void {\n const workerCode = `\n // Simple offscreen worker\n self.onmessage = (e) => {\n const { type, width, height, dpr } = e.data;\n \n if (type === 'render') {\n // Echo back - actual rendering logic would go here\n self.postMessage({ type: 'response', taskId: e.data.taskId });\n }\n };\n `;\n\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n\n for (let i = 0; i < this.size; i++) {\n try {\n const worker = new Worker(workerUrl);\n worker.onmessage = (e) => this.handleWorkerMessage(i, e);\n worker.onerror = (e) => this.handleWorkerError(i, e);\n this.workers.push(worker);\n this.availableWorkers.add(i);\n } catch (error) {\n console.error(`Failed to create worker ${i}:`, error);\n }\n }\n\n URL.revokeObjectURL(workerUrl);\n }\n\n private handleWorkerMessage(workerIndex: number, event: MessageEvent): void {\n const { type, taskId, imageData, error } = event.data;\n\n if (type === 'response') {\n const task = this.findTask(taskId);\n if (task) {\n if (error) {\n task.reject(new Error(error));\n } else if (imageData) {\n task.resolve(imageData);\n }\n this.activeJobs.delete(taskId);\n this.availableWorkers.add(workerIndex);\n this.processQueue();\n }\n }\n }\n\n private handleWorkerError(workerIndex: number, error: ErrorEvent): void {\n console.error(`Worker ${workerIndex} error:`, error);\n // Find and reject any active task for this worker\n for (const [taskId, wIndex] of this.activeJobs.entries()) {\n if (wIndex === workerIndex) {\n const task = this.findTask(taskId);\n if (task) {\n task.reject(new Error(`Worker error: ${error.message}`));\n this.activeJobs.delete(taskId);\n }\n }\n }\n this.availableWorkers.add(workerIndex);\n this.processQueue();\n }\n\n private findTask(taskId: string): WorkerTask | undefined {\n return this.taskQueue.find(t => t.id === taskId);\n }\n\n private processQueue(): void {\n while (this.availableWorkers.size > 0 && this.taskQueue.length > 0) {\n // Sort by priority and timestamp\n this.taskQueue.sort((a, b) => {\n if (a.priority !== b.priority) return b.priority - a.priority;\n return a.timestamp - b.timestamp;\n });\n\n const task = this.taskQueue.shift();\n if (!task) break;\n\n const workerIndex = Array.from(this.availableWorkers)[0];\n this.availableWorkers.delete(workerIndex);\n this.activeJobs.set(task.id, workerIndex);\n\n // Send task to worker\n this.workers[workerIndex].postMessage({\n type: 'render',\n taskId: task.id,\n });\n }\n }\n\n public submit(priority: number = 0): Promise<ImageBitmap> {\n return new Promise((resolve, reject) => {\n const task: WorkerTask = {\n id: Math.random().toString(36).substring(7),\n priority,\n timestamp: Date.now(),\n resolve,\n reject,\n };\n\n this.taskQueue.push(task);\n this.processQueue();\n });\n }\n\n public getStats() {\n return {\n total: this.workers.length,\n active: this.activeJobs.size,\n idle: this.availableWorkers.size,\n queued: this.taskQueue.length,\n };\n }\n\n public destroy(): void {\n for (const worker of this.workers) {\n worker.terminate();\n }\n this.workers = [];\n this.availableWorkers.clear();\n this.taskQueue = [];\n this.activeJobs.clear();\n }\n}\n","/**\n * @fileoverview Offscreen rendering plugin (skeleton with stats + feature detection)\n * @module plugins/offscreen\n */\n\nimport type {\n PluginOffscreenConfig,\n OffscreenAPI,\n OffscreenStats,\n} from \"./types\";\nimport type { ChartPlugin, PluginContext, PluginManifest } from \"../types\";\n\nconst manifest: PluginManifest = {\n name: \"velo-plot-offscreen\",\n version: \"1.0.0\",\n description: \"Offscreen rendering support with worker-ready scaffolding\",\n provides: [\"performance\", \"offscreen\"],\n tags: [\"performance\", \"offscreen\", \"worker\"],\n};\n\nconst DEFAULT_CONFIG: Required<PluginOffscreenConfig> = {\n enabled: false,\n mode: \"auto\",\n workerPool: 1,\n transfer: \"offscreen\",\n fallback: \"main-thread\",\n debug: false,\n};\n\nimport { WorkerPool } from \"./pool\";\n\nexport function PluginOffscreen(\n userConfig: Partial<PluginOffscreenConfig> = {}\n): ChartPlugin<PluginOffscreenConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n let pool: WorkerPool | null = null;\n const stats: OffscreenStats = {\n enabled: config.enabled,\n frames: 0,\n lastFrameTime: 0,\n lastFrameTimestamp: 0,\n };\n\n function log(message: string, ...args: unknown[]) {\n if (config.debug && ctx) {\n ctx.log.info(`[Offscreen] ${message}`, ...args);\n }\n }\n\n function isSupported(): boolean {\n return typeof (globalThis as any).OffscreenCanvas !== \"undefined\";\n }\n\n function enable(): void {\n if (!isSupported()) {\n log(\"OffscreenCanvas not supported. Falling back to main thread.\");\n if (config.fallback === \"disable\") {\n stats.enabled = false;\n return;\n }\n }\n \n if (!pool) {\n pool = new WorkerPool(config.workerPool || 1);\n }\n \n stats.enabled = true;\n config.enabled = true;\n }\n\n function disable(): void {\n if (pool) {\n pool.destroy();\n pool = null;\n }\n stats.enabled = false;\n config.enabled = false;\n }\n\n function updateConfig(newConfig: Partial<PluginOffscreenConfig>): void {\n Object.assign(config, newConfig);\n if (config.enabled) enable();\n else disable();\n stats.enabled = !!config.enabled;\n }\n\n function getStats(): OffscreenStats {\n const poolStats = pool?.getStats();\n return { \n ...stats,\n activeWorkers: poolStats?.active || 0,\n queuedTasks: poolStats?.queued || 0\n } as any;\n }\n\n function flush(): void {\n ctx?.requestRender();\n }\n\n const api: OffscreenAPI & Record<string, unknown> = {\n enable,\n disable,\n isEnabled: () => stats.enabled,\n updateConfig,\n getStats,\n flush,\n };\n\n return {\n manifest,\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n (ctx.chart as any).offscreen = api;\n if (config.enabled) enable();\n log(`Initialized (pool=${config.workerPool})`);\n },\n onDestroy(pluginCtx: PluginContext) {\n disable();\n delete (pluginCtx.chart as any).offscreen;\n ctx = null;\n },\n onAfterRender(_ctx, event) {\n stats.frames += 1;\n stats.lastFrameTime = event.renderTime;\n stats.lastFrameTimestamp = event.timestamp;\n \n if (config.enabled && pool) {\n // In a real implementation, we would offload the next render piece here\n // For now, we just track that we could have used the pool\n }\n },\n api,\n };\n}\n\nexport default PluginOffscreen;\n\n// Type exports\nexport type {\n PluginOffscreenConfig,\n OffscreenAPI,\n OffscreenStats,\n OffscreenMode,\n OffscreenTransferMode,\n OffscreenFallbackMode,\n} from \"./types\";\n"],"names":["WorkerPool","size","__publicField","workerCode","blob","workerUrl","i","worker","e","error","workerIndex","event","type","taskId","imageData","task","wIndex","t","a","b","priority","resolve","reject","manifest","DEFAULT_CONFIG","PluginOffscreen","userConfig","config","ctx","pool","stats","log","message","args","isSupported","enable","disable","updateConfig","newConfig","getStats","poolStats","flush","api","pluginCtx","_ctx"],"mappings":"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"}
@@ -31,10 +31,21 @@ export interface PluginRadarConfig {
31
31
  lineDash?: number[];
32
32
  };
33
33
  }
34
+ export interface RadarSVGExportData {
35
+ categories: string[];
36
+ maxValue: number;
37
+ gridLevels: number;
38
+ showLabels: boolean;
39
+ labelStyle?: PluginRadarConfig["labelStyle"];
40
+ gridStyle?: PluginRadarConfig["gridStyle"];
41
+ series: RadarSeriesData[];
42
+ }
34
43
  export interface RadarAPI {
35
44
  addSeries(data: RadarSeriesData): string;
36
45
  removeSeries(id: string): boolean;
37
46
  updateSeries(id: string, points: RadarPoint[]): boolean;
38
47
  setCategories(categories: string[]): void;
39
48
  setMaxValue(value: number): void;
49
+ /** Snapshot for SVG live renderer / export pipeline */
50
+ getSVGExportData(): RadarSVGExportData | null;
40
51
  }
@@ -1,10 +1,10 @@
1
- const D = {
1
+ const T = {
2
2
  name: "velo-plot-radar",
3
3
  version: "1.0.0",
4
4
  description: "Advanced Radar/Spider Charts for velo-plot",
5
5
  provides: ["radar", "spider-chart"],
6
6
  tags: ["radar", "visualization", "comparison"]
7
- }, k = {
7
+ }, V = {
8
8
  categories: [],
9
9
  maxValue: 100,
10
10
  minValue: 0,
@@ -21,83 +21,94 @@ const D = {
21
21
  lineDash: []
22
22
  }
23
23
  };
24
- function C(L = {}) {
25
- const i = { ...k, ...L };
26
- let a = null;
27
- const p = /* @__PURE__ */ new Map();
28
- function T(o) {
29
- var v, M, y, x, P, R;
30
- const { render: h } = o, { ctx2d: e, plotArea: d } = h;
24
+ function q(A = {}) {
25
+ const a = { ...V, ...A };
26
+ let r = null;
27
+ const f = /* @__PURE__ */ new Map();
28
+ function D(i) {
29
+ var b, M, y, x, P, R;
30
+ const { render: h } = i, { ctx2d: e, plotArea: d } = h;
31
31
  if (!e) return;
32
- const f = d.x + d.width / 2, g = d.y + d.height / 2, u = Math.min(d.width, d.height) / 2 * 0.8, S = i.categories.length;
33
- if (S === 0) return;
34
- const b = 2 * Math.PI / S;
35
- e.save(), e.strokeStyle = ((v = i.gridStyle) == null ? void 0 : v.color) || "rgba(255, 255, 255, 0.1)", e.lineWidth = ((M = i.gridStyle) == null ? void 0 : M.width) || 1, (y = i.gridStyle) != null && y.lineDash && i.gridStyle.lineDash.length > 0 && e.setLineDash(i.gridStyle.lineDash);
36
- for (let s = 1; s <= i.gridLevels; s++) {
37
- const r = s / i.gridLevels * u;
32
+ const g = d.x + d.width / 2, u = d.y + d.height / 2, S = Math.min(d.width, d.height) / 2 * 0.8, m = a.categories.length;
33
+ if (m === 0) return;
34
+ const v = 2 * Math.PI / m;
35
+ e.save(), e.strokeStyle = ((b = a.gridStyle) == null ? void 0 : b.color) || "rgba(255, 255, 255, 0.1)", e.lineWidth = ((M = a.gridStyle) == null ? void 0 : M.width) || 1, (y = a.gridStyle) != null && y.lineDash && a.gridStyle.lineDash.length > 0 && e.setLineDash(a.gridStyle.lineDash);
36
+ for (let n = 1; n <= a.gridLevels; n++) {
37
+ const s = n / a.gridLevels * S;
38
38
  e.beginPath();
39
- for (let t = 0; t < S; t++) {
40
- const l = t * b - Math.PI / 2, n = f + r * Math.cos(l), c = g + r * Math.sin(l);
41
- t === 0 ? e.moveTo(n, c) : e.lineTo(n, c);
39
+ for (let t = 0; t < m; t++) {
40
+ const l = t * v - Math.PI / 2, o = g + s * Math.cos(l), c = u + s * Math.sin(l);
41
+ t === 0 ? e.moveTo(o, c) : e.lineTo(o, c);
42
42
  }
43
43
  e.closePath(), e.stroke();
44
44
  }
45
45
  e.setLineDash([]);
46
- for (let s = 0; s < S; s++) {
47
- const r = s * b - Math.PI / 2, t = f + u * Math.cos(r), l = g + u * Math.sin(r);
48
- if (e.beginPath(), e.moveTo(f, g), e.lineTo(t, l), e.stroke(), i.showLabels) {
49
- const n = u + 25, c = f + n * Math.cos(r), m = g + n * Math.sin(r);
50
- e.fillStyle = ((x = i.labelStyle) == null ? void 0 : x.color) || "#94a3b8", e.font = `${((P = i.labelStyle) == null ? void 0 : P.fontSize) || 12}px ${((R = i.labelStyle) == null ? void 0 : R.fontFamily) || "sans-serif"}`, e.textAlign = Math.abs(Math.cos(r)) < 0.1 ? "center" : Math.cos(r) > 0 ? "left" : "right", e.textBaseline = Math.abs(Math.sin(r)) < 0.1 ? "middle" : Math.sin(r) > 0 ? "top" : "bottom", e.fillText(i.categories[s], c, m);
46
+ for (let n = 0; n < m; n++) {
47
+ const s = n * v - Math.PI / 2, t = g + S * Math.cos(s), l = u + S * Math.sin(s);
48
+ if (e.beginPath(), e.moveTo(g, u), e.lineTo(t, l), e.stroke(), a.showLabels) {
49
+ const o = S + 25, c = g + o * Math.cos(s), p = u + o * Math.sin(s);
50
+ e.fillStyle = ((x = a.labelStyle) == null ? void 0 : x.color) || "#94a3b8", e.font = `${((P = a.labelStyle) == null ? void 0 : P.fontSize) || 12}px ${((R = a.labelStyle) == null ? void 0 : R.fontFamily) || "sans-serif"}`, e.textAlign = Math.abs(Math.cos(s)) < 0.1 ? "center" : Math.cos(s) > 0 ? "left" : "right", e.textBaseline = Math.abs(Math.sin(s)) < 0.1 ? "middle" : Math.sin(s) > 0 ? "top" : "bottom", e.fillText(a.categories[n], c, p);
51
51
  }
52
52
  }
53
- p.forEach((s) => {
54
- const { points: r, style: t } = s;
55
- if (r.length === 0) return;
53
+ f.forEach((n) => {
54
+ const { points: s, style: t } = n;
55
+ if (s.length === 0) return;
56
56
  const l = [];
57
- i.categories.forEach((n, c) => {
58
- const m = r.find((A) => A.category === n), w = (m ? m.value : 0) / i.maxValue * u, I = c * b - Math.PI / 2;
57
+ a.categories.forEach((o, c) => {
58
+ const p = s.find((I) => I.category === o), L = (p ? p.value : 0) / a.maxValue * S, w = c * v - Math.PI / 2;
59
59
  l.push({
60
- x: f + w * Math.cos(I),
61
- y: g + w * Math.sin(I)
60
+ x: g + L * Math.cos(w),
61
+ y: u + L * Math.sin(w)
62
62
  });
63
- }), e.beginPath(), l.forEach((n, c) => {
64
- c === 0 ? e.moveTo(n.x, n.y) : e.lineTo(n.x, n.y);
65
- }), e.closePath(), e.fillStyle = (t == null ? void 0 : t.fillColor) || (t != null && t.color ? `${t.color}33` : "rgba(0, 242, 255, 0.2)"), e.fill(), e.strokeStyle = (t == null ? void 0 : t.color) || "#00f2ff", e.lineWidth = (t == null ? void 0 : t.width) || 2, e.globalAlpha = (t == null ? void 0 : t.opacity) || 1, e.stroke(), ((t == null ? void 0 : t.pointSize) || 0) > 0 && (e.fillStyle = (t == null ? void 0 : t.color) || "#00f2ff", l.forEach((n) => {
66
- e.beginPath(), e.arc(n.x, n.y, t.pointSize / 2, 0, Math.PI * 2), e.fill();
63
+ }), e.beginPath(), l.forEach((o, c) => {
64
+ c === 0 ? e.moveTo(o.x, o.y) : e.lineTo(o.x, o.y);
65
+ }), e.closePath(), e.fillStyle = (t == null ? void 0 : t.fillColor) || (t != null && t.color ? `${t.color}33` : "rgba(0, 242, 255, 0.2)"), e.fill(), e.strokeStyle = (t == null ? void 0 : t.color) || "#00f2ff", e.lineWidth = (t == null ? void 0 : t.width) || 2, e.globalAlpha = (t == null ? void 0 : t.opacity) || 1, e.stroke(), ((t == null ? void 0 : t.pointSize) || 0) > 0 && (e.fillStyle = (t == null ? void 0 : t.color) || "#00f2ff", l.forEach((o) => {
66
+ e.beginPath(), e.arc(o.x, o.y, t.pointSize / 2, 0, Math.PI * 2), e.fill();
67
67
  }));
68
68
  }), e.restore();
69
69
  }
70
70
  return {
71
- manifest: D,
72
- onInit(o) {
73
- a = o, a.chart.updateXAxis({ visible: !1, min: -1.2, max: 1.2 }), a.chart.updateYAxis("default", { visible: !1, min: -1.2, max: 1.2 });
71
+ manifest: T,
72
+ onInit(i) {
73
+ r = i, r.chart.updateXAxis({ visible: !1, min: -1.2, max: 1.2 }), r.chart.updateYAxis("default", { visible: !1, min: -1.2, max: 1.2 });
74
74
  },
75
- onRenderOverlay(o, h) {
76
- T(o);
75
+ onRenderOverlay(i, h) {
76
+ i.chart.getActiveRenderer() !== "svg" && D(i);
77
77
  },
78
78
  api: {
79
- addSeries(o) {
80
- return p.set(o.id, o), a == null || a.requestRender(), o.id;
79
+ addSeries(i) {
80
+ return f.set(i.id, i), r == null || r.requestRender(), i.id;
81
81
  },
82
- removeSeries(o) {
83
- const h = p.delete(o);
84
- return h && (a == null || a.requestRender()), h;
82
+ removeSeries(i) {
83
+ const h = f.delete(i);
84
+ return h && (r == null || r.requestRender()), h;
85
85
  },
86
- updateSeries(o, h) {
87
- const e = p.get(o);
88
- return e ? (e.points = h, a == null || a.requestRender(), !0) : !1;
86
+ updateSeries(i, h) {
87
+ const e = f.get(i);
88
+ return e ? (e.points = h, r == null || r.requestRender(), !0) : !1;
89
89
  },
90
- setCategories(o) {
91
- i.categories = o, a == null || a.requestRender();
90
+ setCategories(i) {
91
+ a.categories = i, r == null || r.requestRender();
92
92
  },
93
- setMaxValue(o) {
94
- i.maxValue = o, a == null || a.requestRender();
93
+ setMaxValue(i) {
94
+ a.maxValue = i, r == null || r.requestRender();
95
+ },
96
+ getSVGExportData() {
97
+ return a.categories.length === 0 ? null : {
98
+ categories: [...a.categories],
99
+ maxValue: a.maxValue,
100
+ gridLevels: a.gridLevels,
101
+ showLabels: a.showLabels,
102
+ labelStyle: a.labelStyle,
103
+ gridStyle: a.gridStyle,
104
+ series: Array.from(f.values())
105
+ };
95
106
  }
96
107
  }
97
108
  };
98
109
  }
99
110
  export {
100
- C as PluginRadar,
101
- C as default
111
+ q as PluginRadar,
112
+ q as default
102
113
  };
103
114
  //# sourceMappingURL=radar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radar.js","sources":["../../src/plugins/radar/index.ts"],"sourcesContent":["import type { \n PluginRadarConfig, \n RadarAPI, \n RadarSeriesData, \n RadarPoint \n} from './types';\nimport type { \n PluginManifest, \n ChartPlugin, \n PluginContext,\n AfterRenderEvent\n} from '../types';\n\nconst manifestRadar: PluginManifest = {\n name: \"velo-plot-radar\",\n version: \"1.0.0\",\n description: \"Advanced Radar/Spider Charts for velo-plot\",\n provides: [\"radar\", \"spider-chart\"],\n tags: [\"radar\", \"visualization\", \"comparison\"],\n};\n\nconst DEFAULT_CONFIG: Required<PluginRadarConfig> = {\n categories: [],\n maxValue: 100,\n minValue: 0,\n gridLevels: 5,\n showLabels: true,\n labelStyle: {\n fontSize: 12,\n color: '#94a3b8',\n fontFamily: 'Inter, system-ui, sans-serif'\n },\n gridStyle: {\n color: 'rgba(255, 255, 255, 0.1)',\n width: 1,\n lineDash: []\n }\n};\n\nexport function PluginRadar(\n userConfig: Partial<PluginRadarConfig> = {}\n): ChartPlugin<PluginRadarConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n const radarSeries = new Map<string, RadarSeriesData>();\n\n // ============================================\n // Drawing Logic\n // ============================================\n\n function drawRadar(pCtx: PluginContext) {\n const { render } = pCtx;\n const { ctx2d, plotArea } = render;\n\n if (!ctx2d) return;\n\n const centerX = plotArea.x + plotArea.width / 2;\n const centerY = plotArea.y + plotArea.height / 2;\n const maxRadiusPixels = Math.min(plotArea.width, plotArea.height) / 2 * 0.8;\n const numCategories = config.categories.length;\n \n if (numCategories === 0) return;\n const angleStep = (2 * Math.PI) / numCategories;\n\n ctx2d.save();\n \n // 1. Draw Grid (Levels)\n ctx2d.strokeStyle = config.gridStyle?.color || 'rgba(255, 255, 255, 0.1)';\n ctx2d.lineWidth = config.gridStyle?.width || 1;\n if (config.gridStyle?.lineDash && config.gridStyle.lineDash.length > 0) {\n ctx2d.setLineDash(config.gridStyle.lineDash);\n }\n\n for (let level = 1; level <= config.gridLevels; level++) {\n const radius = (level / config.gridLevels) * maxRadiusPixels;\n ctx2d.beginPath();\n for (let i = 0; i < numCategories; i++) {\n const angle = i * angleStep - Math.PI / 2;\n const px = centerX + radius * Math.cos(angle);\n const py = centerY + radius * Math.sin(angle);\n if (i === 0) ctx2d.moveTo(px, py);\n else ctx2d.lineTo(px, py);\n }\n ctx2d.closePath();\n ctx2d.stroke();\n }\n\n // 2. Draw Spokes and Labels\n ctx2d.setLineDash([]);\n for (let i = 0; i < numCategories; i++) {\n const angle = i * angleStep - Math.PI / 2;\n const px = centerX + maxRadiusPixels * Math.cos(angle);\n const py = centerY + maxRadiusPixels * Math.sin(angle);\n \n ctx2d.beginPath();\n ctx2d.moveTo(centerX, centerY);\n ctx2d.lineTo(px, py);\n ctx2d.stroke();\n\n if (config.showLabels) {\n const labelRadius = maxRadiusPixels + 25;\n const lx = centerX + labelRadius * Math.cos(angle);\n const ly = centerY + labelRadius * Math.sin(angle);\n \n ctx2d.fillStyle = config.labelStyle?.color || '#94a3b8';\n ctx2d.font = `${config.labelStyle?.fontSize || 12}px ${config.labelStyle?.fontFamily || 'sans-serif'}`;\n ctx2d.textAlign = Math.abs(Math.cos(angle)) < 0.1 ? \"center\" : (Math.cos(angle) > 0 ? \"left\" : \"right\");\n ctx2d.textBaseline = Math.abs(Math.sin(angle)) < 0.1 ? \"middle\" : (Math.sin(angle) > 0 ? \"top\" : \"bottom\");\n ctx2d.fillText(config.categories[i], lx, ly);\n }\n }\n\n // 3. Draw Radar Series\n radarSeries.forEach((series) => {\n const { points, style } = series;\n if (points.length === 0) return;\n\n const pathPoints: { x: number, y: number }[] = [];\n \n config.categories.forEach((cat, idx) => {\n const point = points.find(p => p.category === cat);\n const val = point ? point.value : 0;\n const radius = (val / config.maxValue) * maxRadiusPixels;\n const angle = idx * angleStep - Math.PI / 2;\n \n pathPoints.push({\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n });\n });\n\n ctx2d.beginPath();\n pathPoints.forEach((p, i) => {\n if (i === 0) ctx2d.moveTo(p.x, p.y);\n else ctx2d.lineTo(p.x, p.y);\n });\n ctx2d.closePath();\n \n ctx2d.fillStyle = style?.fillColor || (style?.color ? `${style.color}33` : 'rgba(0, 242, 255, 0.2)');\n ctx2d.fill();\n \n ctx2d.strokeStyle = style?.color || '#00f2ff';\n ctx2d.lineWidth = style?.width || 2;\n ctx2d.globalAlpha = style?.opacity || 1;\n ctx2d.stroke();\n\n if ((style?.pointSize || 0) > 0) {\n ctx2d.fillStyle = style?.color || '#00f2ff';\n pathPoints.forEach(p => {\n ctx2d.beginPath();\n ctx2d.arc(p.x, p.y, style!.pointSize! / 2, 0, Math.PI * 2);\n ctx2d.fill();\n });\n }\n });\n\n ctx2d.restore();\n }\n\n // ============================================\n // Plugin API\n // ============================================\n\n const api: RadarAPI & Record<string, unknown> = {\n addSeries(data: RadarSeriesData) {\n radarSeries.set(data.id, data);\n ctx?.requestRender();\n return data.id;\n },\n removeSeries(id: string) {\n const res = radarSeries.delete(id);\n if (res) ctx?.requestRender();\n return res;\n },\n updateSeries(id: string, points: RadarPoint[]) {\n const series = radarSeries.get(id);\n if (series) {\n series.points = points;\n ctx?.requestRender();\n return true;\n }\n return false;\n },\n setCategories(categories: string[]) {\n config.categories = categories;\n ctx?.requestRender();\n },\n setMaxValue(value: number) {\n config.maxValue = value;\n ctx?.requestRender();\n }\n };\n\n return {\n manifest: manifestRadar,\n\n onInit(c: PluginContext) {\n ctx = c;\n // Setup the chart for Radar (centered origin, fixed bounds)\n ctx.chart.updateXAxis({ visible: false, min: -1.2, max: 1.2 });\n ctx.chart.updateYAxis('default', { visible: false, min: -1.2, max: 1.2 });\n },\n\n onRenderOverlay(pCtx: PluginContext, _event: AfterRenderEvent) {\n drawRadar(pCtx);\n },\n\n api\n };\n}\n\nexport default PluginRadar;\n\nexport type { \n PluginRadarConfig, \n RadarAPI, \n RadarSeriesData, \n RadarPoint \n} from './types';\n"],"names":["manifestRadar","DEFAULT_CONFIG","PluginRadar","userConfig","config","ctx","radarSeries","drawRadar","pCtx","_a","_b","_c","_d","_e","_f","render","ctx2d","plotArea","centerX","centerY","maxRadiusPixels","numCategories","angleStep","level","radius","i","angle","px","py","labelRadius","lx","ly","series","points","style","pathPoints","cat","idx","point","p","c","_event","data","id","res","categories","value"],"mappings":"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"}
1
+ {"version":3,"file":"radar.js","sources":["../../src/plugins/radar/index.ts"],"sourcesContent":["import type { \n PluginRadarConfig, \n RadarAPI, \n RadarSeriesData, \n RadarPoint \n} from './types';\nimport type { \n PluginManifest, \n ChartPlugin, \n PluginContext,\n AfterRenderEvent\n} from '../types';\n\nconst manifestRadar: PluginManifest = {\n name: \"velo-plot-radar\",\n version: \"1.0.0\",\n description: \"Advanced Radar/Spider Charts for velo-plot\",\n provides: [\"radar\", \"spider-chart\"],\n tags: [\"radar\", \"visualization\", \"comparison\"],\n};\n\nconst DEFAULT_CONFIG: Required<PluginRadarConfig> = {\n categories: [],\n maxValue: 100,\n minValue: 0,\n gridLevels: 5,\n showLabels: true,\n labelStyle: {\n fontSize: 12,\n color: '#94a3b8',\n fontFamily: 'Inter, system-ui, sans-serif'\n },\n gridStyle: {\n color: 'rgba(255, 255, 255, 0.1)',\n width: 1,\n lineDash: []\n }\n};\n\nexport function PluginRadar(\n userConfig: Partial<PluginRadarConfig> = {}\n): ChartPlugin<PluginRadarConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n const radarSeries = new Map<string, RadarSeriesData>();\n\n // ============================================\n // Drawing Logic\n // ============================================\n\n function drawRadar(pCtx: PluginContext) {\n const { render } = pCtx;\n const { ctx2d, plotArea } = render;\n\n if (!ctx2d) return;\n\n const centerX = plotArea.x + plotArea.width / 2;\n const centerY = plotArea.y + plotArea.height / 2;\n const maxRadiusPixels = Math.min(plotArea.width, plotArea.height) / 2 * 0.8;\n const numCategories = config.categories.length;\n \n if (numCategories === 0) return;\n const angleStep = (2 * Math.PI) / numCategories;\n\n ctx2d.save();\n \n // 1. Draw Grid (Levels)\n ctx2d.strokeStyle = config.gridStyle?.color || 'rgba(255, 255, 255, 0.1)';\n ctx2d.lineWidth = config.gridStyle?.width || 1;\n if (config.gridStyle?.lineDash && config.gridStyle.lineDash.length > 0) {\n ctx2d.setLineDash(config.gridStyle.lineDash);\n }\n\n for (let level = 1; level <= config.gridLevels; level++) {\n const radius = (level / config.gridLevels) * maxRadiusPixels;\n ctx2d.beginPath();\n for (let i = 0; i < numCategories; i++) {\n const angle = i * angleStep - Math.PI / 2;\n const px = centerX + radius * Math.cos(angle);\n const py = centerY + radius * Math.sin(angle);\n if (i === 0) ctx2d.moveTo(px, py);\n else ctx2d.lineTo(px, py);\n }\n ctx2d.closePath();\n ctx2d.stroke();\n }\n\n // 2. Draw Spokes and Labels\n ctx2d.setLineDash([]);\n for (let i = 0; i < numCategories; i++) {\n const angle = i * angleStep - Math.PI / 2;\n const px = centerX + maxRadiusPixels * Math.cos(angle);\n const py = centerY + maxRadiusPixels * Math.sin(angle);\n \n ctx2d.beginPath();\n ctx2d.moveTo(centerX, centerY);\n ctx2d.lineTo(px, py);\n ctx2d.stroke();\n\n if (config.showLabels) {\n const labelRadius = maxRadiusPixels + 25;\n const lx = centerX + labelRadius * Math.cos(angle);\n const ly = centerY + labelRadius * Math.sin(angle);\n \n ctx2d.fillStyle = config.labelStyle?.color || '#94a3b8';\n ctx2d.font = `${config.labelStyle?.fontSize || 12}px ${config.labelStyle?.fontFamily || 'sans-serif'}`;\n ctx2d.textAlign = Math.abs(Math.cos(angle)) < 0.1 ? \"center\" : (Math.cos(angle) > 0 ? \"left\" : \"right\");\n ctx2d.textBaseline = Math.abs(Math.sin(angle)) < 0.1 ? \"middle\" : (Math.sin(angle) > 0 ? \"top\" : \"bottom\");\n ctx2d.fillText(config.categories[i], lx, ly);\n }\n }\n\n // 3. Draw Radar Series\n radarSeries.forEach((series) => {\n const { points, style } = series;\n if (points.length === 0) return;\n\n const pathPoints: { x: number, y: number }[] = [];\n \n config.categories.forEach((cat, idx) => {\n const point = points.find(p => p.category === cat);\n const val = point ? point.value : 0;\n const radius = (val / config.maxValue) * maxRadiusPixels;\n const angle = idx * angleStep - Math.PI / 2;\n \n pathPoints.push({\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n });\n });\n\n ctx2d.beginPath();\n pathPoints.forEach((p, i) => {\n if (i === 0) ctx2d.moveTo(p.x, p.y);\n else ctx2d.lineTo(p.x, p.y);\n });\n ctx2d.closePath();\n \n ctx2d.fillStyle = style?.fillColor || (style?.color ? `${style.color}33` : 'rgba(0, 242, 255, 0.2)');\n ctx2d.fill();\n \n ctx2d.strokeStyle = style?.color || '#00f2ff';\n ctx2d.lineWidth = style?.width || 2;\n ctx2d.globalAlpha = style?.opacity || 1;\n ctx2d.stroke();\n\n if ((style?.pointSize || 0) > 0) {\n ctx2d.fillStyle = style?.color || '#00f2ff';\n pathPoints.forEach(p => {\n ctx2d.beginPath();\n ctx2d.arc(p.x, p.y, style!.pointSize! / 2, 0, Math.PI * 2);\n ctx2d.fill();\n });\n }\n });\n\n ctx2d.restore();\n }\n\n // ============================================\n // Plugin API\n // ============================================\n\n const api: RadarAPI & Record<string, unknown> = {\n addSeries(data: RadarSeriesData) {\n radarSeries.set(data.id, data);\n ctx?.requestRender();\n return data.id;\n },\n removeSeries(id: string) {\n const res = radarSeries.delete(id);\n if (res) ctx?.requestRender();\n return res;\n },\n updateSeries(id: string, points: RadarPoint[]) {\n const series = radarSeries.get(id);\n if (series) {\n series.points = points;\n ctx?.requestRender();\n return true;\n }\n return false;\n },\n setCategories(categories: string[]) {\n config.categories = categories;\n ctx?.requestRender();\n },\n setMaxValue(value: number) {\n config.maxValue = value;\n ctx?.requestRender();\n },\n getSVGExportData() {\n if (config.categories.length === 0) return null;\n return {\n categories: [...config.categories],\n maxValue: config.maxValue,\n gridLevels: config.gridLevels,\n showLabels: config.showLabels,\n labelStyle: config.labelStyle,\n gridStyle: config.gridStyle,\n series: Array.from(radarSeries.values()),\n };\n },\n };\n\n return {\n manifest: manifestRadar,\n\n onInit(c: PluginContext) {\n ctx = c;\n // Setup the chart for Radar (centered origin, fixed bounds)\n ctx.chart.updateXAxis({ visible: false, min: -1.2, max: 1.2 });\n ctx.chart.updateYAxis('default', { visible: false, min: -1.2, max: 1.2 });\n },\n\n onRenderOverlay(pCtx: PluginContext, _event: AfterRenderEvent) {\n if (pCtx.chart.getActiveRenderer() === \"svg\") return;\n drawRadar(pCtx);\n },\n\n api\n };\n}\n\nexport default PluginRadar;\n\nexport type { \n PluginRadarConfig, \n RadarAPI, \n RadarSeriesData, \n RadarPoint \n} from './types';\n"],"names":["manifestRadar","DEFAULT_CONFIG","PluginRadar","userConfig","config","ctx","radarSeries","drawRadar","pCtx","_a","_b","_c","_d","_e","_f","render","ctx2d","plotArea","centerX","centerY","maxRadiusPixels","numCategories","angleStep","level","radius","i","angle","px","py","labelRadius","lx","ly","series","points","style","pathPoints","cat","idx","point","p","c","_event","data","id","res","categories","value"],"mappings":"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"}