velo-plot 1.11.1 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +35 -2
  2. package/dist/{index.core-CYu3tydL.js → ChartCore-BimVvUEg.js} +1936 -1588
  3. package/dist/ChartCore-BimVvUEg.js.map +1 -0
  4. package/dist/axisFormat-B7o_uIEA.js +127 -0
  5. package/dist/axisFormat-B7o_uIEA.js.map +1 -0
  6. package/dist/core/OverlayRenderer.d.ts +1 -2
  7. package/dist/core/chart/ChartCore.d.ts +18 -1
  8. package/dist/core/chart/ChartRenderLoop.d.ts +4 -0
  9. package/dist/core/chart/ChartScaling.d.ts +11 -0
  10. package/dist/core/chart/NavigationUtils.d.ts +12 -0
  11. package/dist/core/chart/exporter/SVGExporter.d.ts +7 -2
  12. package/dist/core/chart/types.d.ts +13 -1
  13. package/dist/core/format/axisFormat.d.ts +16 -0
  14. package/dist/core/indicator/buildIndicatorPane.d.ts +22 -0
  15. package/dist/core/indicator/buildIndicatorSeries.d.ts +14 -0
  16. package/dist/core/indicator/index.d.ts +3 -0
  17. package/dist/core/indicator/types.d.ts +74 -0
  18. package/dist/core/render/pixelSnap.d.ts +8 -0
  19. package/dist/core/series/SeriesBounds.d.ts +1 -1
  20. package/dist/core/stacked/createStackedChart.d.ts +3 -0
  21. package/dist/core/stacked/index.d.ts +6 -0
  22. package/dist/core/stacked/paneAxis.d.ts +20 -0
  23. package/dist/core/stacked/paneResize.d.ts +29 -0
  24. package/dist/core/stacked/stackExport.d.ts +18 -0
  25. package/dist/core/stacked/types.d.ts +120 -0
  26. package/dist/core/sync/index.d.ts +25 -70
  27. package/dist/createStackedChart-CjsKcOvX.js +1088 -0
  28. package/dist/createStackedChart-CjsKcOvX.js.map +1 -0
  29. package/dist/index-CUGS98p4.js +277 -0
  30. package/dist/index-CUGS98p4.js.map +1 -0
  31. package/dist/index-ChgIdk3N.js +229 -0
  32. package/dist/index-ChgIdk3N.js.map +1 -0
  33. package/dist/{index-D8ifudJH.js → index-DjeWClO9.js} +601 -561
  34. package/dist/index-DjeWClO9.js.map +1 -0
  35. package/dist/index.core-C_-CFftD.js +167 -0
  36. package/dist/index.core-C_-CFftD.js.map +1 -0
  37. package/dist/index.d.ts +2 -0
  38. package/dist/math-Ddm2EZjj.js +85 -0
  39. package/dist/math-Ddm2EZjj.js.map +1 -0
  40. package/dist/plugins/analysis.js +132 -130
  41. package/dist/plugins/analysis.js.map +1 -1
  42. package/dist/plugins/anomaly-detection.d.ts +1 -0
  43. package/dist/plugins/anomaly-detection.js +221 -0
  44. package/dist/plugins/anomaly-detection.js.map +1 -0
  45. package/dist/plugins/broken-axis.d.ts +3 -0
  46. package/dist/plugins/broken-axis.js +262 -0
  47. package/dist/plugins/broken-axis.js.map +1 -0
  48. package/dist/plugins/caching.d.ts +3 -0
  49. package/dist/plugins/caching.js +182 -0
  50. package/dist/plugins/caching.js.map +1 -0
  51. package/dist/plugins/data-transform.d.ts +3 -0
  52. package/dist/plugins/data-transform.js +146 -0
  53. package/dist/plugins/data-transform.js.map +1 -0
  54. package/dist/plugins/debug.js +12 -11
  55. package/dist/plugins/debug.js.map +1 -1
  56. package/dist/plugins/forecasting.d.ts +1 -0
  57. package/dist/plugins/forecasting.js +236 -0
  58. package/dist/plugins/forecasting.js.map +1 -0
  59. package/dist/plugins/latex.d.ts +1 -0
  60. package/dist/plugins/latex.js +454 -0
  61. package/dist/plugins/latex.js.map +1 -0
  62. package/dist/plugins/lazy-load.d.ts +3 -0
  63. package/dist/plugins/lazy-load.js +189 -0
  64. package/dist/plugins/lazy-load.js.map +1 -0
  65. package/dist/plugins/ml-integration.d.ts +3 -0
  66. package/dist/plugins/ml-integration.js +355 -0
  67. package/dist/plugins/ml-integration.js.map +1 -0
  68. package/dist/plugins/offscreen.d.ts +3 -0
  69. package/dist/plugins/offscreen.js +169 -0
  70. package/dist/plugins/offscreen.js.map +1 -0
  71. package/dist/plugins/pattern-recognition.d.ts +3 -0
  72. package/dist/plugins/pattern-recognition.js +690 -0
  73. package/dist/plugins/pattern-recognition.js.map +1 -0
  74. package/dist/plugins/radar.d.ts +3 -0
  75. package/dist/plugins/radar.js +103 -0
  76. package/dist/plugins/radar.js.map +1 -0
  77. package/dist/plugins/regression.d.ts +3 -0
  78. package/dist/plugins/regression.js +634 -0
  79. package/dist/plugins/regression.js.map +1 -0
  80. package/dist/plugins/roi.d.ts +1 -0
  81. package/dist/plugins/roi.js +223 -0
  82. package/dist/plugins/roi.js.map +1 -0
  83. package/dist/plugins/snapshot/types.d.ts +1 -1
  84. package/dist/plugins/snapshot.d.ts +3 -0
  85. package/dist/plugins/snapshot.js +90 -0
  86. package/dist/plugins/snapshot.js.map +1 -0
  87. package/dist/plugins/sync/index.d.ts +2 -1
  88. package/dist/plugins/sync.js +12 -244
  89. package/dist/plugins/sync.js.map +1 -1
  90. package/dist/plugins/tools/tooltip/TooltipManager.d.ts +9 -1
  91. package/dist/plugins/tools/tooltip/format.d.ts +7 -0
  92. package/dist/plugins/tools/tooltip/types.d.ts +6 -8
  93. package/dist/plugins/tools.js +1 -1
  94. package/dist/plugins/video-recorder.d.ts +3 -0
  95. package/dist/plugins/video-recorder.js +104 -0
  96. package/dist/plugins/video-recorder.js.map +1 -0
  97. package/dist/plugins/virtualization.d.ts +3 -0
  98. package/dist/plugins/virtualization.js +6 -0
  99. package/dist/plugins/virtualization.js.map +1 -0
  100. package/dist/react/index.d.ts +2 -1
  101. package/dist/react/useStackedPlot.d.ts +17 -0
  102. package/dist/react.d.ts +1 -0
  103. package/dist/react.js +31 -0
  104. package/dist/react.js.map +1 -0
  105. package/dist/types.d.ts +21 -1
  106. package/dist/utils-BK5UUXxj.js +172 -0
  107. package/dist/utils-BK5UUXxj.js.map +1 -0
  108. package/dist/velo-plot.full.js +1000 -5576
  109. package/dist/velo-plot.full.js.map +1 -1
  110. package/dist/velo-plot.js +23 -22
  111. package/dist/velo-plot.js.map +1 -1
  112. package/package.json +17 -3
  113. package/dist/EventEmitter-DAbs2K1C.js +0 -60
  114. package/dist/EventEmitter-DAbs2K1C.js.map +0 -1
  115. package/dist/index-D8ifudJH.js.map +0 -1
  116. package/dist/index.core-CYu3tydL.js.map +0 -1
  117. package/dist/utils-Dbro9-qM.js +0 -254
  118. package/dist/utils-Dbro9-qM.js.map +0 -1
