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.
- package/README.md +22 -15
- package/dist/ChartCore-KYG2HTcK.js +7474 -0
- package/dist/ChartCore-KYG2HTcK.js.map +1 -0
- package/dist/GpuChartRenderer-Dxc0hrQA.js +75 -0
- package/dist/GpuChartRenderer-Dxc0hrQA.js.map +1 -0
- package/dist/{index.core-BmZe2jRQ.js → PluginRegistry-CDf_jcnp.js} +19 -33
- package/dist/PluginRegistry-CDf_jcnp.js.map +1 -0
- package/dist/SVGDocumentBuilder-C-uLkcFW.js +83 -0
- package/dist/SVGDocumentBuilder-C-uLkcFW.js.map +1 -0
- package/dist/angular-hooks.js +1 -1
- package/dist/angular.js +8 -8
- package/dist/{axisFormat-CzumxpCL.js → axisFormat-Sz4WIJfQ.js} +2 -2
- package/dist/{axisFormat-CzumxpCL.js.map → axisFormat-Sz4WIJfQ.js.map} +1 -1
- package/dist/{chartSyncBridge-DbWrwtyP.js → chartSyncBridge-C1uRy0ZS.js} +12 -11
- package/dist/{chartSyncBridge-DbWrwtyP.js.map → chartSyncBridge-C1uRy0ZS.js.map} +1 -1
- package/dist/core/ChartStatistics.d.ts +1 -1
- package/dist/core/chart/ChartCore.d.ts +19 -20
- package/dist/core/chart/ChartFeatureHooks.d.ts +7 -0
- package/dist/core/chart/ChartRenderLoop.d.ts +5 -0
- package/dist/core/chart/ChartRenderer.d.ts +9 -0
- package/dist/core/chart/ChartSetup.d.ts +1 -0
- package/dist/core/chart/chartExportPatch.d.ts +2 -0
- package/dist/core/chart/exporter/SVGExporter.d.ts +9 -7
- package/dist/core/chart/exporter/svg/SVGDocumentBuilder.d.ts +27 -0
- package/dist/core/chart/exporter/svg/SVGExportContext.d.ts +147 -0
- package/dist/core/chart/exporter/svg/SVGOrchestrator.d.ts +3 -0
- package/dist/core/chart/exporter/svg/SVGThemeAdapter.d.ts +22 -0
- package/dist/core/chart/exporter/svg/__tests__/testFixtures.d.ts +46 -0
- package/dist/core/chart/exporter/svg/__tests__/visualTestUtils.d.ts +12 -0
- package/dist/core/chart/exporter/svg/overlay/axes.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/border.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/errorBars.d.ts +7 -0
- package/dist/core/chart/exporter/svg/overlay/grid.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/index.d.ts +12 -0
- package/dist/core/chart/exporter/svg/overlay/legend.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/pluginCharts.d.ts +6 -0
- package/dist/core/chart/exporter/svg/overlay/polarGrid.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/specialChart.d.ts +15 -0
- package/dist/core/chart/exporter/svg/overlay/title.d.ts +4 -0
- package/dist/core/chart/exporter/svg/plugins/annotations.d.ts +5 -0
- package/dist/core/chart/exporter/svg/plugins/brokenAxis.d.ts +20 -0
- package/dist/core/chart/exporter/svg/plugins/latex.d.ts +9 -0
- package/dist/core/chart/exporter/svg/plugins/register.d.ts +8 -0
- package/dist/core/chart/exporter/svg/plugins/regression.d.ts +33 -0
- package/dist/core/chart/exporter/svg/plugins/roi.d.ts +12 -0
- package/dist/core/chart/exporter/svg/plugins/tradeMarkers.d.ts +3 -0
- package/dist/core/chart/exporter/svg/plugins/types.d.ts +28 -0
- package/dist/core/chart/exporter/svg/plugins/watermark.d.ts +13 -0
- package/dist/core/chart/exporter/svg/series/band.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/bar.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/boxplot.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/candlestick.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/finitePoints.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/gauge.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/heatmap.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/indicator.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/line.d.ts +12 -0
- package/dist/core/chart/exporter/svg/series/polar.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/radar.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/registry.d.ts +10 -0
- package/dist/core/chart/exporter/svg/series/sankey.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/scatter.d.ts +1 -0
- package/dist/core/chart/exporter/svg/series/ternary.d.ts +7 -0
- package/dist/core/chart/exporter/svg/series/waterfall.d.ts +6 -0
- package/dist/core/chart/exporter/svg/seriesAtTimestamp.d.ts +4 -0
- package/dist/core/chart/exporter/svg/seriesUtils.d.ts +3 -0
- package/dist/core/chart/exporter/svg/symbols.d.ts +5 -0
- package/dist/core/chart/exporter/svg/tickUtils.d.ts +9 -0
- package/dist/core/chart/mountSVGString.d.ts +5 -0
- package/dist/core/chart/overlaySeriesRegistry.d.ts +7 -0
- package/dist/core/chart/series/SeriesActions.d.ts +1 -0
- package/dist/core/chart/series/SeriesBufferLite.d.ts +13 -0
- package/dist/core/chart/series/seriesOptionsRegistry.d.ts +8 -0
- package/dist/core/chart/series/seriesTypeRegistry.d.ts +5 -0
- package/dist/core/chart/types.d.ts +2 -2
- package/dist/core/stacked/StackSVGComposer.d.ts +14 -0
- package/dist/core/stacked/index.d.ts +3 -2
- package/dist/core/stacked/types.d.ts +12 -4
- package/dist/createStackedChart-DjA3aJAu.js +2761 -0
- package/dist/createStackedChart-DjA3aJAu.js.map +1 -0
- package/dist/{hooks-CYPCxoZx.js → hooks-4wQH27r9.js} +7 -7
- package/dist/{hooks-CYPCxoZx.js.map → hooks-4wQH27r9.js.map} +1 -1
- package/dist/{index-qunX30Xu.js → index-B7PTX94B.js} +2133 -2133
- package/dist/index-B7PTX94B.js.map +1 -0
- package/dist/{index-BMiZoKmm.js → index-BgrvqltV.js} +67 -67
- package/dist/index-BgrvqltV.js.map +1 -0
- package/dist/index-Bj-xyXY6.js +582 -0
- package/dist/index-Bj-xyXY6.js.map +1 -0
- package/dist/index-qhscKTDy.js.map +1 -1
- package/dist/index.core.d.ts +8 -6
- package/dist/index.d.ts +1 -14
- package/dist/plugins/3d.js +3 -1
- package/dist/plugins/3d.js.map +1 -1
- package/dist/plugins/PluginManager.d.ts +5 -0
- package/dist/plugins/analysis.js.map +1 -1
- package/dist/plugins/annotations.js +8 -7
- package/dist/plugins/annotations.js.map +1 -1
- package/dist/plugins/broken-axis.js +198 -152
- package/dist/plugins/broken-axis.js.map +1 -1
- package/dist/plugins/createPlugin.d.ts +8 -0
- package/dist/plugins/debug.js +32 -32
- package/dist/plugins/debug.js.map +1 -1
- package/dist/plugins/forecasting.js +273 -258
- package/dist/plugins/forecasting.js.map +1 -1
- package/dist/plugins/gpu.js +2033 -209
- package/dist/plugins/gpu.js.map +1 -1
- package/dist/plugins/i18n.js +286 -23
- package/dist/plugins/i18n.js.map +1 -1
- package/dist/plugins/latex.js +766 -207
- package/dist/plugins/latex.js.map +1 -1
- package/dist/plugins/loading/index.d.ts +1 -2
- package/dist/plugins/loading.js +3 -4
- package/dist/plugins/ml-integration.js +107 -93
- package/dist/plugins/ml-integration.js.map +1 -1
- package/dist/plugins/offscreen.js +11 -10
- package/dist/plugins/offscreen.js.map +1 -1
- package/dist/plugins/radar/types.d.ts +11 -0
- package/dist/plugins/radar.js +64 -53
- package/dist/plugins/radar.js.map +1 -1
- package/dist/plugins/regression.js +254 -256
- package/dist/plugins/regression.js.map +1 -1
- package/dist/plugins/roi/index.d.ts +2 -0
- package/dist/plugins/roi.js +184 -145
- package/dist/plugins/roi.js.map +1 -1
- package/dist/plugins/snapshot.js +20 -15
- package/dist/plugins/snapshot.js.map +1 -1
- package/dist/plugins/streaming.js +1 -1
- package/dist/plugins/tools.js +1 -1
- package/dist/plugins/types.d.ts +4 -0
- package/dist/react.js +55 -58
- package/dist/react.js.map +1 -1
- package/dist/regression-HNdyk1Dm.js +28 -0
- package/dist/regression-HNdyk1Dm.js.map +1 -0
- package/dist/renderer/ChartSeriesRenderer.d.ts +3 -2
- package/dist/renderer/NativeWebGLRenderer.d.ts +2 -1
- package/dist/renderer/SVGChartRenderer.d.ts +15 -0
- package/dist/renderer/SankeyRenderer.d.ts +1 -0
- package/dist/renderer/native/NativeWebGLRenderer.d.ts +5 -1
- package/dist/renderer/native/draw.d.ts +2 -47
- package/dist/renderer/native/drawCore.d.ts +27 -0
- package/dist/renderer/native/drawExtended.d.ts +29 -0
- package/dist/renderer/native/frameRenderExtended.d.ts +1 -0
- package/dist/renderer/native/frameRenderRegistry.d.ts +27 -0
- package/dist/renderer/native/programFactoryCore.d.ts +6 -0
- package/dist/renderer/native/programFactoryExtended.d.ts +4 -0
- package/dist/renderer/native/utils.d.ts +3 -29
- package/dist/renderer/native/utilsCore.d.ts +14 -0
- package/dist/renderer/native/utilsExtended.d.ts +17 -0
- package/dist/renderer/overlaySeriesExtended.d.ts +1 -0
- package/dist/renderer/registerExtendedSeries.d.ts +1 -0
- package/dist/renderer/registerSVG.d.ts +5 -0
- package/dist/renderer/registerWebGPU.d.ts +2 -0
- package/dist/renderer/sankeyLayout.d.ts +29 -0
- package/dist/renderer/seriesBufferExtended.d.ts +4 -0
- package/dist/scientific/index.d.ts +1 -5
- package/dist/scientific/registerScientific.d.ts +1 -0
- package/dist/scientific.js +41 -41
- package/dist/solid.js +56 -59
- package/dist/solid.js.map +1 -1
- package/dist/svelte.js +26 -29
- package/dist/svelte.js.map +1 -1
- package/dist/tickUtils-B_X-ha13.js +41 -0
- package/dist/tickUtils-B_X-ha13.js.map +1 -0
- package/dist/trading/index.d.ts +1 -4
- package/dist/trading/registerTrading.d.ts +3 -0
- package/dist/trading.js +42 -42
- package/dist/types.d.ts +5 -4
- package/dist/velo-plot.full.js +1951 -1275
- package/dist/velo-plot.full.js.map +1 -1
- package/dist/velo-plot.js +33 -28
- package/dist/velo-plot.js.map +1 -1
- package/dist/vue/VeloPlot.vue.d.ts +1 -1
- package/dist/vue/index.d.ts +33 -33
- package/dist/vue.js +17 -20
- package/dist/vue.js.map +1 -1
- package/package.json +14 -1
- package/dist/ChartCore-BpzRvN4Y.js +0 -8467
- package/dist/ChartCore-BpzRvN4Y.js.map +0 -1
- package/dist/createStackedChart-Dm-YqUT7.js +0 -756
- package/dist/createStackedChart-Dm-YqUT7.js.map +0 -1
- package/dist/gpuRenderer-BpaMYz-k.js +0 -1848
- package/dist/gpuRenderer-BpaMYz-k.js.map +0 -1
- package/dist/index-BMiZoKmm.js.map +0 -1
- package/dist/index-qunX30Xu.js.map +0 -1
- package/dist/index-x4stH3jD.js +0 -282
- package/dist/index-x4stH3jD.js.map +0 -1
- package/dist/index.core-BmZe2jRQ.js.map +0 -1
- package/dist/mockDatafeed-DHIDPcpX.js +0 -515
- package/dist/mockDatafeed-DHIDPcpX.js.map +0 -1
- package/dist/symbols-DT0eLlpW.js +0 -568
- package/dist/symbols-DT0eLlpW.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broken-axis.js","sources":["../../src/plugins/broken-axis/BrokenAxisScale.ts","../../src/plugins/broken-axis/index.ts"],"sourcesContent":["import type { Scale } from \"../../scales\";\nimport type { AxisBreak } from \"./types\";\n\nexport class BrokenAxisScale implements Scale {\n public domain: [number, number] = [0, 1];\n public range: [number, number] = [0, 100];\n public readonly type = \"linear\"; // Compatible with linear for renderer selection\n\n private underlying: Scale;\n private sortedBreaks: AxisBreak[] = [];\n private visibleRanges: { start: number; end: number; pixelOffset: number; pixelScale: number }[] = [];\n private availableVisualRatio: number = 1.0;\n\n constructor(originalScale: Scale, private breaks: AxisBreak[]) {\n this.underlying = originalScale;\n this.domain = [...originalScale.domain];\n this.range = [...originalScale.range];\n this.refresh();\n }\n\n setDomain(min: number, max: number): void {\n this.domain = [min, max];\n this.underlying.setDomain(min, max);\n this.refresh();\n }\n\n setRange(min: number, max: number): void {\n this.range = [min, max];\n this.underlying.setRange(min, max);\n this.refresh();\n }\n\n updateBreaks(breaks: AxisBreak[]) {\n this.breaks = breaks;\n this.refresh();\n }\n\n private refresh() {\n const [min, max] = this.domain;\n \n // 1. Sort and filter breaks within [min, max]\n this.sortedBreaks = this.breaks\n .filter(b => b.start < max && b.end > min)\n .map(b => ({\n ...b,\n start: Math.max(min, b.start),\n end: Math.min(max, b.end),\n visualRatio: b.visualRatio ?? 0.02\n }))\n .sort((a, b) => a.start - b.start);\n\n // 2. Identify visible data segments\n const segments: { start: number; end: number }[] = [];\n let current = min;\n\n for (const b of this.sortedBreaks) {\n if (b.start > current) {\n segments.push({ start: current, end: b.start });\n }\n current = b.end;\n }\n if (current < max) {\n segments.push({ start: current, end: max });\n }\n\n // 3. Calculate total data span of visible segments\n const totalVisibleDataWidth = segments.reduce((sum, s) => sum + (s.end - s.start), 0) || 1e-10;\n const totalBreakVisualRatio = this.sortedBreaks.reduce((sum, b) => sum + (b.visualRatio || 0.02), 0);\n this.availableVisualRatio = Math.max(0.1, 1.0 - totalBreakVisualRatio);\n\n // 4. Calculate mapping for each segment (in 0-1 ratio space)\n let currentRatioOffset = 0;\n this.visibleRanges = segments.map(s => {\n const dataWidth = s.end - s.start;\n const visualWidth = (dataWidth / totalVisibleDataWidth) * this.availableVisualRatio;\n const range = {\n start: s.start,\n end: s.end,\n pixelOffset: currentRatioOffset,\n pixelScale: visualWidth / dataWidth\n };\n \n // Find following break if any to advance offset\n const nextBreak = this.sortedBreaks.find(b => Math.abs(b.start - s.end) < 1e-10);\n currentRatioOffset += visualWidth + (nextBreak?.visualRatio ?? 0);\n \n return range;\n });\n }\n\n transform(value: number): number {\n const [min, max] = this.domain;\n const [r0, r1] = this.range;\n const isReverse = r1 < r0;\n \n let ratio = 0;\n if (value <= min) ratio = 0;\n else if (value >= max) ratio = 1;\n else {\n let found = false;\n // Check visible segments\n for (const range of this.visibleRanges) {\n if (value >= range.start && value <= range.end) {\n ratio = range.pixelOffset + (value - range.start) * range.pixelScale;\n found = true;\n break;\n }\n }\n \n // If in break\n if (!found) {\n for (const b of this.sortedBreaks) {\n if (value >= b.start && value <= b.end) {\n const prevRange = this.visibleRanges.find(r => Math.abs(r.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n ratio = offset + (value - b.start) / (b.end - b.start) * (b.visualRatio ?? 0.02);\n found = true;\n break;\n }\n }\n }\n \n if (!found) ratio = 0;\n }\n\n // Map ratio to pixels\n return isReverse ? r0 - ratio * (r0 - r1) : r0 + ratio * (r1 - r0);\n }\n\n /** Map data value to 0-1 ratio space (handles breaks) */\n mapToRatio(value: number): number {\n const [min, max] = this.domain;\n if (value <= min) return 0;\n if (value >= max) return 1;\n\n for (const range of this.visibleRanges) {\n if (value >= range.start && value <= range.end) {\n return range.pixelOffset + (value - range.start) * range.pixelScale;\n }\n }\n\n for (const b of this.sortedBreaks) {\n if (value >= b.start && value <= b.end) {\n const prevRange = this.visibleRanges.find(r => Math.abs(r.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n return offset + (value - b.start) / (b.end - b.start) * (b.visualRatio ?? 0.02);\n }\n }\n\n return 0;\n }\n\n invert(pixel: number): number {\n const [r0, r1] = this.range;\n const ratio = (pixel - r0) / (r1 - r0);\n \n const r = Math.max(0, Math.min(1, ratio));\n\n for (const range of this.visibleRanges) {\n const visualEnd = range.pixelOffset + (range.end - range.start) * range.pixelScale;\n if (r >= range.pixelOffset && r <= visualEnd) {\n return range.start + (r - range.pixelOffset) / range.pixelScale;\n }\n }\n\n // In break, return nearest segment boundary\n for (let i = 0; i < this.sortedBreaks.length; i++) {\n const b = this.sortedBreaks[i];\n const prevRange = this.visibleRanges.find(range => Math.abs(range.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n if (r >= offset && r <= offset + (b.visualRatio ?? 0.02)) {\n return b.start;\n }\n }\n\n return this.domain[0];\n }\n\n ticks(count: number = 10): number[] {\n // Generate ticks for each visible segment based on their visual weight\n const allTicks: number[] = [];\n \n for (const range of this.visibleRanges) {\n const visualWeight = (range.end - range.start) / (this.domain[1] - this.domain[0]);\n const segmentCount = Math.max(2, Math.round(count * visualWeight / this.availableVisualRatio));\n \n // Use underlying logic for \"nice\" steps but restricted to this range\n const segmentTicks = this.generateSegmentTicks(range.start, range.end, segmentCount);\n allTicks.push(...segmentTicks);\n }\n\n // Remove duplicates and sort\n return Array.from(new Set(allTicks)).sort((a, b) => a - b);\n }\n\n private generateSegmentTicks(min: number, max: number, count: number): number[] {\n const range = max - min;\n if (range <= 0 || !isFinite(range)) return [];\n \n // Re-use niceStep logic\n const rawStep = range / count;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n let step: number;\n if (normalized < 1.5) step = 1; else if (normalized < 3) step = 2; else if (normalized < 7) step = 5; else step = 10;\n step *= magnitude;\n\n const start = Math.ceil(min / step) * step;\n const ticks: number[] = [];\n let t = start;\n while (t <= max + step * 0.1) {\n ticks.push(Math.round(t * 1e12) / 1e12);\n t += step;\n }\n return ticks;\n }\n}\n","/**\n * @fileoverview Broken Axis plugin for displaying discontinuous data ranges.\n * @module plugins/broken-axis\n */\n\nimport type {\n PluginBrokenAxisConfig,\n BrokenAxisAPI,\n AxisBreak,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\nimport { BrokenAxisScale } from './BrokenAxisScale';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-broken-axis',\n version: '1.0.1',\n description: 'Support for gaps/breaks in axes with visual indicators',\n provides: ['broken-axis', 'coordinate-transform'],\n tags: ['axis', 'layout', 'visualization'],\n};\n\nexport function PluginBrokenAxis(\n config: PluginBrokenAxisConfig = { axes: {} }\n): ChartPlugin<PluginBrokenAxisConfig> {\n // Default enabled to true if not specified\n if (config.enabled === undefined) config.enabled = true;\n \n let ctx: PluginContext | null = null;\n let originalXScale: any = null;\n let brokenXScale: BrokenAxisScale | null = null;\n\n // Storage for raw (un-warped) data of series to allow re-transformation.\n const rawDataStore = new Map<string, { x: Float32Array; y: Float32Array }>();\n\n /** Union X-extent across all stored series — the domain breaks live in. */\n function computeWarpDomain(): [number, number] | null {\n let min = Infinity;\n let max = -Infinity;\n for (const raw of rawDataStore.values()) {\n for (let i = 0; i < raw.x.length; i++) {\n const v = raw.x[i];\n if (v < min) min = v;\n if (v > max) max = v;\n }\n }\n if (!Number.isFinite(min) || !Number.isFinite(max) || min === max) return null;\n return [min, max];\n }\n\n function updateScales() {\n if (!ctx || !config.enabled) return;\n\n const options = config.axes.default || config.axes.xAxis;\n if (options && brokenXScale) {\n brokenXScale.updateBreaks(options.breaks);\n // On break change, we must re-transform everything\n applyTransformations({ syncView: true });\n }\n }\n\n /**\n * Re-warp every stored series into compressed (broken) space using the\n * data-derived warp domain, then align the chart's X view to that domain so\n * the axis ticks and break symbols (which the render pass computes from\n * viewBounds) line up with the warped data.\n */\n function applyTransformations(opts: { syncView?: boolean } = {}) {\n if (!ctx || !brokenXScale || !config.enabled) return;\n const chart = ctx.chart as any;\n\n const domain = computeWarpDomain();\n if (!domain) return;\n const [min, max] = domain;\n const range = max - min || 1;\n\n // Pin the scale to the warp domain so mapToRatio uses the correct segments,\n // independent of whatever sub-range the last render/zoom left behind.\n brokenXScale.setDomain(min, max);\n\n for (const [id, raw] of rawDataStore.entries()) {\n const transformedX = new Float32Array(raw.x.length);\n for (let i = 0; i < raw.x.length; i++) {\n transformedX[i] = min + brokenXScale.mapToRatio(raw.x[i]) * range;\n }\n // Call the TRUE underlying updateSeries to avoid the hijacking loop.\n if (chart._originalUpdateSeries) {\n chart._originalUpdateSeries(id, { x: transformedX, y: raw.y });\n }\n }\n\n if (opts.syncView && typeof chart.zoom === 'function') {\n // Constrain X to the warped data domain (warped values also span\n // [min,max]). Y is left untouched so the caller's Y range is preserved.\n chart.zoom({ x: [min, max], animate: false });\n }\n }\n\n function drawBreakSymbols(pCtx: PluginContext) {\n const { render } = pCtx;\n const { ctx2d, plotArea } = render;\n if (!ctx2d || !brokenXScale) return;\n\n for (const [axisId, options] of Object.entries(config.axes)) {\n const orientation = (axisId === 'default' || axisId === 'xAxis') ? 'horizontal' : 'vertical';\n if (orientation !== 'horizontal') continue;\n\n options.breaks.forEach(b => {\n const pxStart = brokenXScale!.transform(b.start);\n const pxEnd = brokenXScale!.transform(b.end);\n const midPx = (pxStart + pxEnd) / 2;\n // Per-break symbol takes precedence, then the axis default.\n const symbol = b.symbol || options.defaultSymbol || 'diagonal';\n\n ctx2d.save();\n ctx2d.lineWidth = 1.5;\n ctx2d.strokeStyle = options.symbolColor || '#ff00ff';\n\n if (orientation === 'horizontal') {\n drawSymbol(ctx2d, midPx, plotArea.y, symbol, 'top');\n drawSymbol(ctx2d, midPx, plotArea.y + plotArea.height, symbol, 'bottom');\n }\n ctx2d.restore();\n });\n }\n }\n\n function drawSymbol(ctx: CanvasRenderingContext2D, x: number, y: number, type: string, edge: string) {\n const size = 6;\n ctx.beginPath();\n if (type === 'diagonal') {\n ctx.moveTo(x - size, y + size/2);\n ctx.lineTo(x + size, y - size/2);\n ctx.moveTo(x - size + 3, y + size/2);\n ctx.lineTo(x + size + 3, y - size/2);\n } else if (type === 'zigzag') {\n ctx.moveTo(x - size, y);\n ctx.lineTo(x - size/2, y - size/2);\n ctx.lineTo(x + size/2, y + size/2);\n ctx.lineTo(x + size, y);\n } else {\n if (edge === 'top' || edge === 'bottom') {\n ctx.moveTo(x - size, y - 2); ctx.lineTo(x + size, y + 2);\n ctx.moveTo(x - size, y - 6); ctx.lineTo(x + size, y - 2);\n } else {\n ctx.moveTo(x - 2, y - size); ctx.lineTo(x + 2, y + size);\n }\n }\n ctx.stroke();\n }\n\n const api: BrokenAxisAPI = {\n addBreak(axisId, b) {\n if (!config.axes[axisId]) config.axes[axisId] = { breaks: [] };\n config.axes[axisId].breaks.push(b);\n updateScales();\n ctx?.requestRender();\n },\n clearBreaks(axisId) {\n if (config.axes[axisId]) config.axes[axisId].breaks = [];\n updateScales();\n ctx?.requestRender();\n },\n setEnabled(enabled: boolean) {\n const wasEnabled = config.enabled;\n config.enabled = enabled;\n \n if (ctx && wasEnabled !== enabled) {\n const chart = ctx.chart;\n if (enabled) {\n originalXScale = (chart as any).xScale;\n brokenXScale = new BrokenAxisScale(originalXScale, (config.axes.default || config.axes.xAxis)?.breaks || []);\n chart.setXScale(brokenXScale);\n applyTransformations({ syncView: true });\n } else {\n if (originalXScale) {\n chart.setXScale(originalXScale);\n brokenXScale = null;\n // Restore original data to series\n for (const [id, raw] of rawDataStore.entries()) {\n (chart as any)._originalUpdateSeries(id, raw);\n }\n }\n }\n }\n ctx?.requestRender();\n },\n getBreaks(axisId: string): AxisBreak[] {\n return config.axes[axisId]?.breaks || [];\n },\n updateConfig(newConfig: Partial<PluginBrokenAxisConfig>) {\n Object.assign(config, newConfig);\n updateScales();\n ctx?.requestRender();\n }\n };\n\n const pluginApi: BrokenAxisAPI & Record<string, unknown> = api as any;\n\n return {\n manifest,\n onInit(pCtx) {\n ctx = pCtx;\n const chart = ctx.chart as any;\n // NOTE: `chart.brokenAxis` is a read-only getter on ChartCore that resolves\n // this plugin's `api` via the plugin bridge — do NOT assign to it (that\n // throws \"Cannot set property ... which has only a getter\" and aborts\n // plugin registration entirely).\n\n // Hijack and Save original methods\n chart._originalUpdateSeries = chart.updateSeries.bind(chart);\n chart._originalAddSeries = chart.addSeries.bind(chart);\n chart._originalAppendData = chart.appendData.bind(chart);\n\n const toF32 = (v: any): Float32Array =>\n v instanceof Float32Array ? v : new Float32Array(typeof v === 'number' ? [v] : v);\n\n chart.updateSeries = (id: string, data: any) => {\n if (data.x && data.y) {\n rawDataStore.set(id, { x: toF32(data.x), y: toF32(data.y) });\n }\n\n if (config.enabled && brokenXScale && data.x) {\n // Re-warp all series against the (possibly grown) data domain.\n applyTransformations({ syncView: true });\n } else {\n chart._originalUpdateSeries(id, data);\n }\n };\n\n chart.addSeries = (options: any) => {\n if (options.id && options.data?.x && options.data?.y) {\n rawDataStore.set(options.id, { x: toF32(options.data.x), y: toF32(options.data.y) });\n }\n\n if (config.enabled && brokenXScale && options.data?.x) {\n // Add the series (untransformed) so the chart registers it, then\n // warp every series consistently against the data-derived domain.\n chart._originalAddSeries(options);\n applyTransformations({ syncView: true });\n } else {\n chart._originalAddSeries(options);\n }\n };\n\n chart.appendData = (id: string, x: any, y: any) => {\n const raw = rawDataStore.get(id);\n if (raw) {\n const newX = toF32(x);\n const newY = toF32(y);\n const combinedX = new Float32Array(raw.x.length + newX.length);\n const combinedY = new Float32Array(raw.y.length + newY.length);\n combinedX.set(raw.x);\n combinedX.set(newX, raw.x.length);\n combinedY.set(raw.y);\n combinedY.set(newY, raw.y.length);\n rawDataStore.set(id, { x: combinedX, y: combinedY });\n }\n\n if (config.enabled && brokenXScale) {\n applyTransformations({ syncView: true });\n } else {\n chart._originalAppendData(id, x, y);\n }\n };\n\n if (config.enabled) {\n originalXScale = chart.xScale; \n const options = config.axes.default || config.axes.xAxis;\n brokenXScale = new BrokenAxisScale(originalXScale, options?.breaks || []);\n chart.setXScale(brokenXScale);\n }\n },\n onDestroy() {\n if (ctx) {\n const chart = (ctx.chart as any);\n if (originalXScale) {\n chart.setXScale(originalXScale);\n }\n // CLEANUP hijacked methods\n chart.updateSeries = chart._originalUpdateSeries;\n chart.addSeries = chart._originalAddSeries;\n chart.appendData = chart._originalAppendData;\n delete chart._originalUpdateSeries;\n delete chart._originalAddSeries;\n delete chart._originalAppendData;\n }\n ctx = null;\n rawDataStore.clear();\n },\n onRenderOverlay(pCtx) {\n if (config.enabled) drawBreakSymbols(pCtx);\n },\n onViewChange() {\n // Data is warped once against the fixed data-domain; a user zoom/pan is\n // just a linear view over the already-warped buffers, so we must NOT\n // re-warp here (doing so against the transient view domain is exactly\n // what collapsed the chart before). Nothing to do.\n },\n api: pluginApi\n };\n}\n\nexport default PluginBrokenAxis;\n\nexport type {\n PluginBrokenAxisConfig,\n BrokenAxisAPI,\n AxisBreak,\n BrokenAxisOptions,\n} from './types';\n"],"names":["BrokenAxisScale","originalScale","breaks","__publicField","min","max","b","a","segments","current","totalVisibleDataWidth","sum","s","totalBreakVisualRatio","currentRatioOffset","dataWidth","visualWidth","range","nextBreak","value","r0","r1","isReverse","ratio","found","prevRange","r","pixel","visualEnd","i","offset","count","allTicks","visualWeight","segmentCount","segmentTicks","rawStep","magnitude","normalized","step","start","ticks","t","manifest","PluginBrokenAxis","config","ctx","originalXScale","brokenXScale","rawDataStore","computeWarpDomain","raw","v","updateScales","options","applyTransformations","opts","chart","domain","id","transformedX","drawBreakSymbols","pCtx","render","ctx2d","plotArea","axisId","orientation","pxStart","pxEnd","midPx","symbol","drawSymbol","x","y","type","edge","toF32","data","_a","_b","_c","newX","newY","combinedX","combinedY","enabled","wasEnabled","newConfig"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"broken-axis.js","sources":["../../src/plugins/broken-axis/BrokenAxisScale.ts","../../src/core/chart/exporter/svg/plugins/brokenAxis.ts","../../src/plugins/broken-axis/index.ts"],"sourcesContent":["import type { Scale } from \"../../scales\";\nimport type { AxisBreak } from \"./types\";\n\nexport class BrokenAxisScale implements Scale {\n public domain: [number, number] = [0, 1];\n public range: [number, number] = [0, 100];\n public readonly type = \"linear\"; // Compatible with linear for renderer selection\n\n private underlying: Scale;\n private sortedBreaks: AxisBreak[] = [];\n private visibleRanges: { start: number; end: number; pixelOffset: number; pixelScale: number }[] = [];\n private availableVisualRatio: number = 1.0;\n\n constructor(originalScale: Scale, private breaks: AxisBreak[]) {\n this.underlying = originalScale;\n this.domain = [...originalScale.domain];\n this.range = [...originalScale.range];\n this.refresh();\n }\n\n setDomain(min: number, max: number): void {\n this.domain = [min, max];\n this.underlying.setDomain(min, max);\n this.refresh();\n }\n\n setRange(min: number, max: number): void {\n this.range = [min, max];\n this.underlying.setRange(min, max);\n this.refresh();\n }\n\n updateBreaks(breaks: AxisBreak[]) {\n this.breaks = breaks;\n this.refresh();\n }\n\n private refresh() {\n const [min, max] = this.domain;\n \n // 1. Sort and filter breaks within [min, max]\n this.sortedBreaks = this.breaks\n .filter(b => b.start < max && b.end > min)\n .map(b => ({\n ...b,\n start: Math.max(min, b.start),\n end: Math.min(max, b.end),\n visualRatio: b.visualRatio ?? 0.02\n }))\n .sort((a, b) => a.start - b.start);\n\n // 2. Identify visible data segments\n const segments: { start: number; end: number }[] = [];\n let current = min;\n\n for (const b of this.sortedBreaks) {\n if (b.start > current) {\n segments.push({ start: current, end: b.start });\n }\n current = b.end;\n }\n if (current < max) {\n segments.push({ start: current, end: max });\n }\n\n // 3. Calculate total data span of visible segments\n const totalVisibleDataWidth = segments.reduce((sum, s) => sum + (s.end - s.start), 0) || 1e-10;\n const totalBreakVisualRatio = this.sortedBreaks.reduce((sum, b) => sum + (b.visualRatio || 0.02), 0);\n this.availableVisualRatio = Math.max(0.1, 1.0 - totalBreakVisualRatio);\n\n // 4. Calculate mapping for each segment (in 0-1 ratio space)\n let currentRatioOffset = 0;\n this.visibleRanges = segments.map(s => {\n const dataWidth = s.end - s.start;\n const visualWidth = (dataWidth / totalVisibleDataWidth) * this.availableVisualRatio;\n const range = {\n start: s.start,\n end: s.end,\n pixelOffset: currentRatioOffset,\n pixelScale: visualWidth / dataWidth\n };\n \n // Find following break if any to advance offset\n const nextBreak = this.sortedBreaks.find(b => Math.abs(b.start - s.end) < 1e-10);\n currentRatioOffset += visualWidth + (nextBreak?.visualRatio ?? 0);\n \n return range;\n });\n }\n\n transform(value: number): number {\n const [min, max] = this.domain;\n const [r0, r1] = this.range;\n const isReverse = r1 < r0;\n \n let ratio = 0;\n if (value <= min) ratio = 0;\n else if (value >= max) ratio = 1;\n else {\n let found = false;\n // Check visible segments\n for (const range of this.visibleRanges) {\n if (value >= range.start && value <= range.end) {\n ratio = range.pixelOffset + (value - range.start) * range.pixelScale;\n found = true;\n break;\n }\n }\n \n // If in break\n if (!found) {\n for (const b of this.sortedBreaks) {\n if (value >= b.start && value <= b.end) {\n const prevRange = this.visibleRanges.find(r => Math.abs(r.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n ratio = offset + (value - b.start) / (b.end - b.start) * (b.visualRatio ?? 0.02);\n found = true;\n break;\n }\n }\n }\n \n if (!found) ratio = 0;\n }\n\n // Map ratio to pixels\n return isReverse ? r0 - ratio * (r0 - r1) : r0 + ratio * (r1 - r0);\n }\n\n /** Map data value to 0-1 ratio space (handles breaks) */\n mapToRatio(value: number): number {\n const [min, max] = this.domain;\n if (value <= min) return 0;\n if (value >= max) return 1;\n\n for (const range of this.visibleRanges) {\n if (value >= range.start && value <= range.end) {\n return range.pixelOffset + (value - range.start) * range.pixelScale;\n }\n }\n\n for (const b of this.sortedBreaks) {\n if (value >= b.start && value <= b.end) {\n const prevRange = this.visibleRanges.find(r => Math.abs(r.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n return offset + (value - b.start) / (b.end - b.start) * (b.visualRatio ?? 0.02);\n }\n }\n\n return 0;\n }\n\n invert(pixel: number): number {\n const [r0, r1] = this.range;\n const ratio = (pixel - r0) / (r1 - r0);\n \n const r = Math.max(0, Math.min(1, ratio));\n\n for (const range of this.visibleRanges) {\n const visualEnd = range.pixelOffset + (range.end - range.start) * range.pixelScale;\n if (r >= range.pixelOffset && r <= visualEnd) {\n return range.start + (r - range.pixelOffset) / range.pixelScale;\n }\n }\n\n // In break, return nearest segment boundary\n for (let i = 0; i < this.sortedBreaks.length; i++) {\n const b = this.sortedBreaks[i];\n const prevRange = this.visibleRanges.find(range => Math.abs(range.end - b.start) < 1e-10);\n const offset = prevRange ? prevRange.pixelOffset + (prevRange.end - prevRange.start) * prevRange.pixelScale : 0;\n if (r >= offset && r <= offset + (b.visualRatio ?? 0.02)) {\n return b.start;\n }\n }\n\n return this.domain[0];\n }\n\n ticks(count: number = 10): number[] {\n // Generate ticks for each visible segment based on their visual weight\n const allTicks: number[] = [];\n \n for (const range of this.visibleRanges) {\n const visualWeight = (range.end - range.start) / (this.domain[1] - this.domain[0]);\n const segmentCount = Math.max(2, Math.round(count * visualWeight / this.availableVisualRatio));\n \n // Use underlying logic for \"nice\" steps but restricted to this range\n const segmentTicks = this.generateSegmentTicks(range.start, range.end, segmentCount);\n allTicks.push(...segmentTicks);\n }\n\n // Remove duplicates and sort\n return Array.from(new Set(allTicks)).sort((a, b) => a - b);\n }\n\n private generateSegmentTicks(min: number, max: number, count: number): number[] {\n const range = max - min;\n if (range <= 0 || !isFinite(range)) return [];\n \n // Re-use niceStep logic\n const rawStep = range / count;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n let step: number;\n if (normalized < 1.5) step = 1; else if (normalized < 3) step = 2; else if (normalized < 7) step = 5; else step = 10;\n step *= magnitude;\n\n const start = Math.ceil(min / step) * step;\n const ticks: number[] = [];\n let t = start;\n while (t <= max + step * 0.1) {\n ticks.push(Math.round(t * 1e12) / 1e12);\n t += step;\n }\n return ticks;\n }\n}\n","import type { SVGExportPluginContext } from \"./types\";\nimport { fmt } from \"../SVGDocumentBuilder\";\n\ntype BreakSymbol = \"diagonal\" | \"zigzag\" | \"wave\" | \"simple\";\n\nfunction breakSymbolPath(x: number, y: number, type: BreakSymbol, edge: \"top\" | \"bottom\"): string {\n const size = 6;\n if (type === \"diagonal\") {\n return `M ${fmt(x - size)} ${fmt(y + size / 2)} L ${fmt(x + size)} ${fmt(y - size / 2)} M ${fmt(x - size + 3)} ${fmt(y + size / 2)} L ${fmt(x + size + 3)} ${fmt(y - size / 2)}`;\n }\n if (type === \"zigzag\") {\n return `M ${fmt(x - size)} ${fmt(y)} L ${fmt(x - size / 2)} ${fmt(y - size / 2)} L ${fmt(x + size / 2)} ${fmt(y + size / 2)} L ${fmt(x + size)} ${fmt(y)}`;\n }\n if (edge === \"top\" || edge === \"bottom\") {\n return `M ${fmt(x - size)} ${fmt(y - 2)} L ${fmt(x + size)} ${fmt(y + 2)} M ${fmt(x - size)} ${fmt(y - 6)} L ${fmt(x + size)} ${fmt(y - 2)}`;\n }\n return `M ${fmt(x - size)} ${fmt(y)} L ${fmt(x)} ${fmt(y - size)} L ${fmt(x + size)} ${fmt(y)}`;\n}\n\nexport function exportBrokenAxisMarkers(\n ctx: SVGExportPluginContext,\n breaks: Array<{ axis: \"x\" | \"y\"; position: number; style?: BreakSymbol; color?: string }>,\n): void {\n if (!ctx.builder) return;\n const { plotArea } = ctx;\n\n for (const brk of breaks) {\n const color = brk.color ?? ctx.theme.xAxis.lineColor;\n const symbol = brk.style ?? \"diagonal\";\n if (brk.axis === \"x\") {\n const x = ctx.xScale.transform(brk.position);\n const topY = plotArea.y;\n const bottomY = plotArea.y + plotArea.height;\n ctx.builder.push(\n \"plugins\",\n `<path d=\"${breakSymbolPath(x, topY, symbol, \"top\")}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n ctx.builder.push(\n \"plugins\",\n `<path d=\"${breakSymbolPath(x, bottomY, symbol, \"bottom\")}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n } else {\n const yScale = ctx.yScales.values().next().value;\n if (!yScale) continue;\n const y = yScale.transform(brk.position);\n const x = plotArea.x;\n const size = 6;\n ctx.builder.push(\n \"plugins\",\n `<path d=\"M ${fmt(x)} ${fmt(y - size)} L ${fmt(x + size)} ${fmt(y)} L ${fmt(x)} ${fmt(y + size)}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n }\n }\n}\n\n/** Export breaks from PluginBrokenAxis config (data-space start/end). */\nexport function exportBrokenAxisFromConfig(\n ctx: SVGExportPluginContext,\n axes: Record<string, { breaks: Array<{ start: number; end: number; symbol?: BreakSymbol }>; defaultSymbol?: BreakSymbol; symbolColor?: string }>,\n): void {\n const breaks: Array<{ axis: \"x\" | \"y\"; position: number; style?: BreakSymbol; color?: string }> = [];\n\n for (const [axisId, options] of Object.entries(axes)) {\n const horizontal = axisId === \"default\" || axisId === \"xAxis\";\n if (!horizontal) continue;\n for (const b of options.breaks) {\n breaks.push({\n axis: \"x\",\n position: (b.start + b.end) / 2,\n style: b.symbol ?? options.defaultSymbol,\n color: options.symbolColor,\n });\n }\n }\n\n exportBrokenAxisMarkers(ctx, breaks);\n}\n","/**\n * @fileoverview Broken Axis plugin for displaying discontinuous data ranges.\n * @module plugins/broken-axis\n */\n\nimport type {\n PluginBrokenAxisConfig,\n BrokenAxisAPI,\n AxisBreak,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\nimport { BrokenAxisScale } from './BrokenAxisScale';\nimport { exportBrokenAxisFromConfig } from '../../core/chart/exporter/svg/plugins/brokenAxis';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-broken-axis',\n version: '1.0.1',\n description: 'Support for gaps/breaks in axes with visual indicators',\n provides: ['broken-axis', 'coordinate-transform'],\n tags: ['axis', 'layout', 'visualization'],\n};\n\nexport function PluginBrokenAxis(\n config: PluginBrokenAxisConfig = { axes: {} }\n): ChartPlugin<PluginBrokenAxisConfig> {\n // Default enabled to true if not specified\n if (config.enabled === undefined) config.enabled = true;\n \n let ctx: PluginContext | null = null;\n let originalXScale: any = null;\n let brokenXScale: BrokenAxisScale | null = null;\n\n // Storage for raw (un-warped) data of series to allow re-transformation.\n const rawDataStore = new Map<string, { x: Float32Array; y: Float32Array }>();\n\n /** Union X-extent across all stored series — the domain breaks live in. */\n function computeWarpDomain(): [number, number] | null {\n let min = Infinity;\n let max = -Infinity;\n for (const raw of rawDataStore.values()) {\n for (let i = 0; i < raw.x.length; i++) {\n const v = raw.x[i];\n if (v < min) min = v;\n if (v > max) max = v;\n }\n }\n if (!Number.isFinite(min) || !Number.isFinite(max) || min === max) return null;\n return [min, max];\n }\n\n function updateScales() {\n if (!ctx || !config.enabled) return;\n\n const options = config.axes.default || config.axes.xAxis;\n if (options && brokenXScale) {\n brokenXScale.updateBreaks(options.breaks);\n // On break change, we must re-transform everything\n applyTransformations({ syncView: true });\n }\n }\n\n /**\n * Re-warp every stored series into compressed (broken) space using the\n * data-derived warp domain, then align the chart's X view to that domain so\n * the axis ticks and break symbols (which the render pass computes from\n * viewBounds) line up with the warped data.\n */\n function applyTransformations(opts: { syncView?: boolean } = {}) {\n if (!ctx || !brokenXScale || !config.enabled) return;\n const chart = ctx.chart as any;\n\n const domain = computeWarpDomain();\n if (!domain) return;\n const [min, max] = domain;\n const range = max - min || 1;\n\n // Pin the scale to the warp domain so mapToRatio uses the correct segments,\n // independent of whatever sub-range the last render/zoom left behind.\n brokenXScale.setDomain(min, max);\n\n for (const [id, raw] of rawDataStore.entries()) {\n const transformedX = new Float32Array(raw.x.length);\n for (let i = 0; i < raw.x.length; i++) {\n transformedX[i] = min + brokenXScale.mapToRatio(raw.x[i]) * range;\n }\n // Call the TRUE underlying updateSeries to avoid the hijacking loop.\n if (chart._originalUpdateSeries) {\n chart._originalUpdateSeries(id, { x: transformedX, y: raw.y });\n }\n }\n\n if (opts.syncView && typeof chart.zoom === 'function') {\n // Constrain X to the warped data domain (warped values also span\n // [min,max]). Y is left untouched so the caller's Y range is preserved.\n chart.zoom({ x: [min, max], animate: false });\n }\n }\n\n function drawBreakSymbols(pCtx: PluginContext) {\n const { render } = pCtx;\n const { ctx2d, plotArea } = render;\n if (!ctx2d || !brokenXScale) return;\n\n for (const [axisId, options] of Object.entries(config.axes)) {\n const orientation = (axisId === 'default' || axisId === 'xAxis') ? 'horizontal' : 'vertical';\n if (orientation !== 'horizontal') continue;\n\n options.breaks.forEach(b => {\n const pxStart = brokenXScale!.transform(b.start);\n const pxEnd = brokenXScale!.transform(b.end);\n const midPx = (pxStart + pxEnd) / 2;\n // Per-break symbol takes precedence, then the axis default.\n const symbol = b.symbol || options.defaultSymbol || 'diagonal';\n\n ctx2d.save();\n ctx2d.lineWidth = 1.5;\n ctx2d.strokeStyle = options.symbolColor || '#ff00ff';\n\n if (orientation === 'horizontal') {\n drawSymbol(ctx2d, midPx, plotArea.y, symbol, 'top');\n drawSymbol(ctx2d, midPx, plotArea.y + plotArea.height, symbol, 'bottom');\n }\n ctx2d.restore();\n });\n }\n }\n\n function drawSymbol(ctx: CanvasRenderingContext2D, x: number, y: number, type: string, edge: string) {\n const size = 6;\n ctx.beginPath();\n if (type === 'diagonal') {\n ctx.moveTo(x - size, y + size/2);\n ctx.lineTo(x + size, y - size/2);\n ctx.moveTo(x - size + 3, y + size/2);\n ctx.lineTo(x + size + 3, y - size/2);\n } else if (type === 'zigzag') {\n ctx.moveTo(x - size, y);\n ctx.lineTo(x - size/2, y - size/2);\n ctx.lineTo(x + size/2, y + size/2);\n ctx.lineTo(x + size, y);\n } else {\n if (edge === 'top' || edge === 'bottom') {\n ctx.moveTo(x - size, y - 2); ctx.lineTo(x + size, y + 2);\n ctx.moveTo(x - size, y - 6); ctx.lineTo(x + size, y - 2);\n } else {\n ctx.moveTo(x - 2, y - size); ctx.lineTo(x + 2, y + size);\n }\n }\n ctx.stroke();\n }\n\n const api: BrokenAxisAPI = {\n addBreak(axisId, b) {\n if (!config.axes[axisId]) config.axes[axisId] = { breaks: [] };\n config.axes[axisId].breaks.push(b);\n updateScales();\n ctx?.requestRender();\n },\n clearBreaks(axisId) {\n if (config.axes[axisId]) config.axes[axisId].breaks = [];\n updateScales();\n ctx?.requestRender();\n },\n setEnabled(enabled: boolean) {\n const wasEnabled = config.enabled;\n config.enabled = enabled;\n \n if (ctx && wasEnabled !== enabled) {\n const chart = ctx.chart;\n if (enabled) {\n originalXScale = (chart as any).xScale;\n brokenXScale = new BrokenAxisScale(originalXScale, (config.axes.default || config.axes.xAxis)?.breaks || []);\n chart.setXScale(brokenXScale);\n applyTransformations({ syncView: true });\n } else {\n if (originalXScale) {\n chart.setXScale(originalXScale);\n brokenXScale = null;\n // Restore original data to series\n for (const [id, raw] of rawDataStore.entries()) {\n (chart as any)._originalUpdateSeries(id, raw);\n }\n }\n }\n }\n ctx?.requestRender();\n },\n getBreaks(axisId: string): AxisBreak[] {\n return config.axes[axisId]?.breaks || [];\n },\n updateConfig(newConfig: Partial<PluginBrokenAxisConfig>) {\n Object.assign(config, newConfig);\n updateScales();\n ctx?.requestRender();\n }\n };\n\n const pluginApi: BrokenAxisAPI & Record<string, unknown> = api as any;\n\n return {\n manifest,\n onInit(pCtx) {\n ctx = pCtx;\n const chart = ctx.chart as any;\n // NOTE: `chart.brokenAxis` is a read-only getter on ChartCore that resolves\n // this plugin's `api` via the plugin bridge — do NOT assign to it (that\n // throws \"Cannot set property ... which has only a getter\" and aborts\n // plugin registration entirely).\n\n // Hijack and Save original methods\n chart._originalUpdateSeries = chart.updateSeries.bind(chart);\n chart._originalAddSeries = chart.addSeries.bind(chart);\n chart._originalAppendData = chart.appendData.bind(chart);\n\n const toF32 = (v: any): Float32Array =>\n v instanceof Float32Array ? v : new Float32Array(typeof v === 'number' ? [v] : v);\n\n chart.updateSeries = (id: string, data: any) => {\n if (data.x && data.y) {\n rawDataStore.set(id, { x: toF32(data.x), y: toF32(data.y) });\n }\n\n if (config.enabled && brokenXScale && data.x) {\n // Re-warp all series against the (possibly grown) data domain.\n applyTransformations({ syncView: true });\n } else {\n chart._originalUpdateSeries(id, data);\n }\n };\n\n chart.addSeries = (options: any) => {\n if (options.id && options.data?.x && options.data?.y) {\n rawDataStore.set(options.id, { x: toF32(options.data.x), y: toF32(options.data.y) });\n }\n\n if (config.enabled && brokenXScale && options.data?.x) {\n // Add the series (untransformed) so the chart registers it, then\n // warp every series consistently against the data-derived domain.\n chart._originalAddSeries(options);\n applyTransformations({ syncView: true });\n } else {\n chart._originalAddSeries(options);\n }\n };\n\n chart.appendData = (id: string, x: any, y: any) => {\n const raw = rawDataStore.get(id);\n if (raw) {\n const newX = toF32(x);\n const newY = toF32(y);\n const combinedX = new Float32Array(raw.x.length + newX.length);\n const combinedY = new Float32Array(raw.y.length + newY.length);\n combinedX.set(raw.x);\n combinedX.set(newX, raw.x.length);\n combinedY.set(raw.y);\n combinedY.set(newY, raw.y.length);\n rawDataStore.set(id, { x: combinedX, y: combinedY });\n }\n\n if (config.enabled && brokenXScale) {\n applyTransformations({ syncView: true });\n } else {\n chart._originalAppendData(id, x, y);\n }\n };\n\n if (config.enabled) {\n originalXScale = chart.xScale; \n const options = config.axes.default || config.axes.xAxis;\n brokenXScale = new BrokenAxisScale(originalXScale, options?.breaks || []);\n chart.setXScale(brokenXScale);\n }\n },\n onDestroy() {\n if (ctx) {\n const chart = (ctx.chart as any);\n if (originalXScale) {\n chart.setXScale(originalXScale);\n }\n // CLEANUP hijacked methods\n chart.updateSeries = chart._originalUpdateSeries;\n chart.addSeries = chart._originalAddSeries;\n chart.appendData = chart._originalAppendData;\n delete chart._originalUpdateSeries;\n delete chart._originalAddSeries;\n delete chart._originalAppendData;\n }\n ctx = null;\n rawDataStore.clear();\n },\n onRenderOverlay(pCtx) {\n if (config.enabled) drawBreakSymbols(pCtx);\n },\n onExportSVG(svgCtx) {\n if (!config.enabled || !svgCtx.builder || svgCtx.exportContext?.options.includeOverlays === false) return;\n exportBrokenAxisFromConfig(svgCtx, config.axes);\n },\n onViewChange() {\n // Data is warped once against the fixed data-domain; a user zoom/pan is\n // just a linear view over the already-warped buffers, so we must NOT\n // re-warp here (doing so against the transient view domain is exactly\n // what collapsed the chart before). Nothing to do.\n },\n api: pluginApi\n };\n}\n\nexport default PluginBrokenAxis;\n\nexport type {\n PluginBrokenAxisConfig,\n BrokenAxisAPI,\n AxisBreak,\n BrokenAxisOptions,\n} from './types';\n"],"names":["BrokenAxisScale","originalScale","breaks","__publicField","min","max","b","a","segments","current","totalVisibleDataWidth","sum","s","totalBreakVisualRatio","currentRatioOffset","dataWidth","visualWidth","range","nextBreak","value","r0","r1","isReverse","ratio","found","prevRange","r","pixel","visualEnd","i","offset","count","allTicks","visualWeight","segmentCount","segmentTicks","rawStep","magnitude","normalized","step","start","ticks","t","breakSymbolPath","x","y","type","edge","fmt","exportBrokenAxisMarkers","ctx","plotArea","brk","color","symbol","topY","bottomY","yScale","size","exportBrokenAxisFromConfig","axes","axisId","options","manifest","PluginBrokenAxis","config","originalXScale","brokenXScale","rawDataStore","computeWarpDomain","raw","v","updateScales","applyTransformations","opts","chart","domain","id","transformedX","drawBreakSymbols","pCtx","render","ctx2d","orientation","pxStart","pxEnd","midPx","drawSymbol","toF32","data","_a","_b","_c","newX","newY","combinedX","combinedY","svgCtx","enabled","wasEnabled","newConfig"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChartPlugin, PluginFactory, PluginManifest } from './types';
|
|
2
|
+
|
|
3
|
+
export declare function createPlugin<TConfig = void, TApi extends Record<string, unknown> = {}>(definition: ChartPlugin<TConfig> & {
|
|
4
|
+
api?: TApi;
|
|
5
|
+
}): ChartPlugin<TConfig> & {
|
|
6
|
+
api: TApi;
|
|
7
|
+
};
|
|
8
|
+
export declare function createConfigurablePlugin<TConfig = void>(manifest: PluginManifest, factory: (config?: TConfig) => Omit<ChartPlugin<TConfig>, "manifest">): PluginFactory<TConfig>;
|
package/dist/plugins/debug.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var n = (r, e, t) =>
|
|
4
|
-
import { i as f } from "../math-Ddm2EZjj.js";
|
|
5
|
-
import { h as g } from "../utils-Dx0h0bgQ.js";
|
|
1
|
+
var f = Object.defineProperty;
|
|
2
|
+
var g = (r, e, t) => e in r ? f(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var n = (r, e, t) => g(r, typeof e != "symbol" ? e + "" : e, t);
|
|
6
4
|
class u {
|
|
7
5
|
constructor(e, t) {
|
|
8
6
|
n(this, "container");
|
|
@@ -178,10 +176,10 @@ class u {
|
|
|
178
176
|
return isFinite(e) ? Math.abs(e) >= 1e6 || Math.abs(e) < 1e-3 && e !== 0 ? e.toExponential(2) : e.toFixed(3) : e.toString();
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
|
-
function
|
|
179
|
+
function y(r, e) {
|
|
182
180
|
return new u(r, e);
|
|
183
181
|
}
|
|
184
|
-
function
|
|
182
|
+
function w(r) {
|
|
185
183
|
const e = document.querySelector(".velo-plot-container");
|
|
186
184
|
if (!e)
|
|
187
185
|
return console.warn("[VeloPlot] No chart container found for debug overlay"), null;
|
|
@@ -235,36 +233,38 @@ class x {
|
|
|
235
233
|
pointer-events: auto;
|
|
236
234
|
`;
|
|
237
235
|
}
|
|
238
|
-
update(e) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (!
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
236
|
+
async update(e) {
|
|
237
|
+
if (!this.isExpanded) return;
|
|
238
|
+
const { calculateStats: t, integrate: i } = await import("./analysis.js");
|
|
239
|
+
this.content.innerHTML = "", this.series.forEach((s) => {
|
|
240
|
+
if (!s.getVisible()) return;
|
|
241
|
+
const o = s.getData();
|
|
242
|
+
if (!o) return;
|
|
243
|
+
const p = [], h = [];
|
|
244
|
+
for (let l = 0; l < o.x.length; l++)
|
|
245
|
+
o.x[l] >= e.xMin && o.x[l] <= e.xMax && (h.push(o.x[l]), p.push(o.y[l]));
|
|
246
|
+
if (p.length === 0) return;
|
|
247
|
+
const a = t(p), c = i(h, p), m = s.getStyle(), d = document.createElement("div");
|
|
248
248
|
d.style.cssText = `
|
|
249
249
|
padding: 8px 0;
|
|
250
250
|
border-top: 1px solid ${this.isDarkTheme() ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"};
|
|
251
251
|
`, d.innerHTML = `
|
|
252
252
|
<div style="display: flex; align-items: center; gap: 6px; margin-bottom: 4px; font-weight: 600;">
|
|
253
|
-
<div style="width: 8px; height: 8px; border-radius: 2px; background: ${
|
|
254
|
-
${
|
|
253
|
+
<div style="width: 8px; height: 8px; border-radius: 2px; background: ${m.color}"></div>
|
|
254
|
+
${s.getId()}
|
|
255
255
|
</div>
|
|
256
256
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; opacity: 0.9; font-size: 11px;">
|
|
257
|
-
<span>Min: ${
|
|
258
|
-
<span>Max: ${
|
|
259
|
-
<span>Mean: ${
|
|
260
|
-
<span>Count: ${
|
|
261
|
-
<span style="grid-column: span 2;">Area: ${
|
|
257
|
+
<span>Min: ${a.min.toExponential(3)}</span>
|
|
258
|
+
<span>Max: ${a.max.toExponential(3)}</span>
|
|
259
|
+
<span>Mean: ${a.mean.toExponential(3)}</span>
|
|
260
|
+
<span>Count: ${a.count}</span>
|
|
261
|
+
<span style="grid-column: span 2;">Area: ${c.toExponential(4)}</span>
|
|
262
262
|
</div>
|
|
263
263
|
`, this.content.appendChild(d);
|
|
264
|
-
}), this.content.innerHTML === "" && (this.content.innerHTML = "<div style='opacity: 0.5; font-style: italic;'>No series visible in range</div>")
|
|
264
|
+
}), this.content.innerHTML === "" && (this.content.innerHTML = "<div style='opacity: 0.5; font-style: italic;'>No series visible in range</div>");
|
|
265
265
|
}
|
|
266
266
|
toggle() {
|
|
267
|
-
this.isExpanded = !this.isExpanded, this.content.style.display = this.isExpanded ? "block" : "none"
|
|
267
|
+
this.isExpanded = !this.isExpanded, this.content.style.display = this.isExpanded ? "block" : "none";
|
|
268
268
|
}
|
|
269
269
|
updateTheme(e) {
|
|
270
270
|
this.theme = e, this.updateContainerStyle();
|
|
@@ -280,7 +280,7 @@ const v = {
|
|
|
280
280
|
provides: ["ui"],
|
|
281
281
|
tags: ["debug", "performance", "fps", "monitoring"]
|
|
282
282
|
};
|
|
283
|
-
function
|
|
283
|
+
function S(r = {}) {
|
|
284
284
|
let e = null, t = null, i;
|
|
285
285
|
return {
|
|
286
286
|
manifest: v,
|
|
@@ -294,7 +294,7 @@ function F(r = {}) {
|
|
|
294
294
|
}), e.show(), e.setStatsProvider(() => {
|
|
295
295
|
const o = i.data.getAllSeries();
|
|
296
296
|
return {
|
|
297
|
-
pointCount: o.reduce((
|
|
297
|
+
pointCount: o.reduce((h, a) => h + a.getData().x.length, 0),
|
|
298
298
|
seriesCount: o.length,
|
|
299
299
|
viewBounds: i.data.getViewBounds(),
|
|
300
300
|
devicePixelRatio: i.chart.dpr || 1
|
|
@@ -323,9 +323,9 @@ function F(r = {}) {
|
|
|
323
323
|
}
|
|
324
324
|
export {
|
|
325
325
|
u as DebugOverlay,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
326
|
+
S as PluginDebug,
|
|
327
|
+
y as createDebugOverlay,
|
|
328
|
+
S as default,
|
|
329
|
+
w as enableDebugMode
|
|
330
330
|
};
|
|
331
331
|
//# sourceMappingURL=debug.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sources":["../../src/core/debug/index.ts","../../src/core/ChartStatistics.ts","../../src/plugins/debug/index.ts"],"sourcesContent":["/**\n * Velo Plot - Debug Overlay Module\n * \n * Provides a visual debug overlay showing performance metrics,\n * rendering info, and chart state for development and debugging.\n * \n * @module debug\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport interface DebugStats {\n /** Current frames per second */\n fps: number;\n /** Average frame time in ms */\n frameTime: number;\n /** Total number of points being rendered */\n pointCount: number;\n /** Number of visible series */\n seriesCount: number;\n /** Current view bounds */\n viewBounds: {\n xMin: number;\n xMax: number;\n yMin: number;\n yMax: number;\n };\n /** WebGL/WebGPU renderer info */\n rendererInfo: {\n type: 'webgl' | 'webgpu' | 'unknown';\n vendor?: string;\n renderer?: string;\n };\n /** Memory usage estimate (bytes) */\n memoryEstimate: number;\n /** Number of draw calls per frame */\n drawCalls: number;\n /** Whether GPU downsampling is active */\n downsamplingActive: boolean;\n /** Device pixel ratio */\n devicePixelRatio: number;\n /** Canvas dimensions */\n canvasSize: { width: number; height: number };\n /** Plot area dimensions */\n plotArea: { x: number; y: number; width: number; height: number };\n}\n\nexport interface DebugOverlayOptions {\n /** Show FPS counter (default: true) */\n showFps?: boolean;\n /** Show point count (default: true) */\n showPointCount?: boolean;\n /** Show view bounds (default: true) */\n showBounds?: boolean;\n /** Show renderer info (default: true) */\n showRendererInfo?: boolean;\n /** Show memory estimate (default: true) */\n showMemory?: boolean;\n /** Show draw calls (default: true) */\n showDrawCalls?: boolean;\n /** Position: 'top-left', 'top-right', 'bottom-left', 'bottom-right' */\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n /** Background opacity (0-1, default: 0.8) */\n opacity?: number;\n /** Font size in pixels (default: 11) */\n fontSize?: number;\n /** Update interval in ms (default: 250) */\n updateInterval?: number;\n /** Custom CSS class name */\n className?: string;\n}\n\n// ============================================\n// Debug Overlay Implementation\n// ============================================\n\nexport class DebugOverlay {\n private container: HTMLElement;\n private element: HTMLDivElement | null = null;\n private options: Required<DebugOverlayOptions>;\n private visible: boolean = false;\n private updateIntervalId: number | null = null;\n private statsProvider: (() => Partial<DebugStats>) | null = null;\n private lastStats: Partial<DebugStats> = {};\n\n // FPS calculation\n private frameCount: number = 0;\n private lastFpsUpdate: number = 0;\n private currentFps: number = 0;\n private frameTimes: number[] = [];\n\n constructor(container: HTMLElement, options?: DebugOverlayOptions) {\n this.container = container;\n this.options = {\n showFps: true,\n showPointCount: true,\n showBounds: true,\n showRendererInfo: true,\n showMemory: true,\n showDrawCalls: true,\n position: 'top-left',\n opacity: 0.8,\n fontSize: 11,\n updateInterval: 250,\n className: 'velo-plot-debug-overlay',\n ...options,\n };\n }\n\n /**\n * Set the stats provider function\n */\n setStatsProvider(provider: () => Partial<DebugStats>): void {\n this.statsProvider = provider;\n }\n\n /**\n * Record a frame for FPS calculation\n */\n recordFrame(frameTime?: number): void {\n const now = performance.now();\n this.frameCount++;\n\n if (frameTime !== undefined) {\n this.frameTimes.push(frameTime);\n if (this.frameTimes.length > 60) {\n this.frameTimes.shift();\n }\n }\n\n // Update FPS every second\n if (now - this.lastFpsUpdate >= 1000) {\n this.currentFps = Math.round((this.frameCount * 1000) / (now - this.lastFpsUpdate));\n this.frameCount = 0;\n this.lastFpsUpdate = now;\n }\n }\n\n /**\n * Show the debug overlay\n */\n show(): void {\n if (this.visible) return;\n \n this.visible = true;\n this.createElement();\n this.startUpdates();\n }\n\n /**\n * Hide the debug overlay\n */\n hide(): void {\n if (!this.visible) return;\n \n this.visible = false;\n this.stopUpdates();\n this.destroyElement();\n }\n\n /**\n * Toggle visibility\n */\n toggle(): void {\n if (this.visible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Check if visible\n */\n isVisible(): boolean {\n return this.visible;\n }\n\n /**\n * Update the display with new stats\n */\n update(stats?: Partial<DebugStats>): void {\n if (!this.visible || !this.element) return;\n\n // Merge with provider stats\n const providerStats = this.statsProvider?.() || {};\n this.lastStats = {\n ...this.lastStats,\n ...providerStats,\n ...stats,\n fps: this.currentFps,\n frameTime: this.getAverageFrameTime(),\n };\n\n this.renderStats();\n }\n\n /**\n * Get current stats\n */\n getStats(): Partial<DebugStats> {\n return {\n ...this.lastStats,\n fps: this.currentFps,\n frameTime: this.getAverageFrameTime(),\n };\n }\n\n /**\n * Destroy the overlay\n */\n destroy(): void {\n this.hide();\n this.statsProvider = null;\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createElement(): void {\n if (this.element) return;\n\n this.element = document.createElement('div');\n this.element.className = this.options.className;\n \n // Apply styles\n Object.assign(this.element.style, {\n position: 'absolute',\n zIndex: '9999',\n fontFamily: 'monospace',\n fontSize: `${this.options.fontSize}px`,\n lineHeight: '1.4',\n padding: '8px 12px',\n backgroundColor: `rgba(0, 0, 0, ${this.options.opacity})`,\n color: '#00ff00',\n borderRadius: '4px',\n pointerEvents: 'none',\n userSelect: 'none',\n whiteSpace: 'pre',\n ...this.getPositionStyles(),\n });\n\n this.container.style.position = 'relative';\n this.container.appendChild(this.element);\n }\n\n private destroyElement(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n }\n\n private getPositionStyles(): Partial<CSSStyleDeclaration> {\n switch (this.options.position) {\n case 'top-right':\n return { top: '8px', right: '8px' };\n case 'bottom-left':\n return { bottom: '8px', left: '8px' };\n case 'bottom-right':\n return { bottom: '8px', right: '8px' };\n case 'top-left':\n default:\n return { top: '8px', left: '8px' };\n }\n }\n\n private startUpdates(): void {\n if (this.updateIntervalId !== null) return;\n \n this.updateIntervalId = window.setInterval(() => {\n this.update();\n }, this.options.updateInterval);\n }\n\n private stopUpdates(): void {\n if (this.updateIntervalId !== null) {\n clearInterval(this.updateIntervalId);\n this.updateIntervalId = null;\n }\n }\n\n private getAverageFrameTime(): number {\n if (this.frameTimes.length === 0) return 0;\n const sum = this.frameTimes.reduce((a, b) => a + b, 0);\n return sum / this.frameTimes.length;\n }\n\n private renderStats(): void {\n if (!this.element) return;\n\n const lines: string[] = [];\n const stats = this.lastStats;\n\n // FPS\n if (this.options.showFps && stats.fps !== undefined) {\n const fpsColor = stats.fps >= 55 ? '#00ff00' : stats.fps >= 30 ? '#ffff00' : '#ff4444';\n lines.push(`<span style=\"color:${fpsColor}\">FPS: ${stats.fps}</span>`);\n if (stats.frameTime) {\n lines.push(`Frame: ${stats.frameTime.toFixed(2)}ms`);\n }\n }\n\n // Point count\n if (this.options.showPointCount && stats.pointCount !== undefined) {\n lines.push(`Points: ${this.formatNumber(stats.pointCount)}`);\n }\n\n // Series count\n if (stats.seriesCount !== undefined) {\n lines.push(`Series: ${stats.seriesCount}`);\n }\n\n // Draw calls\n if (this.options.showDrawCalls && stats.drawCalls !== undefined) {\n lines.push(`Draw calls: ${stats.drawCalls}`);\n }\n\n // Memory\n if (this.options.showMemory && stats.memoryEstimate !== undefined) {\n lines.push(`Memory: ${this.formatBytes(stats.memoryEstimate)}`);\n }\n\n // Bounds\n if (this.options.showBounds && stats.viewBounds) {\n const b = stats.viewBounds;\n lines.push(`X: [${this.formatValue(b.xMin)}, ${this.formatValue(b.xMax)}]`);\n lines.push(`Y: [${this.formatValue(b.yMin)}, ${this.formatValue(b.yMax)}]`);\n }\n\n // Renderer info\n if (this.options.showRendererInfo && stats.rendererInfo) {\n const info = stats.rendererInfo;\n lines.push(`Renderer: ${info.type.toUpperCase()}`);\n if (info.renderer) {\n // Truncate long renderer names\n const shortRenderer = info.renderer.length > 30 \n ? info.renderer.substring(0, 27) + '...'\n : info.renderer;\n lines.push(`GPU: ${shortRenderer}`);\n }\n }\n\n // Canvas size\n if (stats.canvasSize) {\n lines.push(`Canvas: ${stats.canvasSize.width}×${stats.canvasSize.height}`);\n }\n\n // Downsampling\n if (stats.downsamplingActive !== undefined) {\n lines.push(`Downsampling: ${stats.downsamplingActive ? 'ON' : 'OFF'}`);\n }\n\n // DPR\n if (stats.devicePixelRatio !== undefined) {\n lines.push(`DPR: ${stats.devicePixelRatio}`);\n }\n\n this.element.innerHTML = lines.join('\\n');\n }\n\n private formatNumber(n: number): string {\n if (n >= 1e9) return (n / 1e9).toFixed(1) + 'B';\n if (n >= 1e6) return (n / 1e6).toFixed(1) + 'M';\n if (n >= 1e3) return (n / 1e3).toFixed(1) + 'K';\n return n.toLocaleString();\n }\n\n private formatBytes(bytes: number): string {\n if (bytes >= 1e9) return (bytes / 1e9).toFixed(2) + ' GB';\n if (bytes >= 1e6) return (bytes / 1e6).toFixed(2) + ' MB';\n if (bytes >= 1e3) return (bytes / 1e3).toFixed(2) + ' KB';\n return bytes + ' B';\n }\n\n private formatValue(v: number): string {\n if (!isFinite(v)) return v.toString();\n if (Math.abs(v) >= 1e6 || (Math.abs(v) < 0.001 && v !== 0)) {\n return v.toExponential(2);\n }\n return v.toFixed(3);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a debug overlay for a chart container\n */\nexport function createDebugOverlay(\n container: HTMLElement,\n options?: DebugOverlayOptions\n): DebugOverlay {\n return new DebugOverlay(container, options);\n}\n\n/**\n * Quick enable debug mode (attaches to first chart container found)\n */\nexport function enableDebugMode(options?: DebugOverlayOptions): DebugOverlay | null {\n const container = document.querySelector('.velo-plot-container') as HTMLElement;\n if (!container) {\n console.warn('[VeloPlot] No chart container found for debug overlay');\n return null;\n }\n \n const overlay = new DebugOverlay(container, options);\n overlay.show();\n return overlay;\n}\n","/**\n * ChartStatistics - In-chart statistics panel\n * \n * Displays real-time statistics (Min, Max, Mean, StdDev, Area) \n * for the visible data range of active series.\n */\n\nimport { ChartTheme } from \"../theme\";\nimport { Series } from \"./Series\";\nimport { calculateStats, integrate } from \"../plugins/analysis\";\nimport { Bounds } from \"../types\";\n\nexport class ChartStatistics {\n private container: HTMLDivElement;\n private content: HTMLDivElement;\n private theme: ChartTheme;\n private series: Map<string, Series>;\n private isExpanded = false;\n\n constructor(\n parent: HTMLElement,\n theme: ChartTheme,\n series: Map<string, Series>\n ) {\n this.theme = theme;\n this.series = series;\n\n this.container = document.createElement(\"div\");\n this.container.className = \"velo-plot-stats-panel\";\n this.updateContainerStyle();\n\n const title = document.createElement(\"div\");\n title.innerHTML = \"📊 Statistics\";\n title.style.cssText = `\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n `;\n title.onclick = () => this.toggle();\n\n this.content = document.createElement(\"div\");\n this.content.style.display = \"none\";\n \n this.container.appendChild(title);\n this.container.appendChild(this.content);\n parent.appendChild(this.container);\n }\n\n private isDarkTheme(): boolean {\n const name = this.theme.name.toLowerCase();\n return name.includes(\"dark\") || name.includes(\"midnight\") || name.includes(\"electro\");\n }\n\n private updateContainerStyle(): void {\n const isDark = this.isDarkTheme();\n const bg = isDark ? \"rgba(15, 23, 42, 0.85)\" : \"rgba(255, 255, 255, 0.95)\";\n const color = isDark ? \"#f1f5f9\" : \"#1e293b\";\n const borderColor = isDark ? \"rgba(255, 255, 255, 0.1)\" : \"rgba(0, 0, 0, 0.1)\";\n const shadow = isDark ? \"0 4px 12px rgba(0, 0, 0, 0.5)\" : \"0 4px 12px rgba(0, 0, 0, 0.1)\";\n\n this.container.style.cssText = `\n position: absolute;\n bottom: 8px;\n right: 8px;\n width: 240px;\n background: ${bg};\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 1px solid ${borderColor};\n border-radius: 8px;\n box-shadow: ${shadow};\n color: ${color};\n font-family: system-ui, -apple-system, sans-serif;\n padding: 8px 12px;\n z-index: 90;\n transition: all 0.3s ease;\n font-size: 12px;\n pointer-events: auto;\n `;\n }\n\n public update(viewBounds: Bounds): void {\n if (!this.isExpanded) return;\n\n this.content.innerHTML = \"\";\n \n this.series.forEach((s) => {\n if (!s.getVisible()) return;\n\n const data = s.getData();\n if (!data) return;\n\n // Filter data in visible range\n const visibleY: number[] = [];\n const visibleX: number[] = [];\n for (let i = 0; i < data.x.length; i++) {\n if (data.x[i] >= viewBounds.xMin && data.x[i] <= viewBounds.xMax) {\n visibleX.push(data.x[i]);\n visibleY.push(data.y[i]);\n }\n }\n\n if (visibleY.length === 0) return;\n\n const stats = calculateStats(visibleY);\n const area = integrate(visibleX as any, visibleY as any);\n const style = s.getStyle();\n\n const item = document.createElement(\"div\");\n item.style.cssText = `\n padding: 8px 0;\n border-top: 1px solid ${this.isDarkTheme() ? \"rgba(255,255,255,0.05)\" : \"rgba(0,0,0,0.05)\"};\n `;\n\n item.innerHTML = `\n <div style=\"display: flex; align-items: center; gap: 6px; margin-bottom: 4px; font-weight: 600;\">\n <div style=\"width: 8px; height: 8px; border-radius: 2px; background: ${style.color}\"></div>\n ${s.getId()}\n </div>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 4px; opacity: 0.9; font-size: 11px;\">\n <span>Min: ${stats.min.toExponential(3)}</span>\n <span>Max: ${stats.max.toExponential(3)}</span>\n <span>Mean: ${stats.mean.toExponential(3)}</span>\n <span>Count: ${stats.count}</span>\n <span style=\"grid-column: span 2;\">Area: ${area.toExponential(4)}</span>\n </div>\n `;\n\n this.content.appendChild(item);\n });\n\n if (this.content.innerHTML === \"\") {\n this.content.innerHTML = \"<div style='opacity: 0.5; font-style: italic;'>No series visible in range</div>\";\n }\n }\n\n public toggle(): void {\n this.isExpanded = !this.isExpanded;\n this.content.style.display = this.isExpanded ? \"block\" : \"none\";\n if (this.isExpanded) {\n // Redraw immediately will be handled by the chart's next render\n }\n }\n\n public updateTheme(theme: ChartTheme): void {\n this.theme = theme;\n this.updateContainerStyle();\n }\n\n public destroy(): void {\n this.container.remove();\n }\n}\n","/**\n * VeloPlot Engine - Debug Overlay Plugin\n * \n * Provides performance metrics and debugging information.\n * \n * @module plugins/debug\n */\n\nexport * from \"../../core/debug\";\nimport type { PluginManifest, ChartPlugin, PluginContext, AfterRenderEvent } from \"../types\";\n\nexport interface PluginDebugConfig extends Partial<DebugOverlayOptions> {\n /** Show FPS counter */\n showFPS?: boolean;\n /** Show data stats */\n showDataStats?: boolean;\n}\n\nconst manifestDebug: PluginManifest = {\n name: \"velo-plot-debug\",\n version: \"1.0.0\",\n description: \"Performance monitoring and debugging overlay for velo-plot\",\n provides: [\"ui\"],\n tags: [\"debug\", \"performance\", \"fps\", \"monitoring\"],\n};\n\nimport { DebugOverlay, DebugOverlayOptions } from \"../../core/debug\";\nimport { ChartStatistics } from \"../../core/ChartStatistics\";\n\n/**\n * VeloPlot Debug Plugin\n * \n * Adds a useful overlay with real-time performance metrics and debugging info.\n */\nexport function PluginDebug(config: PluginDebugConfig = {}): ChartPlugin<PluginDebugConfig> {\n let overlay: DebugOverlay | null = null;\n let stats: ChartStatistics | null = null;\n\n let ctx: PluginContext;\n\n return {\n manifest: manifestDebug,\n\n onInit(pCtx: PluginContext) {\n ctx = pCtx;\n\n // Initialize FPS/Performance overlay\n if (config.showFPS !== false) {\n overlay = new DebugOverlay(ctx.ui.container, {\n showFps: true,\n showMemory: true,\n showPointCount: true,\n updateInterval: 500,\n ...config\n });\n overlay.show();\n\n // Set stats provider for more detailed info\n overlay.setStatsProvider(() => {\n const series = ctx.data.getAllSeries();\n const pointCount = series.reduce((sum, s) => sum + s.getData().x.length, 0);\n\n return {\n pointCount,\n seriesCount: series.length,\n viewBounds: ctx.data.getViewBounds(),\n devicePixelRatio: (ctx.chart as any).dpr || 1,\n };\n });\n }\n\n // Initialize data statistics panel\n if (config.showDataStats) {\n stats = new ChartStatistics(\n ctx.ui.container,\n (ctx.chart as any).theme,\n (ctx.chart as any).series\n );\n }\n },\n\n onBeforeRender() {\n if (overlay) {\n overlay.recordFrame();\n }\n },\n\n onAfterRender(_ctx, event: AfterRenderEvent) {\n if (overlay) {\n overlay.update({\n frameTime: (event as any).frameTime || event.renderTime,\n });\n }\n },\n\n onRenderOverlay(_ctx) {\n if (stats) {\n stats.update(ctx.data.getViewBounds());\n }\n },\n\n onDestroy(_ctx: PluginContext) {\n if (overlay) {\n overlay.destroy();\n overlay = null;\n }\n if (stats) {\n stats.destroy();\n stats = null;\n }\n }\n };\n}\n\nexport { DebugOverlay };\nexport default PluginDebug;\n"],"names":["DebugOverlay","container","options","__publicField","provider","frameTime","now","stats","providerStats","_a","a","b","lines","fpsColor","info","shortRenderer","n","bytes","v","createDebugOverlay","enableDebugMode","overlay","ChartStatistics","parent","theme","series","title","name","isDark","bg","color","borderColor","shadow","viewBounds","s","data","visibleY","visibleX","i","calculateStats","area","integrate","style","item","manifestDebug","PluginDebug","config","ctx","pCtx","sum","_ctx","event"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"debug.js","sources":["../../src/core/debug/index.ts","../../src/core/ChartStatistics.ts","../../src/plugins/debug/index.ts"],"sourcesContent":["/**\n * Velo Plot - Debug Overlay Module\n * \n * Provides a visual debug overlay showing performance metrics,\n * rendering info, and chart state for development and debugging.\n * \n * @module debug\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport interface DebugStats {\n /** Current frames per second */\n fps: number;\n /** Average frame time in ms */\n frameTime: number;\n /** Total number of points being rendered */\n pointCount: number;\n /** Number of visible series */\n seriesCount: number;\n /** Current view bounds */\n viewBounds: {\n xMin: number;\n xMax: number;\n yMin: number;\n yMax: number;\n };\n /** WebGL/WebGPU renderer info */\n rendererInfo: {\n type: 'webgl' | 'webgpu' | 'unknown';\n vendor?: string;\n renderer?: string;\n };\n /** Memory usage estimate (bytes) */\n memoryEstimate: number;\n /** Number of draw calls per frame */\n drawCalls: number;\n /** Whether GPU downsampling is active */\n downsamplingActive: boolean;\n /** Device pixel ratio */\n devicePixelRatio: number;\n /** Canvas dimensions */\n canvasSize: { width: number; height: number };\n /** Plot area dimensions */\n plotArea: { x: number; y: number; width: number; height: number };\n}\n\nexport interface DebugOverlayOptions {\n /** Show FPS counter (default: true) */\n showFps?: boolean;\n /** Show point count (default: true) */\n showPointCount?: boolean;\n /** Show view bounds (default: true) */\n showBounds?: boolean;\n /** Show renderer info (default: true) */\n showRendererInfo?: boolean;\n /** Show memory estimate (default: true) */\n showMemory?: boolean;\n /** Show draw calls (default: true) */\n showDrawCalls?: boolean;\n /** Position: 'top-left', 'top-right', 'bottom-left', 'bottom-right' */\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n /** Background opacity (0-1, default: 0.8) */\n opacity?: number;\n /** Font size in pixels (default: 11) */\n fontSize?: number;\n /** Update interval in ms (default: 250) */\n updateInterval?: number;\n /** Custom CSS class name */\n className?: string;\n}\n\n// ============================================\n// Debug Overlay Implementation\n// ============================================\n\nexport class DebugOverlay {\n private container: HTMLElement;\n private element: HTMLDivElement | null = null;\n private options: Required<DebugOverlayOptions>;\n private visible: boolean = false;\n private updateIntervalId: number | null = null;\n private statsProvider: (() => Partial<DebugStats>) | null = null;\n private lastStats: Partial<DebugStats> = {};\n\n // FPS calculation\n private frameCount: number = 0;\n private lastFpsUpdate: number = 0;\n private currentFps: number = 0;\n private frameTimes: number[] = [];\n\n constructor(container: HTMLElement, options?: DebugOverlayOptions) {\n this.container = container;\n this.options = {\n showFps: true,\n showPointCount: true,\n showBounds: true,\n showRendererInfo: true,\n showMemory: true,\n showDrawCalls: true,\n position: 'top-left',\n opacity: 0.8,\n fontSize: 11,\n updateInterval: 250,\n className: 'velo-plot-debug-overlay',\n ...options,\n };\n }\n\n /**\n * Set the stats provider function\n */\n setStatsProvider(provider: () => Partial<DebugStats>): void {\n this.statsProvider = provider;\n }\n\n /**\n * Record a frame for FPS calculation\n */\n recordFrame(frameTime?: number): void {\n const now = performance.now();\n this.frameCount++;\n\n if (frameTime !== undefined) {\n this.frameTimes.push(frameTime);\n if (this.frameTimes.length > 60) {\n this.frameTimes.shift();\n }\n }\n\n // Update FPS every second\n if (now - this.lastFpsUpdate >= 1000) {\n this.currentFps = Math.round((this.frameCount * 1000) / (now - this.lastFpsUpdate));\n this.frameCount = 0;\n this.lastFpsUpdate = now;\n }\n }\n\n /**\n * Show the debug overlay\n */\n show(): void {\n if (this.visible) return;\n \n this.visible = true;\n this.createElement();\n this.startUpdates();\n }\n\n /**\n * Hide the debug overlay\n */\n hide(): void {\n if (!this.visible) return;\n \n this.visible = false;\n this.stopUpdates();\n this.destroyElement();\n }\n\n /**\n * Toggle visibility\n */\n toggle(): void {\n if (this.visible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Check if visible\n */\n isVisible(): boolean {\n return this.visible;\n }\n\n /**\n * Update the display with new stats\n */\n update(stats?: Partial<DebugStats>): void {\n if (!this.visible || !this.element) return;\n\n // Merge with provider stats\n const providerStats = this.statsProvider?.() || {};\n this.lastStats = {\n ...this.lastStats,\n ...providerStats,\n ...stats,\n fps: this.currentFps,\n frameTime: this.getAverageFrameTime(),\n };\n\n this.renderStats();\n }\n\n /**\n * Get current stats\n */\n getStats(): Partial<DebugStats> {\n return {\n ...this.lastStats,\n fps: this.currentFps,\n frameTime: this.getAverageFrameTime(),\n };\n }\n\n /**\n * Destroy the overlay\n */\n destroy(): void {\n this.hide();\n this.statsProvider = null;\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createElement(): void {\n if (this.element) return;\n\n this.element = document.createElement('div');\n this.element.className = this.options.className;\n \n // Apply styles\n Object.assign(this.element.style, {\n position: 'absolute',\n zIndex: '9999',\n fontFamily: 'monospace',\n fontSize: `${this.options.fontSize}px`,\n lineHeight: '1.4',\n padding: '8px 12px',\n backgroundColor: `rgba(0, 0, 0, ${this.options.opacity})`,\n color: '#00ff00',\n borderRadius: '4px',\n pointerEvents: 'none',\n userSelect: 'none',\n whiteSpace: 'pre',\n ...this.getPositionStyles(),\n });\n\n this.container.style.position = 'relative';\n this.container.appendChild(this.element);\n }\n\n private destroyElement(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n }\n\n private getPositionStyles(): Partial<CSSStyleDeclaration> {\n switch (this.options.position) {\n case 'top-right':\n return { top: '8px', right: '8px' };\n case 'bottom-left':\n return { bottom: '8px', left: '8px' };\n case 'bottom-right':\n return { bottom: '8px', right: '8px' };\n case 'top-left':\n default:\n return { top: '8px', left: '8px' };\n }\n }\n\n private startUpdates(): void {\n if (this.updateIntervalId !== null) return;\n \n this.updateIntervalId = window.setInterval(() => {\n this.update();\n }, this.options.updateInterval);\n }\n\n private stopUpdates(): void {\n if (this.updateIntervalId !== null) {\n clearInterval(this.updateIntervalId);\n this.updateIntervalId = null;\n }\n }\n\n private getAverageFrameTime(): number {\n if (this.frameTimes.length === 0) return 0;\n const sum = this.frameTimes.reduce((a, b) => a + b, 0);\n return sum / this.frameTimes.length;\n }\n\n private renderStats(): void {\n if (!this.element) return;\n\n const lines: string[] = [];\n const stats = this.lastStats;\n\n // FPS\n if (this.options.showFps && stats.fps !== undefined) {\n const fpsColor = stats.fps >= 55 ? '#00ff00' : stats.fps >= 30 ? '#ffff00' : '#ff4444';\n lines.push(`<span style=\"color:${fpsColor}\">FPS: ${stats.fps}</span>`);\n if (stats.frameTime) {\n lines.push(`Frame: ${stats.frameTime.toFixed(2)}ms`);\n }\n }\n\n // Point count\n if (this.options.showPointCount && stats.pointCount !== undefined) {\n lines.push(`Points: ${this.formatNumber(stats.pointCount)}`);\n }\n\n // Series count\n if (stats.seriesCount !== undefined) {\n lines.push(`Series: ${stats.seriesCount}`);\n }\n\n // Draw calls\n if (this.options.showDrawCalls && stats.drawCalls !== undefined) {\n lines.push(`Draw calls: ${stats.drawCalls}`);\n }\n\n // Memory\n if (this.options.showMemory && stats.memoryEstimate !== undefined) {\n lines.push(`Memory: ${this.formatBytes(stats.memoryEstimate)}`);\n }\n\n // Bounds\n if (this.options.showBounds && stats.viewBounds) {\n const b = stats.viewBounds;\n lines.push(`X: [${this.formatValue(b.xMin)}, ${this.formatValue(b.xMax)}]`);\n lines.push(`Y: [${this.formatValue(b.yMin)}, ${this.formatValue(b.yMax)}]`);\n }\n\n // Renderer info\n if (this.options.showRendererInfo && stats.rendererInfo) {\n const info = stats.rendererInfo;\n lines.push(`Renderer: ${info.type.toUpperCase()}`);\n if (info.renderer) {\n // Truncate long renderer names\n const shortRenderer = info.renderer.length > 30 \n ? info.renderer.substring(0, 27) + '...'\n : info.renderer;\n lines.push(`GPU: ${shortRenderer}`);\n }\n }\n\n // Canvas size\n if (stats.canvasSize) {\n lines.push(`Canvas: ${stats.canvasSize.width}×${stats.canvasSize.height}`);\n }\n\n // Downsampling\n if (stats.downsamplingActive !== undefined) {\n lines.push(`Downsampling: ${stats.downsamplingActive ? 'ON' : 'OFF'}`);\n }\n\n // DPR\n if (stats.devicePixelRatio !== undefined) {\n lines.push(`DPR: ${stats.devicePixelRatio}`);\n }\n\n this.element.innerHTML = lines.join('\\n');\n }\n\n private formatNumber(n: number): string {\n if (n >= 1e9) return (n / 1e9).toFixed(1) + 'B';\n if (n >= 1e6) return (n / 1e6).toFixed(1) + 'M';\n if (n >= 1e3) return (n / 1e3).toFixed(1) + 'K';\n return n.toLocaleString();\n }\n\n private formatBytes(bytes: number): string {\n if (bytes >= 1e9) return (bytes / 1e9).toFixed(2) + ' GB';\n if (bytes >= 1e6) return (bytes / 1e6).toFixed(2) + ' MB';\n if (bytes >= 1e3) return (bytes / 1e3).toFixed(2) + ' KB';\n return bytes + ' B';\n }\n\n private formatValue(v: number): string {\n if (!isFinite(v)) return v.toString();\n if (Math.abs(v) >= 1e6 || (Math.abs(v) < 0.001 && v !== 0)) {\n return v.toExponential(2);\n }\n return v.toFixed(3);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a debug overlay for a chart container\n */\nexport function createDebugOverlay(\n container: HTMLElement,\n options?: DebugOverlayOptions\n): DebugOverlay {\n return new DebugOverlay(container, options);\n}\n\n/**\n * Quick enable debug mode (attaches to first chart container found)\n */\nexport function enableDebugMode(options?: DebugOverlayOptions): DebugOverlay | null {\n const container = document.querySelector('.velo-plot-container') as HTMLElement;\n if (!container) {\n console.warn('[VeloPlot] No chart container found for debug overlay');\n return null;\n }\n \n const overlay = new DebugOverlay(container, options);\n overlay.show();\n return overlay;\n}\n","/**\n * ChartStatistics - In-chart statistics panel\n */\nimport { ChartTheme } from \"../theme\";\nimport { Series } from \"./Series\";\nimport { Bounds } from \"../types\";\n\nexport class ChartStatistics {\n private container: HTMLDivElement;\n private content: HTMLDivElement;\n private theme: ChartTheme;\n private series: Map<string, Series>;\n private isExpanded = false;\n\n constructor(\n parent: HTMLElement,\n theme: ChartTheme,\n series: Map<string, Series>\n ) {\n this.theme = theme;\n this.series = series;\n\n this.container = document.createElement(\"div\");\n this.container.className = \"velo-plot-stats-panel\";\n this.updateContainerStyle();\n\n const title = document.createElement(\"div\");\n title.innerHTML = \"📊 Statistics\";\n title.style.cssText = `\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n `;\n title.onclick = () => this.toggle();\n\n this.content = document.createElement(\"div\");\n this.content.style.display = \"none\";\n \n this.container.appendChild(title);\n this.container.appendChild(this.content);\n parent.appendChild(this.container);\n }\n\n private isDarkTheme(): boolean {\n const name = this.theme.name.toLowerCase();\n return name.includes(\"dark\") || name.includes(\"midnight\") || name.includes(\"electro\");\n }\n\n private updateContainerStyle(): void {\n const isDark = this.isDarkTheme();\n const bg = isDark ? \"rgba(15, 23, 42, 0.85)\" : \"rgba(255, 255, 255, 0.95)\";\n const color = isDark ? \"#f1f5f9\" : \"#1e293b\";\n const borderColor = isDark ? \"rgba(255, 255, 255, 0.1)\" : \"rgba(0, 0, 0, 0.1)\";\n const shadow = isDark ? \"0 4px 12px rgba(0, 0, 0, 0.5)\" : \"0 4px 12px rgba(0, 0, 0, 0.1)\";\n\n this.container.style.cssText = `\n position: absolute;\n bottom: 8px;\n right: 8px;\n width: 240px;\n background: ${bg};\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n border: 1px solid ${borderColor};\n border-radius: 8px;\n box-shadow: ${shadow};\n color: ${color};\n font-family: system-ui, -apple-system, sans-serif;\n padding: 8px 12px;\n z-index: 90;\n transition: all 0.3s ease;\n font-size: 12px;\n pointer-events: auto;\n `;\n }\n\n public async update(viewBounds: Bounds): Promise<void> {\n if (!this.isExpanded) return;\n\n const { calculateStats, integrate } = await import(\"../plugins/analysis\");\n this.content.innerHTML = \"\";\n \n this.series.forEach((s) => {\n if (!s.getVisible()) return;\n\n const data = s.getData();\n if (!data) return;\n\n const visibleY: number[] = [];\n const visibleX: number[] = [];\n for (let i = 0; i < data.x.length; i++) {\n if (data.x[i] >= viewBounds.xMin && data.x[i] <= viewBounds.xMax) {\n visibleX.push(data.x[i]);\n visibleY.push(data.y[i]);\n }\n }\n\n if (visibleY.length === 0) return;\n\n const stats = calculateStats(visibleY);\n const area = integrate(visibleX as any, visibleY as any);\n const style = s.getStyle();\n\n const item = document.createElement(\"div\");\n item.style.cssText = `\n padding: 8px 0;\n border-top: 1px solid ${this.isDarkTheme() ? \"rgba(255,255,255,0.05)\" : \"rgba(0,0,0,0.05)\"};\n `;\n\n item.innerHTML = `\n <div style=\"display: flex; align-items: center; gap: 6px; margin-bottom: 4px; font-weight: 600;\">\n <div style=\"width: 8px; height: 8px; border-radius: 2px; background: ${style.color}\"></div>\n ${s.getId()}\n </div>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 4px; opacity: 0.9; font-size: 11px;\">\n <span>Min: ${stats.min.toExponential(3)}</span>\n <span>Max: ${stats.max.toExponential(3)}</span>\n <span>Mean: ${stats.mean.toExponential(3)}</span>\n <span>Count: ${stats.count}</span>\n <span style=\"grid-column: span 2;\">Area: ${area.toExponential(4)}</span>\n </div>\n `;\n\n this.content.appendChild(item);\n });\n\n if (this.content.innerHTML === \"\") {\n this.content.innerHTML = \"<div style='opacity: 0.5; font-style: italic;'>No series visible in range</div>\";\n }\n }\n\n public toggle(): void {\n this.isExpanded = !this.isExpanded;\n this.content.style.display = this.isExpanded ? \"block\" : \"none\";\n }\n\n public updateTheme(theme: ChartTheme): void {\n this.theme = theme;\n this.updateContainerStyle();\n }\n\n public destroy(): void {\n this.container.remove();\n }\n}\n","/**\n * VeloPlot Engine - Debug Overlay Plugin\n * \n * Provides performance metrics and debugging information.\n * \n * @module plugins/debug\n */\n\nexport * from \"../../core/debug\";\nimport type { PluginManifest, ChartPlugin, PluginContext, AfterRenderEvent } from \"../types\";\n\nexport interface PluginDebugConfig extends Partial<DebugOverlayOptions> {\n /** Show FPS counter */\n showFPS?: boolean;\n /** Show data stats */\n showDataStats?: boolean;\n}\n\nconst manifestDebug: PluginManifest = {\n name: \"velo-plot-debug\",\n version: \"1.0.0\",\n description: \"Performance monitoring and debugging overlay for velo-plot\",\n provides: [\"ui\"],\n tags: [\"debug\", \"performance\", \"fps\", \"monitoring\"],\n};\n\nimport { DebugOverlay, DebugOverlayOptions } from \"../../core/debug\";\nimport { ChartStatistics } from \"../../core/ChartStatistics\";\n\n/**\n * VeloPlot Debug Plugin\n * \n * Adds a useful overlay with real-time performance metrics and debugging info.\n */\nexport function PluginDebug(config: PluginDebugConfig = {}): ChartPlugin<PluginDebugConfig> {\n let overlay: DebugOverlay | null = null;\n let stats: ChartStatistics | null = null;\n\n let ctx: PluginContext;\n\n return {\n manifest: manifestDebug,\n\n onInit(pCtx: PluginContext) {\n ctx = pCtx;\n\n // Initialize FPS/Performance overlay\n if (config.showFPS !== false) {\n overlay = new DebugOverlay(ctx.ui.container, {\n showFps: true,\n showMemory: true,\n showPointCount: true,\n updateInterval: 500,\n ...config\n });\n overlay.show();\n\n // Set stats provider for more detailed info\n overlay.setStatsProvider(() => {\n const series = ctx.data.getAllSeries();\n const pointCount = series.reduce((sum, s) => sum + s.getData().x.length, 0);\n\n return {\n pointCount,\n seriesCount: series.length,\n viewBounds: ctx.data.getViewBounds(),\n devicePixelRatio: (ctx.chart as any).dpr || 1,\n };\n });\n }\n\n // Initialize data statistics panel\n if (config.showDataStats) {\n stats = new ChartStatistics(\n ctx.ui.container,\n (ctx.chart as any).theme,\n (ctx.chart as any).series\n );\n }\n },\n\n onBeforeRender() {\n if (overlay) {\n overlay.recordFrame();\n }\n },\n\n onAfterRender(_ctx, event: AfterRenderEvent) {\n if (overlay) {\n overlay.update({\n frameTime: (event as any).frameTime || event.renderTime,\n });\n }\n },\n\n onRenderOverlay(_ctx) {\n if (stats) {\n stats.update(ctx.data.getViewBounds());\n }\n },\n\n onDestroy(_ctx: PluginContext) {\n if (overlay) {\n overlay.destroy();\n overlay = null;\n }\n if (stats) {\n stats.destroy();\n stats = null;\n }\n }\n };\n}\n\nexport { DebugOverlay };\nexport default PluginDebug;\n"],"names":["DebugOverlay","container","options","__publicField","provider","frameTime","now","stats","_a","providerStats","a","b","lines","fpsColor","info","shortRenderer","n","bytes","v","createDebugOverlay","enableDebugMode","overlay","ChartStatistics","parent","theme","series","title","name","isDark","bg","color","borderColor","shadow","viewBounds","calculateStats","integrate","data","visibleY","visibleX","i","area","style","item","manifestDebug","PluginDebug","config","ctx","pCtx","sum","s","_ctx","event"],"mappings":";;;AA8EO,MAAMA,EAAa;AAAA,EAexB,YAAYC,GAAwBC,GAA+B;AAd3D,IAAAC,EAAA;AACA,IAAAA,EAAA,iBAAiC;AACjC,IAAAA,EAAA;AACA,IAAAA,EAAA,iBAAmB;AACnB,IAAAA,EAAA,0BAAkC;AAClC,IAAAA,EAAA,uBAAoD;AACpD,IAAAA,EAAA,mBAAiC,CAAA;AAGjC;AAAA,IAAAA,EAAA,oBAAqB;AACrB,IAAAA,EAAA,uBAAwB;AACxB,IAAAA,EAAA,oBAAqB;AACrB,IAAAA,EAAA,oBAAuB,CAAA;AAG7B,SAAK,YAAYF,GACjB,KAAK,UAAU;AAAA,MACb,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,GAAGC;AAAA,IAAA;AAAA,EAEP;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiBE,GAA2C;AAC1D,SAAK,gBAAgBA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAYC,GAA0B;AACpC,UAAMC,IAAM,YAAY,IAAA;AACxB,SAAK,cAEDD,MAAc,WAChB,KAAK,WAAW,KAAKA,CAAS,GAC1B,KAAK,WAAW,SAAS,MAC3B,KAAK,WAAW,MAAA,IAKhBC,IAAM,KAAK,iBAAiB,QAC9B,KAAK,aAAa,KAAK,MAAO,KAAK,aAAa,OAASA,IAAM,KAAK,cAAc,GAClF,KAAK,aAAa,GAClB,KAAK,gBAAgBA;AAAA,EAEzB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,IAAI,KAAK,YAET,KAAK,UAAU,IACf,KAAK,cAAA,GACL,KAAK,aAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,IAAK,KAAK,YAEV,KAAK,UAAU,IACf,KAAK,YAAA,GACL,KAAK,eAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,SAAe;AACb,IAAI,KAAK,UACP,KAAK,KAAA,IAEL,KAAK,KAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,OAAOC,GAAmC;AAzGrC,QAAAC;AA0GH,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,QAAS;AAGpC,UAAMC,MAAgBD,IAAA,KAAK,kBAAL,gBAAAA,EAAA,eAA0B,CAAA;AAChD,SAAK,YAAY;AAAA,MACf,GAAG,KAAK;AAAA,MACR,GAAGC;AAAA,MACH,GAAGF;AAAA,MACH,KAAK,KAAK;AAAA,MACV,WAAW,KAAK,oBAAA;AAAA,IAAoB,GAGtC,KAAK,YAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,WAAgC;AAC9B,WAAO;AAAA,MACL,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV,WAAW,KAAK,oBAAA;AAAA,IAAoB;AAAA,EAExC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,KAAA,GACL,KAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAsB;AAC5B,IAAI,KAAK,YAET,KAAK,UAAU,SAAS,cAAc,KAAK,GAC3C,KAAK,QAAQ,YAAY,KAAK,QAAQ,WAGtC,OAAO,OAAO,KAAK,QAAQ,OAAO;AAAA,MAChC,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,UAAU,GAAG,KAAK,QAAQ,QAAQ;AAAA,MAClC,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,iBAAiB,iBAAiB,KAAK,QAAQ,OAAO;AAAA,MACtD,OAAO;AAAA,MACP,cAAc;AAAA,MACd,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,GAAG,KAAK,kBAAA;AAAA,IAAkB,CAC3B,GAED,KAAK,UAAU,MAAM,WAAW,YAChC,KAAK,UAAU,YAAY,KAAK,OAAO;AAAA,EACzC;AAAA,EAEQ,iBAAuB;AAC7B,IAAI,KAAK,WAAW,KAAK,QAAQ,cAC/B,KAAK,QAAQ,WAAW,YAAY,KAAK,OAAO,GAElD,KAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,oBAAkD;AACxD,YAAQ,KAAK,QAAQ,UAAA;AAAA,MACnB,KAAK;AACH,eAAO,EAAE,KAAK,OAAO,OAAO,MAAA;AAAA,MAC9B,KAAK;AACH,eAAO,EAAE,QAAQ,OAAO,MAAM,MAAA;AAAA,MAChC,KAAK;AACH,eAAO,EAAE,QAAQ,OAAO,OAAO,MAAA;AAAA,MACjC,KAAK;AAAA,MACL;AACE,eAAO,EAAE,KAAK,OAAO,MAAM,MAAA;AAAA,IAAM;AAAA,EAEvC;AAAA,EAEQ,eAAqB;AAC3B,IAAI,KAAK,qBAAqB,SAE9B,KAAK,mBAAmB,OAAO,YAAY,MAAM;AAC/C,WAAK,OAAA;AAAA,IACP,GAAG,KAAK,QAAQ,cAAc;AAAA,EAChC;AAAA,EAEQ,cAAoB;AAC1B,IAAI,KAAK,qBAAqB,SAC5B,cAAc,KAAK,gBAAgB,GACnC,KAAK,mBAAmB;AAAA,EAE5B;AAAA,EAEQ,sBAA8B;AACpC,WAAI,KAAK,WAAW,WAAW,IAAU,IAC7B,KAAK,WAAW,OAAO,CAACG,GAAGC,MAAMD,IAAIC,GAAG,CAAC,IACxC,KAAK,WAAW;AAAA,EAC/B;AAAA,EAEQ,cAAoB;AAC1B,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAMC,IAAkB,CAAA,GAClBL,IAAQ,KAAK;AAGnB,QAAI,KAAK,QAAQ,WAAWA,EAAM,QAAQ,QAAW;AACnD,YAAMM,IAAWN,EAAM,OAAO,KAAK,YAAYA,EAAM,OAAO,KAAK,YAAY;AAC7E,MAAAK,EAAM,KAAK,sBAAsBC,CAAQ,UAAUN,EAAM,GAAG,SAAS,GACjEA,EAAM,aACRK,EAAM,KAAK,UAAUL,EAAM,UAAU,QAAQ,CAAC,CAAC,IAAI;AAAA,IAEvD;AAuBA,QApBI,KAAK,QAAQ,kBAAkBA,EAAM,eAAe,UACtDK,EAAM,KAAK,WAAW,KAAK,aAAaL,EAAM,UAAU,CAAC,EAAE,GAIzDA,EAAM,gBAAgB,UACxBK,EAAM,KAAK,WAAWL,EAAM,WAAW,EAAE,GAIvC,KAAK,QAAQ,iBAAiBA,EAAM,cAAc,UACpDK,EAAM,KAAK,eAAeL,EAAM,SAAS,EAAE,GAIzC,KAAK,QAAQ,cAAcA,EAAM,mBAAmB,UACtDK,EAAM,KAAK,WAAW,KAAK,YAAYL,EAAM,cAAc,CAAC,EAAE,GAI5D,KAAK,QAAQ,cAAcA,EAAM,YAAY;AAC/C,YAAMI,IAAIJ,EAAM;AAChB,MAAAK,EAAM,KAAK,OAAO,KAAK,YAAYD,EAAE,IAAI,CAAC,KAAK,KAAK,YAAYA,EAAE,IAAI,CAAC,GAAG,GAC1EC,EAAM,KAAK,OAAO,KAAK,YAAYD,EAAE,IAAI,CAAC,KAAK,KAAK,YAAYA,EAAE,IAAI,CAAC,GAAG;AAAA,IAC5E;AAGA,QAAI,KAAK,QAAQ,oBAAoBJ,EAAM,cAAc;AACvD,YAAMO,IAAOP,EAAM;AAEnB,UADAK,EAAM,KAAK,aAAaE,EAAK,KAAK,YAAA,CAAa,EAAE,GAC7CA,EAAK,UAAU;AAEjB,cAAMC,IAAgBD,EAAK,SAAS,SAAS,KACzCA,EAAK,SAAS,UAAU,GAAG,EAAE,IAAI,QACjCA,EAAK;AACT,QAAAF,EAAM,KAAK,QAAQG,CAAa,EAAE;AAAA,MACpC;AAAA,IACF;AAGA,IAAIR,EAAM,cACRK,EAAM,KAAK,WAAWL,EAAM,WAAW,KAAK,IAAIA,EAAM,WAAW,MAAM,EAAE,GAIvEA,EAAM,uBAAuB,UAC/BK,EAAM,KAAK,iBAAiBL,EAAM,qBAAqB,OAAO,KAAK,EAAE,GAInEA,EAAM,qBAAqB,UAC7BK,EAAM,KAAK,QAAQL,EAAM,gBAAgB,EAAE,GAG7C,KAAK,QAAQ,YAAYK,EAAM,KAAK;AAAA,CAAI;AAAA,EAC1C;AAAA,EAEQ,aAAaI,GAAmB;AACtC,WAAIA,KAAK,OAAaA,IAAI,KAAK,QAAQ,CAAC,IAAI,MACxCA,KAAK,OAAaA,IAAI,KAAK,QAAQ,CAAC,IAAI,MACxCA,KAAK,OAAaA,IAAI,KAAK,QAAQ,CAAC,IAAI,MACrCA,EAAE,eAAA;AAAA,EACX;AAAA,EAEQ,YAAYC,GAAuB;AACzC,WAAIA,KAAS,OAAaA,IAAQ,KAAK,QAAQ,CAAC,IAAI,QAChDA,KAAS,OAAaA,IAAQ,KAAK,QAAQ,CAAC,IAAI,QAChDA,KAAS,OAAaA,IAAQ,KAAK,QAAQ,CAAC,IAAI,QAC7CA,IAAQ;AAAA,EACjB;AAAA,EAEQ,YAAYC,GAAmB;AACrC,WAAK,SAASA,CAAC,IACX,KAAK,IAAIA,CAAC,KAAK,OAAQ,KAAK,IAAIA,CAAC,IAAI,QAASA,MAAM,IAC/CA,EAAE,cAAc,CAAC,IAEnBA,EAAE,QAAQ,CAAC,IAJOA,EAAE,SAAA;AAAA,EAK7B;AACF;AASO,SAASC,EACdlB,GACAC,GACc;AACd,SAAO,IAAIF,EAAaC,GAAWC,CAAO;AAC5C;AAKO,SAASkB,EAAgBlB,GAAoD;AAClF,QAAMD,IAAY,SAAS,cAAc,sBAAsB;AAC/D,MAAI,CAACA;AACH,mBAAQ,KAAK,uDAAuD,GAC7D;AAGT,QAAMoB,IAAU,IAAIrB,EAAaC,GAAWC,CAAO;AACnD,SAAAmB,EAAQ,KAAA,GACDA;AACT;ACvZO,MAAMC,EAAgB;AAAA,EAO3B,YACEC,GACAC,GACAC,GACA;AAVM,IAAAtB,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,oBAAa;AAOnB,SAAK,QAAQqB,GACb,KAAK,SAASC,GAEd,KAAK,YAAY,SAAS,cAAc,KAAK,GAC7C,KAAK,UAAU,YAAY,yBAC3B,KAAK,qBAAA;AAEL,UAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAY,iBAClBA,EAAM,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAWtBA,EAAM,UAAU,MAAM,KAAK,OAAA,GAE3B,KAAK,UAAU,SAAS,cAAc,KAAK,GAC3C,KAAK,QAAQ,MAAM,UAAU,QAE7B,KAAK,UAAU,YAAYA,CAAK,GAChC,KAAK,UAAU,YAAY,KAAK,OAAO,GACvCH,EAAO,YAAY,KAAK,SAAS;AAAA,EACnC;AAAA,EAEQ,cAAuB;AAC7B,UAAMI,IAAO,KAAK,MAAM,KAAK,YAAA;AAC7B,WAAOA,EAAK,SAAS,MAAM,KAAKA,EAAK,SAAS,UAAU,KAAKA,EAAK,SAAS,SAAS;AAAA,EACtF;AAAA,EAEQ,uBAA6B;AACnC,UAAMC,IAAS,KAAK,YAAA,GACdC,IAAKD,IAAS,2BAA2B,6BACzCE,IAAQF,IAAS,YAAY,WAC7BG,IAAcH,IAAS,6BAA6B,sBACpDI,IAASJ,IAAS,kCAAkC;AAE1D,SAAK,UAAU,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,oBAKfC,CAAE;AAAA;AAAA;AAAA,0BAGIE,CAAW;AAAA;AAAA,oBAEjBC,CAAM;AAAA,eACXF,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlB;AAAA,EAEA,MAAa,OAAOG,GAAmC;AACrD,QAAI,CAAC,KAAK,WAAY;AAEtB,UAAM,EAAE,gBAAAC,GAAgB,WAAAC,MAAc,MAAM,OAAO,eAAqB;AACxE,SAAK,QAAQ,YAAY,IAEzB,KAAK,OAAO,QAAQ,CAAC,MAAM;AACzB,UAAI,CAAC,EAAE,aAAc;AAErB,YAAMC,IAAO,EAAE,QAAA;AACf,UAAI,CAACA,EAAM;AAEX,YAAMC,IAAqB,CAAA,GACrBC,IAAqB,CAAA;AAC3B,eAASC,IAAI,GAAGA,IAAIH,EAAK,EAAE,QAAQG;AACjC,QAAIH,EAAK,EAAEG,CAAC,KAAKN,EAAW,QAAQG,EAAK,EAAEG,CAAC,KAAKN,EAAW,SAC1DK,EAAS,KAAKF,EAAK,EAAEG,CAAC,CAAC,GACvBF,EAAS,KAAKD,EAAK,EAAEG,CAAC,CAAC;AAI3B,UAAIF,EAAS,WAAW,EAAG;AAE3B,YAAM9B,IAAQ2B,EAAeG,CAAQ,GAC/BG,IAAOL,EAAUG,GAAiBD,CAAe,GACjDI,IAAQ,EAAE,SAAA,GAEVC,IAAO,SAAS,cAAc,KAAK;AACzC,MAAAA,EAAK,MAAM,UAAU;AAAA;AAAA,gCAEK,KAAK,gBAAgB,2BAA2B,kBAAkB;AAAA,SAG5FA,EAAK,YAAY;AAAA;AAAA,iFAE0DD,EAAM,KAAK;AAAA,YAChF,EAAE,OAAO;AAAA;AAAA;AAAA,uBAGElC,EAAM,IAAI,cAAc,CAAC,CAAC;AAAA,uBAC1BA,EAAM,IAAI,cAAc,CAAC,CAAC;AAAA,wBACzBA,EAAM,KAAK,cAAc,CAAC,CAAC;AAAA,yBAC1BA,EAAM,KAAK;AAAA,qDACiBiC,EAAK,cAAc,CAAC,CAAC;AAAA;AAAA,SAIpE,KAAK,QAAQ,YAAYE,CAAI;AAAA,IAC/B,CAAC,GAEG,KAAK,QAAQ,cAAc,OAC3B,KAAK,QAAQ,YAAY;AAAA,EAE/B;AAAA,EAEO,SAAe;AACpB,SAAK,aAAa,CAAC,KAAK,YACxB,KAAK,QAAQ,MAAM,UAAU,KAAK,aAAa,UAAU;AAAA,EAC3D;AAAA,EAEO,YAAYlB,GAAyB;AAC1C,SAAK,QAAQA,GACb,KAAK,qBAAA;AAAA,EACP;AAAA,EAEO,UAAgB;AACrB,SAAK,UAAU,OAAA;AAAA,EACjB;AACF;ACpIA,MAAMmB,IAAgC;AAAA,EAClC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,IAAI;AAAA,EACf,MAAM,CAAC,SAAS,eAAe,OAAO,YAAY;AACtD;AAUO,SAASC,EAAYC,IAA4B,IAAoC;AACxF,MAAIxB,IAA+B,MAC/Bd,IAAgC,MAEhCuC;AAEJ,SAAO;AAAA,IACH,UAAUH;AAAA,IAEV,OAAOI,GAAqB;AACxB,MAAAD,IAAMC,GAGFF,EAAO,YAAY,OACnBxB,IAAU,IAAIrB,EAAa8C,EAAI,GAAG,WAAW;AAAA,QACzC,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,GAAGD;AAAA,MAAA,CACN,GACDxB,EAAQ,KAAA,GAGRA,EAAQ,iBAAiB,MAAM;AAC3B,cAAMI,IAASqB,EAAI,KAAK,aAAA;AAGxB,eAAO;AAAA,UACH,YAHerB,EAAO,OAAO,CAACuB,GAAKC,MAAMD,IAAMC,EAAE,QAAA,EAAU,EAAE,QAAQ,CAAC;AAAA,UAItE,aAAaxB,EAAO;AAAA,UACpB,YAAYqB,EAAI,KAAK,cAAA;AAAA,UACrB,kBAAmBA,EAAI,MAAc,OAAO;AAAA,QAAA;AAAA,MAEpD,CAAC,IAIDD,EAAO,kBACPtC,IAAQ,IAAIe;AAAA,QACRwB,EAAI,GAAG;AAAA,QACNA,EAAI,MAAc;AAAA,QAClBA,EAAI,MAAc;AAAA,MAAA;AAAA,IAG/B;AAAA,IAEA,iBAAiB;AACb,MAAIzB,KACAA,EAAQ,YAAA;AAAA,IAEhB;AAAA,IAEA,cAAc6B,GAAMC,GAAyB;AACzC,MAAI9B,KACAA,EAAQ,OAAO;AAAA,QACX,WAAY8B,EAAc,aAAaA,EAAM;AAAA,MAAA,CAChD;AAAA,IAET;AAAA,IAEA,gBAAgBD,GAAM;AAClB,MAAI3C,KACAA,EAAM,OAAOuC,EAAI,KAAK,cAAA,CAAe;AAAA,IAE7C;AAAA,IAEA,UAAUI,GAAqB;AACvB,MAAI7B,MACJA,EAAQ,QAAA,GACRA,IAAU,OAEVd,MACAA,EAAM,QAAA,GACNA,IAAQ;AAAA,IAEhB;AAAA,EAAA;AAER;"}
|