@@ -1,250 +1,18 @@
1
- var h = Object.defineProperty;
2
- var l = (o, t, s) => t in o ? h(o, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : o[t] = s;
3
- var a = (o, t, s) => l(o, typeof t != "symbol" ? t + "" : t, s);
4
- class c {
5
- constructor(t) {
6
- a(this, "charts", /* @__PURE__ */ new Map());
7
- a(this, "options");
8
- a(this, "eventHandlers", /* @__PURE__ */ new Map());
9
- a(this, "isUpdating", !1);
10
- a(this, "debounceTimers", /* @__PURE__ */ new Map());
11
- this.options = {
12
- axis: "x",
13
- syncCursor: !0,
14
- syncSelection: !1,
15
- syncZoom: !0,
16
- syncPan: !0,
17
- debounce: 0,
18
- bidirectional: !0,
19
- ...t
20
- };
21
- }
22
- /**
23
- * Add a chart to the group
24
- */
25
- add(t) {
26
- const s = t.getId();
27
- return this.charts.has(s) ? (console.warn(`[ChartGroup] Chart ${s} is already in the group`), this) : (this.charts.set(s, t), this.attachEventHandlers(t), this);
28
- }
29
- /**
30
- * Add multiple charts at once
31
- */
32
- addAll(...t) {
33
- for (const s of t)
34
- this.add(s);
35
- return this;
36
- }
37
- /**
38
- * Remove a chart from the group
39
- */
40
- remove(t) {
41
- const s = t.getId();
42
- return this.charts.has(s) ? (this.detachEventHandlers(t), this.charts.delete(s), this) : this;
43
- }
44
- /**
45
- * Get all charts in the group
46
- */
47
- getCharts() {
48
- return Array.from(this.charts.values());
49
- }
50
- /**
51
- * Get chart count
52
- */
53
- size() {
54
- return this.charts.size;
55
- }
56
- /**
57
- * Check if a chart is in the group
58
- */
59
- has(t) {
60
- return this.charts.has(t.getId());
61
- }
62
- /**
63
- * Set synchronization axis
64
- */
65
- syncAxis(t) {
66
- return this.options.axis = t, this;
67
- }
68
- /**
69
- * Enable/disable cursor synchronization
70
- */
71
- syncCursor(t) {
72
- return this.options.syncCursor = t, this;
73
- }
74
- /**
75
- * Enable/disable selection synchronization
76
- */
77
- syncSelection(t) {
78
- return this.options.syncSelection = t, this;
79
- }
80
- /**
81
- * Synchronize all charts to a specific view
82
- */
83
- syncTo(t, s) {
84
- this.propagateZoom(s || "", t);
85
- }
86
- /**
87
- * Reset all charts to auto-scale
88
- */
89
- resetAll() {
90
- for (const t of this.charts.values())
91
- t.zoom({ x: void 0, y: void 0 });
92
- }
93
- /**
94
- * Clear all selections in the group
95
- */
96
- clearAllSelections() {
97
- var t;
98
- for (const s of this.charts.values())
99
- (t = s.clearSelection) == null || t.call(s);
100
- }
101
- /**
102
- * Destroy the group and cleanup
103
- */
104
- destroy() {
105
- for (const t of this.charts.values())
106
- this.detachEventHandlers(t);
107
- this.charts.clear(), this.eventHandlers.clear();
108
- for (const t of this.debounceTimers.values())
109
- clearTimeout(t);
110
- this.debounceTimers.clear();
111
- }
112
- // ============================================
113
- // Private Methods
114
- // ============================================
115
- attachEventHandlers(t) {
116
- const s = t.getId(), i = /* @__PURE__ */ new Map();
117
- if (this.options.syncZoom) {
118
- const n = (...e) => {
119
- const r = e[0];
120
- this.handleZoom(s, r);
121
- };
122
- t.on("zoom", n), i.set("zoom", n);
123
- }
124
- if (this.options.syncPan) {
125
- const n = (...e) => {
126
- const r = e[0];
127
- this.handlePan(s, r);
128
- };
129
- t.on("pan", n), i.set("pan", n);
130
- }
131
- if (this.options.syncCursor) {
132
- const n = (...e) => {
133
- const r = e[0];
134
- this.handleCursor(s, r);
135
- };
136
- t.on("hover", n), i.set("hover", n);
137
- }
138
- if (this.options.syncSelection) {
139
- const n = (...e) => {
140
- const r = e[0];
141
- this.handleSelection(s, r);
142
- };
143
- t.on("selectionChange", n), i.set("selectionChange", n);
144
- }
145
- this.eventHandlers.set(s, i);
146
- }
147
- detachEventHandlers(t) {
148
- const s = t.getId(), i = this.eventHandlers.get(s);
149
- if (i) {
150
- for (const [n, e] of i.entries())
151
- t.off(n, e);
152
- this.eventHandlers.delete(s);
153
- }
154
- }
155
- handleZoom(t, s) {
156
- if (this.isUpdating) return;
157
- const i = {};
158
- (this.options.axis === "x" || this.options.axis === "xy") && (i.xMin = s.x[0], i.xMax = s.x[1]), (this.options.axis === "y" || this.options.axis === "xy") && (i.yMin = s.y[0], i.yMax = s.y[1]), this.debounceAction(`zoom-${t}`, () => {
159
- this.propagateZoom(t, i);
160
- });
161
- }
162
- handlePan(t, s) {
163
- if (this.isUpdating) return;
164
- const i = this.options.axis === "x" || this.options.axis === "xy" ? s.deltaX : 0, n = this.options.axis === "y" || this.options.axis === "xy" ? s.deltaY : 0;
165
- i === 0 && n === 0 || this.debounceAction(`pan-${t}`, () => {
166
- this.propagatePan(t, i, n);
167
- });
168
- }
169
- handleCursor(t, s) {
170
- var i, n;
171
- if (!this.isUpdating)
172
- for (const [e, r] of this.charts.entries())
173
- e !== t && (s != null && s.point ? (i = r.setExternalCursor) == null || i.call(r, s.point.x, s.point.y) : (n = r.clearExternalCursor) == null || n.call(r));
174
- }
175
- handleSelection(t, s) {
176
- if (!(this.isUpdating || !this.options.syncSelection))
177
- for (const [i, n] of this.charts.entries())
178
- ;
179
- }
180
- propagateZoom(t, s) {
181
- if (!this.isUpdating) {
182
- this.isUpdating = !0;
183
- try {
184
- for (const [i, n] of this.charts.entries()) {
185
- if (i === t && !this.options.bidirectional || i === t) continue;
186
- const e = {
187
- animate: !1
188
- };
189
- s.xMin !== void 0 && s.xMax !== void 0 && (e.x = [s.xMin, s.xMax]), s.yMin !== void 0 && s.yMax !== void 0 && (e.y = [s.yMin, s.yMax]), n.zoom(e);
190
- }
191
- } finally {
192
- this.isUpdating = !1;
193
- }
194
- }
195
- }
196
- propagatePan(t, s, i) {
197
- if (!this.isUpdating) {
198
- this.isUpdating = !0;
199
- try {
200
- for (const [n, e] of this.charts.entries())
201
- n !== t && e.pan(s, i);
202
- } finally {
203
- this.isUpdating = !1;
204
- }
205
- }
206
- }
207
- debounceAction(t, s) {
208
- if (this.options.debounce <= 0) {
209
- s();
210
- return;
211
- }
212
- const i = this.debounceTimers.get(t);
213
- i && clearTimeout(i);
214
- const n = window.setTimeout(() => {
215
- this.debounceTimers.delete(t), s();
216
- }, this.options.debounce);
217
- this.debounceTimers.set(t, n);
218
- }
219
- }
220
- function d(o, t) {
221
- const s = new c(t);
222
- return s.addAll(...o), s;
223
- }
224
- function p(o, t, s) {
225
- return d([o, t], s);
226
- }
227
- function y(o, t, s = "x") {
228
- return new c({
229
- axis: s,
230
- bidirectional: !1,
231
- syncCursor: !0,
232
- syncZoom: !0,
233
- syncPan: !0
234
- }).addAll(o, t);
235
- }
236
- const u = {
1
+ import { C as c, c as s, a as i, l } from "../index-CUGS98p4.js";
2
+ const n = {
237
3
  name: "velo-plot-sync",
238
4
  version: "1.0.0",
239
5
  description: "Multi-chart synchronization for velo-plot",
240
6
  provides: ["interaction"],
241
7
  tags: ["sync", "multi-chart", "coordination"]
242
8
  };
243
- function x(o = {}) {
9
+ function r(o = {}) {
244
10
  return {
245
- manifest: u,
11
+ manifest: n,
246
12
  onInit(t) {
247
- o.groupId;
13
+ console.warn(
14
+ "[PluginSync] Deprecated: use ChartGroup / createChartGroup from the core sync module instead."
15
+ );
248
16
  },
249
17
  onDestroy(t) {
250
18
  }
@@ -252,10 +20,10 @@ function x(o = {}) {
252
20
  }
253
21
  export {
254
22
  c as ChartGroup,
255
- x as PluginSync,
256
- d as createChartGroup,
257
- y as createMasterSlave,
258
- x as default,
259
- p as linkCharts
23
+ r as PluginSync,
24
+ s as createChartGroup,
25
+ i as createMasterSlave,
26
+ r as default,
27
+ l as linkCharts
260
28
  };
261
29
  //# sourceMappingURL=sync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sources":["../../src/core/sync/index.ts","../../src/plugins/sync/index.ts"],"sourcesContent":["/**\n * Sci Plot - Chart Synchronization Module\n * \n * Provides synchronization between multiple charts:\n * - Synchronized zoom/pan (X, Y, or both)\n * - Shared crosshair cursor\n * - Coordinated selection\n * - Event propagation between linked charts\n * \n * @module sync\n */\n\nimport type { Bounds, Range } from \"../../types\";\n\n// ============================================\n// Types\n// ============================================\n\nexport type SyncAxis = 'x' | 'y' | 'xy' | 'none';\n\nexport interface SyncOptions {\n /** Synchronize axis (default: 'x') */\n axis?: SyncAxis;\n /** Synchronize cursor position (default: true) */\n syncCursor?: boolean;\n /** Synchronize selection state (default: false) */\n syncSelection?: boolean;\n /** Synchronize zoom level (default: true) */\n syncZoom?: boolean;\n /** Synchronize pan (default: true) */\n syncPan?: boolean;\n /** Debounce time for sync events in ms (default: 0) */\n debounce?: number;\n /** Enable bidirectional sync (default: true) */\n bidirectional?: boolean;\n}\n\nexport interface ChartLike {\n /** Unique identifier for the chart */\n getId(): string;\n /** Get current view bounds */\n getViewBounds(): Bounds;\n /** Set view bounds (zoom) */\n zoom(options: { x?: Range; y?: Range; animate?: boolean }): void;\n /** Pan the chart */\n pan(dx: number, dy: number): void;\n /** Get cursor position */\n getCursorPosition?(): { x: number; y: number } | null;\n /** Set external cursor position */\n setExternalCursor?(x: number, y: number): void;\n /** Clear external cursor */\n clearExternalCursor?(): void;\n /** Get selected points */\n getSelectedPoints?(): { seriesId: string; indices: number[] }[];\n /** Set selection */\n selectPoints?(points: { seriesId: string; indices: number[] }[]): void;\n /** Clear selection */\n clearSelection?(): void;\n /** Subscribe to events */\n on(event: string, callback: (...args: unknown[]) => void): void;\n /** Unsubscribe from events */\n off(event: string, callback: (...args: unknown[]) => void): void;\n}\n\nexport interface SyncEvent {\n /** Source chart ID */\n sourceId: string;\n /** Event type */\n type: 'zoom' | 'pan' | 'cursor' | 'selection' | 'bounds';\n /** Event data */\n data: unknown;\n}\n\n// ============================================\n// Chart Group Implementation\n// ============================================\n\nexport class ChartGroup {\n private charts: Map<string, ChartLike> = new Map();\n private options: Required<SyncOptions>;\n private eventHandlers: Map<string, Map<string, (...args: unknown[]) => void>> = new Map();\n private isUpdating: boolean = false;\n private debounceTimers: Map<string, number> = new Map();\n\n constructor(options?: SyncOptions) {\n this.options = {\n axis: 'x',\n syncCursor: true,\n syncSelection: false,\n syncZoom: true,\n syncPan: true,\n debounce: 0,\n bidirectional: true,\n ...options,\n };\n }\n\n /**\n * Add a chart to the group\n */\n add(chart: ChartLike): this {\n const chartId = chart.getId();\n \n if (this.charts.has(chartId)) {\n console.warn(`[ChartGroup] Chart ${chartId} is already in the group`);\n return this;\n }\n\n this.charts.set(chartId, chart);\n this.attachEventHandlers(chart);\n \n return this;\n }\n\n /**\n * Add multiple charts at once\n */\n addAll(...charts: ChartLike[]): this {\n for (const chart of charts) {\n this.add(chart);\n }\n return this;\n }\n\n /**\n * Remove a chart from the group\n */\n remove(chart: ChartLike): this {\n const chartId = chart.getId();\n \n if (!this.charts.has(chartId)) {\n return this;\n }\n\n this.detachEventHandlers(chart);\n this.charts.delete(chartId);\n \n return this;\n }\n\n /**\n * Get all charts in the group\n */\n getCharts(): ChartLike[] {\n return Array.from(this.charts.values());\n }\n\n /**\n * Get chart count\n */\n size(): number {\n return this.charts.size;\n }\n\n /**\n * Check if a chart is in the group\n */\n has(chart: ChartLike): boolean {\n return this.charts.has(chart.getId());\n }\n\n /**\n * Set synchronization axis\n */\n syncAxis(axis: SyncAxis): this {\n this.options.axis = axis;\n return this;\n }\n\n /**\n * Enable/disable cursor synchronization\n */\n syncCursor(enabled: boolean): this {\n this.options.syncCursor = enabled;\n return this;\n }\n\n /**\n * Enable/disable selection synchronization\n */\n syncSelection(enabled: boolean): this {\n this.options.syncSelection = enabled;\n return this;\n }\n\n /**\n * Synchronize all charts to a specific view\n */\n syncTo(bounds: Partial<Bounds>, excludeChartId?: string): void {\n this.propagateZoom(excludeChartId || '', bounds);\n }\n\n /**\n * Reset all charts to auto-scale\n */\n resetAll(): void {\n for (const chart of this.charts.values()) {\n chart.zoom({ x: undefined, y: undefined });\n }\n }\n\n /**\n * Clear all selections in the group\n */\n clearAllSelections(): void {\n for (const chart of this.charts.values()) {\n chart.clearSelection?.();\n }\n }\n\n /**\n * Destroy the group and cleanup\n */\n destroy(): void {\n for (const chart of this.charts.values()) {\n this.detachEventHandlers(chart);\n }\n this.charts.clear();\n this.eventHandlers.clear();\n \n // Clear any pending debounce timers\n for (const timerId of this.debounceTimers.values()) {\n clearTimeout(timerId);\n }\n this.debounceTimers.clear();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private attachEventHandlers(chart: ChartLike): void {\n const chartId = chart.getId();\n const handlers = new Map<string, (...args: unknown[]) => void>();\n\n // Zoom handler\n if (this.options.syncZoom) {\n const zoomHandler = (...args: unknown[]) => {\n const e = args[0] as { x: Range; y: Range };\n this.handleZoom(chartId, e);\n };\n chart.on('zoom', zoomHandler);\n handlers.set('zoom', zoomHandler);\n }\n\n // Pan handler\n if (this.options.syncPan) {\n const panHandler = (...args: unknown[]) => {\n const e = args[0] as { deltaX: number; deltaY: number };\n this.handlePan(chartId, e);\n };\n chart.on('pan', panHandler);\n handlers.set('pan', panHandler);\n }\n\n // Cursor handler\n if (this.options.syncCursor) {\n const hoverHandler = (...args: unknown[]) => {\n const e = args[0] as { point?: { x: number; y: number } } | null;\n this.handleCursor(chartId, e);\n };\n chart.on('hover', hoverHandler);\n handlers.set('hover', hoverHandler);\n }\n\n // Selection handler\n if (this.options.syncSelection) {\n const selectionHandler = (...args: unknown[]) => {\n const e = args[0] as { selected: unknown[] };\n this.handleSelection(chartId, e);\n };\n chart.on('selectionChange', selectionHandler);\n handlers.set('selectionChange', selectionHandler);\n }\n\n this.eventHandlers.set(chartId, handlers);\n }\n\n private detachEventHandlers(chart: ChartLike): void {\n const chartId = chart.getId();\n const handlers = this.eventHandlers.get(chartId);\n \n if (!handlers) return;\n\n for (const [event, handler] of handlers.entries()) {\n chart.off(event, handler);\n }\n\n this.eventHandlers.delete(chartId);\n }\n\n private handleZoom(sourceId: string, event: { x: Range; y: Range }): void {\n if (this.isUpdating) return;\n \n const bounds: Partial<Bounds> = {};\n \n if (this.options.axis === 'x' || this.options.axis === 'xy') {\n bounds.xMin = event.x[0];\n bounds.xMax = event.x[1];\n }\n \n if (this.options.axis === 'y' || this.options.axis === 'xy') {\n bounds.yMin = event.y[0];\n bounds.yMax = event.y[1];\n }\n\n this.debounceAction(`zoom-${sourceId}`, () => {\n this.propagateZoom(sourceId, bounds);\n });\n }\n\n private handlePan(sourceId: string, event: { deltaX: number; deltaY: number }): void {\n if (this.isUpdating) return;\n\n const dx = (this.options.axis === 'x' || this.options.axis === 'xy') ? event.deltaX : 0;\n const dy = (this.options.axis === 'y' || this.options.axis === 'xy') ? event.deltaY : 0;\n\n if (dx === 0 && dy === 0) return;\n\n this.debounceAction(`pan-${sourceId}`, () => {\n this.propagatePan(sourceId, dx, dy);\n });\n }\n\n private handleCursor(sourceId: string, event: { point?: { x: number; y: number } } | null): void {\n if (this.isUpdating) return;\n\n for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n \n if (event?.point) {\n chart.setExternalCursor?.(event.point.x, event.point.y);\n } else {\n chart.clearExternalCursor?.();\n }\n }\n }\n\n private handleSelection(sourceId: string, _event: { selected: unknown[] }): void {\n if (this.isUpdating || !this.options.syncSelection) return;\n\n // Selection sync is more complex - we need to map indices across charts\n // For now, just clear selection on other charts when one changes\n for (const [chartId, _chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n // In a full implementation, you'd map selection by data values\n // For basic sync, we just notify that selection changed\n }\n }\n\n private propagateZoom(sourceId: string, bounds: Partial<Bounds>): void {\n if (this.isUpdating) return;\n \n this.isUpdating = true;\n\n try {\n for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId && !this.options.bidirectional) continue;\n if (chartId === sourceId) continue;\n\n const zoomOptions: { x?: Range; y?: Range; animate?: boolean } = {\n animate: false,\n };\n\n if (bounds.xMin !== undefined && bounds.xMax !== undefined) {\n zoomOptions.x = [bounds.xMin, bounds.xMax];\n }\n\n if (bounds.yMin !== undefined && bounds.yMax !== undefined) {\n zoomOptions.y = [bounds.yMin, bounds.yMax];\n }\n\n chart.zoom(zoomOptions);\n }\n } finally {\n this.isUpdating = false;\n }\n }\n\n private propagatePan(sourceId: string, dx: number, dy: number): void {\n if (this.isUpdating) return;\n \n this.isUpdating = true;\n\n try {\n for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n chart.pan(dx, dy);\n }\n } finally {\n this.isUpdating = false;\n }\n }\n\n private debounceAction(key: string, action: () => void): void {\n if (this.options.debounce <= 0) {\n action();\n return;\n }\n\n // Clear existing timer\n const existingTimer = this.debounceTimers.get(key);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set new timer\n const timerId = window.setTimeout(() => {\n this.debounceTimers.delete(key);\n action();\n }, this.options.debounce);\n\n this.debounceTimers.set(key, timerId);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a chart group with specified charts\n */\nexport function createChartGroup(\n charts: ChartLike[],\n options?: SyncOptions\n): ChartGroup {\n const group = new ChartGroup(options);\n group.addAll(...charts);\n return group;\n}\n\n/**\n * Link two charts for synchronized viewing\n */\nexport function linkCharts(\n chart1: ChartLike,\n chart2: ChartLike,\n options?: SyncOptions\n): ChartGroup {\n return createChartGroup([chart1, chart2], options);\n}\n\n/**\n * Create a master-slave relationship (master controls slave)\n */\nexport function createMasterSlave(\n master: ChartLike,\n slave: ChartLike,\n axis: SyncAxis = 'x'\n): ChartGroup {\n return new ChartGroup({\n axis,\n bidirectional: false,\n syncCursor: true,\n syncZoom: true,\n syncPan: true,\n }).addAll(master, slave);\n}\n","/**\n * SciPlot Engine - Chart Sync Plugin\n * \n * Provides synchronization between multiple chart instances.\n * \n * @module plugins/sync\n */\n\nexport * from \"../../core/sync\";\n\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginSyncConfig {\n /** Group ID to join */\n groupId?: string;\n /** Sync axes: 'x' | 'y' | 'both' */\n syncAxes?: \"x\" | \"y\" | \"both\";\n}\n\nconst manifestSync: PluginManifest = {\n name: \"velo-plot-sync\",\n version: \"1.0.0\",\n description: \"Multi-chart synchronization for velo-plot\",\n provides: [\"interaction\"],\n tags: [\"sync\", \"multi-chart\", \"coordination\"],\n};\n\n/**\n * SciPlot Sync Plugin\n * \n * Enables smooth coordination and synchronization between separate chart instances.\n */\nexport function PluginSync(config: PluginSyncConfig = {}): ChartPlugin<PluginSyncConfig> {\n void config;\n return {\n manifest: manifestSync,\n\n onInit(_ctx: PluginContext) { \n if (config.groupId) {\n // Join the specified group\n }\n },\n\n onDestroy(_ctx: PluginContext) {\n }\n };\n}\n\nexport default PluginSync;\n"],"names":["ChartGroup","options","__publicField","chart","chartId","charts","axis","enabled","bounds","excludeChartId","_a","timerId","handlers","zoomHandler","args","e","panHandler","hoverHandler","selectionHandler","event","handler","sourceId","dx","dy","_b","_event","_chart","zoomOptions","key","action","existingTimer","createChartGroup","group","linkCharts","chart1","chart2","createMasterSlave","master","slave","manifestSync","PluginSync","config","_ctx"],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sources":["../../src/plugins/sync/index.ts"],"sourcesContent":["/**\n * SciPlot Engine - Chart Sync Plugin\n * \n * Provides synchronization between multiple chart instances.\n * \n * @module plugins/sync\n */\n\nexport * from \"../../core/sync\";\n\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginSyncConfig {\n /** Group ID to join */\n groupId?: string;\n /** Sync axes: 'x' | 'y' | 'both' */\n syncAxes?: \"x\" | \"y\" | \"both\";\n}\n\nconst manifestSync: PluginManifest = {\n name: \"velo-plot-sync\",\n version: \"1.0.0\",\n description: \"Multi-chart synchronization for velo-plot\",\n provides: [\"interaction\"],\n tags: [\"sync\", \"multi-chart\", \"coordination\"],\n};\n\n/**\n * SciPlot Sync Plugin\n *\n * @deprecated Use `ChartGroup` / `createChartGroup` from `velo-plot` (or `velo-plot/full`) instead.\n * This plugin stub does not perform synchronization. Kept for backward-compatible imports only.\n */\nexport function PluginSync(config: PluginSyncConfig = {}): ChartPlugin<PluginSyncConfig> {\n void config;\n return {\n manifest: manifestSync,\n\n onInit(_ctx: PluginContext) {\n console.warn(\n \"[PluginSync] Deprecated: use ChartGroup / createChartGroup from the core sync module instead.\",\n );\n },\n\n onDestroy(_ctx: PluginContext) {\n },\n };\n}\n\nexport default PluginSync;\n"],"names":["manifestSync","PluginSync","config","_ctx"],"mappings":";AAmBA,MAAMA,IAA+B;AAAA,EACjC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,aAAa;AAAA,EACxB,MAAM,CAAC,QAAQ,eAAe,cAAc;AAChD;AAQO,SAASC,EAAWC,IAA2B,IAAmC;AAEvF,SAAO;AAAA,IACL,UAAUF;AAAA,IAEV,OAAOG,GAAqB;AAC1B,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,UAAUA,GAAqB;AAAA,IAC/B;AAAA,EAAA;AAEJ;"}
@@ -1,4 +1,4 @@
1
- import { PlotArea, Bounds } from '../../../types';
1
+ import { PlotArea, Bounds, AxisOptions } from '../../../types';
2
2
  import { Scale } from '../../../scales';
3
3
  import { Series } from '../../../core/Series';
4
4
  import { TooltipData, TooltipOptions, TooltipTheme, TooltipTemplate, ShowTooltipOptions, TooltipEventMap } from './types';
@@ -23,6 +23,10 @@ export interface TooltipManagerConfig {
23
23
  getYScales: () => Map<string, Scale>;
24
24
  /** Function to get view bounds */
25
25
  getViewBounds: () => Bounds;
26
+ /** Function to get X axis options */
27
+ getXAxisOptions?: () => AxisOptions;
28
+ /** Function to get Y axis options for a series axis id */
29
+ getYAxisOptions?: (axisId?: string) => AxisOptions | undefined;
26
30
  /** Initial options */
27
31
  options?: TooltipOptions;
28
32
  }
@@ -34,6 +38,9 @@ export declare class TooltipManager {
34
38
  private pixelToDataY;
35
39
  private getXScale;
36
40
  private getYScales;
41
+ private getViewBounds;
42
+ private getXAxisOptions?;
43
+ private getYAxisOptions?;
37
44
  private options;
38
45
  private theme;
39
46
  private positioner;
@@ -131,6 +138,7 @@ export declare class TooltipManager {
131
138
  * Handle heatmap and crosshair tooltip types (fallback)
132
139
  */
133
140
  private performFallbackTooltipUpdate;
141
+ private buildAxisFormat;
134
142
  /**
135
143
  * Find data point by X coordinate only (O(log n) - fastest method)
136
144
  * Best for very large datasets where precision is less important than speed
@@ -0,0 +1,7 @@
1
+ import { DataPointTooltip, CrosshairTooltip } from './types';
2
+
3
+ export declare function formatDataPointX(data: DataPointTooltip): string;
4
+ export declare function formatDataPointY(data: DataPointTooltip): string;
5
+ export declare function formatCrosshairX(data: CrosshairTooltip): string;
6
+ export declare function formatCrosshairY(value: number, data: CrosshairTooltip): string;
7
+ export declare function formatCompactValue(data: DataPointTooltip, axis: "x" | "y"): string;
@@ -1,11 +1,5 @@
1
- /**
2
- * Tooltip System - Type Definitions
3
- *
4
- * This module defines all types and interfaces for the high-performance
5
- * tooltip system in Sci Plot.
6
- *
7
- * @module tooltip/types
8
- */
1
+ import { TooltipAxisFormat } from '../../../core/format/axisFormat';
2
+
9
3
  /** Base type for all tooltip data */
10
4
  export type TooltipType = 'datapoint' | 'crosshair' | 'range' | 'annotation' | 'heatmap' | 'axis';
11
5
  /** Union type for all tooltip data structures */
@@ -37,6 +31,8 @@ export interface DataPointTooltip {
37
31
  xError?: [number, number];
38
32
  /** Cycle number (for CV data) */
39
33
  cycle?: number;
34
+ /** Axis formatting context aligned with chart tick formatters */
35
+ axisFormat?: TooltipAxisFormat;
40
36
  /** Custom metadata from series */
41
37
  metadata?: Record<string, unknown>;
42
38
  }
@@ -53,6 +49,8 @@ export interface CrosshairTooltip {
53
49
  dataX: number;
54
50
  /** Interpolated values for each visible series */
55
51
  interpolatedValues: CrosshairSeriesValue[];
52
+ /** Axis formatting context aligned with chart tick formatters */
53
+ axisFormat?: TooltipAxisFormat;
56
54
  }
57
55
  export interface CrosshairSeriesValue {
58
56
  /** Series ID */
@@ -1,4 +1,4 @@
1
- import { D as l, b as s, P as e, T, P as t } from "../index-D8ifudJH.js";
1
+ import { D as l, b as s, P as e, T, P as t } from "../index-DjeWClO9.js";
2
2
  export {
3
3
  l as DeltaTool,
4
4
  s as PeakTool,
@@ -0,0 +1,3 @@
1
+ export * from './video-recorder/index'
2
+ import SciPlot from './video-recorder/index'
3
+ export default SciPlot
@@ -0,0 +1,104 @@
1
+ const w = {
2
+ name: "velo-plot-video-recorder",
3
+ version: "1.0.0",
4
+ description: "Capture chart animations and export to video files",
5
+ provides: ["video-export", "media-tools"],
6
+ tags: ["export", "video", "animation"]
7
+ }, R = {
8
+ format: "webm",
9
+ fps: 30,
10
+ bitrate: 25e5,
11
+ fillBackground: !0,
12
+ backgroundColor: "#ffffff",
13
+ quality: 0.9,
14
+ autoDownload: !1,
15
+ filename: "chart-recording",
16
+ debug: !1
17
+ };
18
+ function F(b = {}) {
19
+ const a = { ...R, ...b };
20
+ let s = null, t = null, m = [], r = !1, l = !1, n = null, d = null, o = null;
21
+ function h() {
22
+ var i;
23
+ if (!s) return;
24
+ const e = (i = s.render.gl) == null ? void 0 : i.canvas;
25
+ e && (n = document.createElement("canvas"), n.width = e.width, n.height = e.height, d = n.getContext("2d"));
26
+ }
27
+ function u() {
28
+ var c, f, p, g, v;
29
+ if (!s || !d || !n) return;
30
+ const e = (c = s.render.gl) == null ? void 0 : c.canvas, i = (f = s.render.ctx2d) == null ? void 0 : f.canvas;
31
+ a.fillBackground ? (d.fillStyle = a.backgroundColor || ((v = (g = (p = s.chart).getTheme) == null ? void 0 : g.call(p)) == null ? void 0 : v.background) || "#ffffff", d.fillRect(0, 0, n.width, n.height)) : d.clearRect(0, 0, n.width, n.height), e && d.drawImage(e, 0, 0), i && d.drawImage(i, 0, 0), r && !l && (o && cancelAnimationFrame(o), o = requestAnimationFrame(u));
32
+ }
33
+ return {
34
+ manifest: w,
35
+ onInit(e) {
36
+ s = e;
37
+ },
38
+ onDestroy() {
39
+ r && (t == null || t.stop(), o && cancelAnimationFrame(o)), s = null;
40
+ },
41
+ api: {
42
+ start() {
43
+ if (r || !s) return;
44
+ if (h(), !n) {
45
+ console.error("[VideoRecorder] Could not initialize capture canvas");
46
+ return;
47
+ }
48
+ m = [];
49
+ const e = n.captureStream(a.fps), i = {
50
+ mimeType: a.format === "mp4" ? "video/mp4;codecs=h264" : "video/webm;codecs=vp9",
51
+ videoBitsPerSecond: a.bitrate
52
+ };
53
+ MediaRecorder.isTypeSupported(i.mimeType) || (i.mimeType = "video/webm");
54
+ try {
55
+ t = new MediaRecorder(e, i), t.ondataavailable = (c) => {
56
+ c.data.size > 0 && m.push(c.data);
57
+ }, t.onstop = () => {
58
+ r = !1, o && cancelAnimationFrame(o);
59
+ }, r = !0, l = !1, t.start(100), o && cancelAnimationFrame(o), u(), a.debug && console.log("[VideoRecorder] Recording started");
60
+ } catch (c) {
61
+ console.error("[VideoRecorder] Failed to start MediaRecorder:", c);
62
+ }
63
+ },
64
+ async stop() {
65
+ return new Promise((e) => {
66
+ if (!t || !r) {
67
+ e(new Blob([], { type: "video/webm" }));
68
+ return;
69
+ }
70
+ t.onstop = () => {
71
+ const i = new Blob(m, {
72
+ type: a.format === "mp4" ? "video/mp4" : "video/webm"
73
+ });
74
+ if (a.autoDownload) {
75
+ const c = URL.createObjectURL(i), f = document.createElement("a");
76
+ f.href = c, f.download = `${a.filename}.${a.format}`, f.click(), setTimeout(() => URL.revokeObjectURL(c), 100);
77
+ }
78
+ e(i), r = !1, o && cancelAnimationFrame(o), a.debug && console.log("[VideoRecorder] Recording stopped, size:", i.size);
79
+ }, t.stop();
80
+ });
81
+ },
82
+ pause() {
83
+ t && r && !l && (t.pause(), l = !0);
84
+ },
85
+ resume() {
86
+ t && r && l && (t.resume(), l = !1, o && cancelAnimationFrame(o), u());
87
+ },
88
+ isRecording() {
89
+ return r;
90
+ },
91
+ isPaused() {
92
+ return l;
93
+ },
94
+ updateConfig(e) {
95
+ Object.assign(a, e);
96
+ }
97
+ }
98
+ };
99
+ }
100
+ export {
101
+ F as PluginVideoRecorder,
102
+ F as default
103
+ };
104
+ //# sourceMappingURL=video-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-recorder.js","sources":["../../src/plugins/video-recorder/index.ts"],"sourcesContent":["/**\n * @fileoverview Video Recorder plugin for capturing chart animations.\n * @module plugins/video-recorder\n */\n\nimport type {\n PluginVideoRecorderConfig,\n VideoRecorderAPI,\n VideoRecorderOptions,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-video-recorder',\n version: '1.0.0',\n description: 'Capture chart animations and export to video files',\n provides: ['video-export', 'media-tools'],\n tags: ['export', 'video', 'animation'],\n};\n\nconst DEFAULT_CONFIG: Required<PluginVideoRecorderConfig> = {\n format: 'webm',\n fps: 30,\n bitrate: 2500000,\n fillBackground: true,\n backgroundColor: '#ffffff',\n quality: 0.9,\n autoDownload: false,\n filename: 'chart-recording',\n debug: false,\n};\n\nexport function PluginVideoRecorder(\n userConfig: Partial<PluginVideoRecorderConfig> = {}\n): ChartPlugin<PluginVideoRecorderConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n \n let mediaRecorder: MediaRecorder | null = null;\n let recordedChunks: Blob[] = [];\n let isRecording = false;\n let isPaused = false;\n \n // Composite canvas for capturing both WebGL and Overlay\n let compositeCanvas: HTMLCanvasElement | null = null;\n let compositeCtx: CanvasRenderingContext2D | null = null;\n let animationFrameId: number | null = null;\n\n function createCompositeCanvas() {\n if (!ctx) return;\n \n // Get canvases from the rendering context\n const mainCanvas = ctx.render.gl?.canvas as HTMLCanvasElement;\n \n if (!mainCanvas) return;\n\n compositeCanvas = document.createElement('canvas');\n compositeCanvas.width = mainCanvas.width;\n compositeCanvas.height = mainCanvas.height;\n compositeCtx = compositeCanvas.getContext('2d');\n }\n\n function updateComposite() {\n if (!ctx || !compositeCtx || !compositeCanvas) return;\n \n const mainCanvas = ctx.render.gl?.canvas as HTMLCanvasElement;\n const overlayCanvas = ctx.render.ctx2d?.canvas as HTMLCanvasElement;\n \n // Clear/Background\n if (config.fillBackground) {\n compositeCtx.fillStyle = config.backgroundColor || (ctx.chart as any).getTheme?.()?.background || '#ffffff';\n compositeCtx.fillRect(0, 0, compositeCanvas.width, compositeCanvas.height);\n } else {\n compositeCtx.clearRect(0, 0, compositeCanvas.width, compositeCanvas.height);\n }\n\n // Draw all chart canvases in order\n if (mainCanvas) compositeCtx.drawImage(mainCanvas, 0, 0);\n if (overlayCanvas) compositeCtx.drawImage(overlayCanvas, 0, 0);\n\n if (isRecording && !isPaused) {\n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n animationFrameId = requestAnimationFrame(updateComposite);\n }\n }\n\n const api: VideoRecorderAPI = {\n start() {\n if (isRecording || !ctx) return;\n \n createCompositeCanvas();\n if (!compositeCanvas) {\n console.error('[VideoRecorder] Could not initialize capture canvas');\n return;\n }\n\n recordedChunks = [];\n const stream = compositeCanvas.captureStream(config.fps);\n \n const options: MediaRecorderOptions = {\n mimeType: config.format === 'mp4' ? 'video/mp4;codecs=h264' : 'video/webm;codecs=vp9',\n videoBitsPerSecond: config.bitrate\n };\n\n // Check for browser support and fallback\n if (!MediaRecorder.isTypeSupported(options.mimeType!)) {\n options.mimeType = 'video/webm';\n }\n\n try {\n mediaRecorder = new MediaRecorder(stream, options);\n \n mediaRecorder.ondataavailable = (event) => {\n if (event.data.size > 0) {\n recordedChunks.push(event.data);\n }\n };\n\n mediaRecorder.onstop = () => {\n isRecording = false;\n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n };\n\n isRecording = true;\n isPaused = false;\n mediaRecorder.start(100); // Collect data every 100ms\n \n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n updateComposite(); // Start render loop\n \n if (config.debug) console.log('[VideoRecorder] Recording started');\n } catch (e) {\n console.error('[VideoRecorder] Failed to start MediaRecorder:', e);\n }\n },\n\n async stop(): Promise<Blob> {\n return new Promise((resolve) => {\n if (!mediaRecorder || !isRecording) {\n resolve(new Blob([], { type: 'video/webm' }));\n return;\n }\n\n mediaRecorder.onstop = () => {\n const blob = new Blob(recordedChunks, {\n type: config.format === 'mp4' ? 'video/mp4' : 'video/webm'\n });\n \n if (config.autoDownload) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${config.filename}.${config.format}`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 100);\n }\n\n resolve(blob);\n isRecording = false;\n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n if (config.debug) console.log('[VideoRecorder] Recording stopped, size:', blob.size);\n };\n\n mediaRecorder.stop();\n });\n },\n\n pause() {\n if (mediaRecorder && isRecording && !isPaused) {\n mediaRecorder.pause();\n isPaused = true;\n }\n },\n\n resume() {\n if (mediaRecorder && isRecording && isPaused) {\n mediaRecorder.resume();\n isPaused = false;\n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n updateComposite();\n }\n },\n\n isRecording() { return isRecording; },\n isPaused() { return isPaused; },\n \n updateConfig(newConfig: Partial<VideoRecorderOptions>) {\n Object.assign(config, newConfig);\n }\n };\n\n const pluginApi: VideoRecorderAPI & Record<string, unknown> = api as any;\n\n return {\n manifest,\n onInit(pCtx) {\n ctx = pCtx;\n },\n onDestroy() {\n if (isRecording) {\n mediaRecorder?.stop();\n if (animationFrameId) cancelAnimationFrame(animationFrameId);\n }\n ctx = null;\n },\n api: pluginApi\n };\n}\n\nexport default PluginVideoRecorder;\n\n// Type exports\nexport type {\n PluginVideoRecorderConfig,\n VideoRecorderAPI,\n VideoRecorderOptions,\n} from './types';\n"],"names":["manifest","DEFAULT_CONFIG","PluginVideoRecorder","userConfig","config","ctx","mediaRecorder","recordedChunks","isRecording","isPaused","compositeCanvas","compositeCtx","animationFrameId","createCompositeCanvas","_a","mainCanvas","updateComposite","_b","_c","_d","_e","overlayCanvas","pCtx","stream","options","event","e","resolve","blob","url","a","newConfig"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './virtualization/index'
2
+ import SciPlot from './virtualization/index'
3
+ export default SciPlot
@@ -0,0 +1,6 @@
1
+ import { P as t, P as l } from "../index-ChgIdk3N.js";
2
+ export {
3
+ t as PluginVirtualization,
4
+ l as default
5
+ };
6
+ //# sourceMappingURL=virtualization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtualization.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,5 +1,6 @@
1
1
  /**
2
- * React bindings for Sci Plot
2
+ * React bindings for Velo Plot
3
3
  */
4
4
  export { SciPlot, type SciPlotProps, type SciPlotRef, type SciPlotSeries } from './SciPlot';
5
5
  export { useSciPlot, type UseSciPlotOptions, type UseSciPlotReturn } from './useSciPlot';
6
+ export { useStackedPlot, type UseStackedPlotOptions, type UseStackedPlotReturn } from './useStackedPlot';
@@ -0,0 +1,17 @@
1
+ import { RefObject } from 'react';
2
+ import { StackedChart, StackedChartOptions } from '../core/stacked';
3
+ import { Range } from '../types';
4
+
5
+ export interface UseStackedPlotOptions extends Omit<StackedChartOptions, "container"> {
6
+ }
7
+ export interface UseStackedPlotReturn {
8
+ containerRef: RefObject<HTMLDivElement>;
9
+ stack: StackedChart | null;
10
+ isReady: boolean;
11
+ fitAll: (options?: {
12
+ x?: Range;
13
+ padding?: number;
14
+ }) => void;
15
+ resetAll: () => void;
16
+ }
17
+ export declare function useStackedPlot(options: UseStackedPlotOptions): UseStackedPlotReturn;
@@ -0,0 +1 @@
1
+ export * from './react/index'
package/dist/react.js ADDED
@@ -0,0 +1,31 @@
1
+ import { c as k } from "./createStackedChart-CjsKcOvX.js";
2
+ import { S as x, u as C } from "./createStackedChart-CjsKcOvX.js";
3
+ import { useRef as n, useState as a, useEffect as m, useCallback as f } from "react";
4
+ function A(c) {
5
+ const s = n(null), r = n(null), [i, l] = a(null), [d, u] = a(!1), o = n(c);
6
+ o.current = c, m(() => {
7
+ const t = s.current;
8
+ if (!t) return;
9
+ const e = k({
10
+ ...o.current,
11
+ container: t
12
+ });
13
+ return r.current = e, l(e), e.whenReady().then(() => u(!0)), () => {
14
+ u(!1), e.destroy(), r.current = null, l(null);
15
+ };
16
+ }, []);
17
+ const R = f((t) => {
18
+ var e;
19
+ (e = r.current) == null || e.fitAll(t);
20
+ }, []), S = f(() => {
21
+ var t;
22
+ (t = r.current) == null || t.resetAll();
23
+ }, []);
24
+ return { containerRef: s, stack: i, isReady: d, fitAll: R, resetAll: S };
25
+ }
26
+ export {
27
+ x as SciPlot,
28
+ C as useSciPlot,
29
+ A as useStackedPlot
30
+ };
31
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sources":["../src/react/useStackedPlot.ts"],"sourcesContent":["/**\n * useStackedPlot - React hook for multi-pane stacked charts\n */\n\nimport {\n useEffect,\n useRef,\n useState,\n useCallback,\n type RefObject,\n} from \"react\";\nimport { createStackedChart } from \"../core/stacked\";\nimport type { StackedChart, StackedChartOptions } from \"../core/stacked\";\nimport type { Range } from \"../types\";\n\nexport interface UseStackedPlotOptions extends Omit<StackedChartOptions, \"container\"> {}\n\nexport interface UseStackedPlotReturn {\n containerRef: RefObject<HTMLDivElement>;\n stack: StackedChart | null;\n isReady: boolean;\n fitAll: (options?: { x?: Range; padding?: number }) => void;\n resetAll: () => void;\n}\n\nexport function useStackedPlot(\n options: UseStackedPlotOptions,\n): UseStackedPlotReturn {\n const containerRef = useRef<HTMLDivElement>(null);\n const stackRef = useRef<StackedChart | null>(null);\n const [stack, setStack] = useState<StackedChart | null>(null);\n const [isReady, setIsReady] = useState(false);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const created = createStackedChart({\n ...optionsRef.current,\n container: el,\n });\n stackRef.current = created;\n setStack(created);\n\n created.whenReady().then(() => setIsReady(true));\n\n return () => {\n setIsReady(false);\n created.destroy();\n stackRef.current = null;\n setStack(null);\n };\n }, []);\n\n const fitAll = useCallback((opts?: { x?: Range; padding?: number }) => {\n stackRef.current?.fitAll(opts);\n }, []);\n\n const resetAll = useCallback(() => {\n stackRef.current?.resetAll();\n }, []);\n\n return { containerRef, stack, isReady, fitAll, resetAll };\n}\n"],"names":["useStackedPlot","options","containerRef","useRef","stackRef","stack","setStack","useState","isReady","setIsReady","optionsRef","useEffect","el","created","createStackedChart","fitAll","useCallback","opts","_a","resetAll"],"mappings":";;;AAyBO,SAASA,EACdC,GACsB;AACtB,QAAMC,IAAeC,EAAuB,IAAI,GAC1CC,IAAWD,EAA4B,IAAI,GAC3C,CAACE,GAAOC,CAAQ,IAAIC,EAA8B,IAAI,GACtD,CAACC,GAASC,CAAU,IAAIF,EAAS,EAAK,GACtCG,IAAaP,EAAOF,CAAO;AACjC,EAAAS,EAAW,UAAUT,GAErBU,EAAU,MAAM;AACd,UAAMC,IAAKV,EAAa;AACxB,QAAI,CAACU,EAAI;AAET,UAAMC,IAAUC,EAAmB;AAAA,MACjC,GAAGJ,EAAW;AAAA,MACd,WAAWE;AAAA,IAAA,CACZ;AACD,WAAAR,EAAS,UAAUS,GACnBP,EAASO,CAAO,GAEhBA,EAAQ,YAAY,KAAK,MAAMJ,EAAW,EAAI,CAAC,GAExC,MAAM;AACX,MAAAA,EAAW,EAAK,GAChBI,EAAQ,QAAA,GACRT,EAAS,UAAU,MACnBE,EAAS,IAAI;AAAA,IACf;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAMS,IAASC,EAAY,CAACC,MAA2C;;AACrE,KAAAC,IAAAd,EAAS,YAAT,QAAAc,EAAkB,OAAOD;AAAA,EAC3B,GAAG,CAAA,CAAE,GAECE,IAAWH,EAAY,MAAM;;AACjC,KAAAE,IAAAd,EAAS,YAAT,QAAAc,EAAkB;AAAA,EACpB,GAAG,CAAA,CAAE;AAEL,SAAO,EAAE,cAAAhB,GAAc,OAAAG,GAAO,SAAAG,GAAS,QAAAO,GAAQ,UAAAI,EAAA;AACjD;"}