velo-plot 1.12.0 → 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.
- package/README.md +14 -0
- package/dist/{index.core-xiNcuFfJ.js → ChartCore-BimVvUEg.js} +922 -929
- package/dist/ChartCore-BimVvUEg.js.map +1 -0
- package/dist/core/chart/ChartCore.d.ts +1 -0
- package/dist/core/chart/exporter/SVGExporter.d.ts +7 -2
- package/dist/core/chart/types.d.ts +2 -0
- package/dist/core/render/pixelSnap.d.ts +8 -0
- package/dist/core/stacked/index.d.ts +3 -1
- package/dist/core/stacked/paneResize.d.ts +15 -18
- package/dist/core/stacked/stackExport.d.ts +18 -0
- package/dist/core/stacked/types.d.ts +34 -5
- package/dist/createStackedChart-CjsKcOvX.js +1088 -0
- package/dist/createStackedChart-CjsKcOvX.js.map +1 -0
- package/dist/index-CUGS98p4.js +277 -0
- package/dist/index-CUGS98p4.js.map +1 -0
- package/dist/index-ChgIdk3N.js +229 -0
- package/dist/index-ChgIdk3N.js.map +1 -0
- package/dist/index.core-C_-CFftD.js +167 -0
- package/dist/index.core-C_-CFftD.js.map +1 -0
- package/dist/math-Ddm2EZjj.js +85 -0
- package/dist/math-Ddm2EZjj.js.map +1 -0
- package/dist/plugins/analysis.js +132 -130
- package/dist/plugins/analysis.js.map +1 -1
- package/dist/plugins/anomaly-detection.d.ts +1 -0
- package/dist/plugins/anomaly-detection.js +221 -0
- package/dist/plugins/anomaly-detection.js.map +1 -0
- package/dist/plugins/broken-axis.d.ts +3 -0
- package/dist/plugins/broken-axis.js +262 -0
- package/dist/plugins/broken-axis.js.map +1 -0
- package/dist/plugins/caching.d.ts +3 -0
- package/dist/plugins/caching.js +182 -0
- package/dist/plugins/caching.js.map +1 -0
- package/dist/plugins/data-transform.d.ts +3 -0
- package/dist/plugins/data-transform.js +146 -0
- package/dist/plugins/data-transform.js.map +1 -0
- package/dist/plugins/debug.js +12 -11
- package/dist/plugins/debug.js.map +1 -1
- package/dist/plugins/forecasting.d.ts +1 -0
- package/dist/plugins/forecasting.js +236 -0
- package/dist/plugins/forecasting.js.map +1 -0
- package/dist/plugins/latex.d.ts +1 -0
- package/dist/plugins/latex.js +454 -0
- package/dist/plugins/latex.js.map +1 -0
- package/dist/plugins/lazy-load.d.ts +3 -0
- package/dist/plugins/lazy-load.js +189 -0
- package/dist/plugins/lazy-load.js.map +1 -0
- package/dist/plugins/ml-integration.d.ts +3 -0
- package/dist/plugins/ml-integration.js +355 -0
- package/dist/plugins/ml-integration.js.map +1 -0
- package/dist/plugins/offscreen.d.ts +3 -0
- package/dist/plugins/offscreen.js +169 -0
- package/dist/plugins/offscreen.js.map +1 -0
- package/dist/plugins/pattern-recognition.d.ts +3 -0
- package/dist/plugins/pattern-recognition.js +690 -0
- package/dist/plugins/pattern-recognition.js.map +1 -0
- package/dist/plugins/radar.d.ts +3 -0
- package/dist/plugins/radar.js +103 -0
- package/dist/plugins/radar.js.map +1 -0
- package/dist/plugins/regression.d.ts +3 -0
- package/dist/plugins/regression.js +634 -0
- package/dist/plugins/regression.js.map +1 -0
- package/dist/plugins/roi.d.ts +1 -0
- package/dist/plugins/roi.js +223 -0
- package/dist/plugins/roi.js.map +1 -0
- package/dist/plugins/snapshot/types.d.ts +1 -1
- package/dist/plugins/snapshot.d.ts +3 -0
- package/dist/plugins/snapshot.js +90 -0
- package/dist/plugins/snapshot.js.map +1 -0
- package/dist/plugins/sync/index.d.ts +2 -1
- package/dist/plugins/sync.js +13 -269
- package/dist/plugins/sync.js.map +1 -1
- package/dist/plugins/video-recorder.d.ts +3 -0
- package/dist/plugins/video-recorder.js +104 -0
- package/dist/plugins/video-recorder.js.map +1 -0
- package/dist/plugins/virtualization.d.ts +3 -0
- package/dist/plugins/virtualization.js +6 -0
- package/dist/plugins/virtualization.js.map +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +31 -0
- package/dist/react.js.map +1 -0
- package/dist/utils-BK5UUXxj.js +172 -0
- package/dist/utils-BK5UUXxj.js.map +1 -0
- package/dist/velo-plot.full.js +920 -6003
- package/dist/velo-plot.full.js.map +1 -1
- package/dist/velo-plot.js +23 -22
- package/dist/velo-plot.js.map +1 -1
- package/package.json +9 -2
- package/dist/core/OverlayRenderer.test.d.ts +0 -1
- package/dist/core/chart/ChartScaling.test.d.ts +0 -1
- package/dist/core/chart/NavigationUtils.test.d.ts +0 -1
- package/dist/core/format/axisFormat.test.d.ts +0 -1
- package/dist/core/indicator/buildIndicatorSeries.test.d.ts +0 -1
- package/dist/core/series/SeriesBounds.test.d.ts +0 -1
- package/dist/core/stacked/createStackedChart.test.d.ts +0 -1
- package/dist/core/stacked/paneAxis.test.d.ts +0 -1
- package/dist/core/stacked/paneResize.test.d.ts +0 -1
- package/dist/core/sync/index.test.d.ts +0 -1
- package/dist/index.core-xiNcuFfJ.js.map +0 -1
- package/dist/plugins/tools/tooltip/format.test.d.ts +0 -1
- package/dist/utils-Dbro9-qM.js +0 -254
- package/dist/utils-Dbro9-qM.js.map +0 -1
package/dist/plugins/sync.js
CHANGED
|
@@ -1,285 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var o = (r, t, i) => l(r, typeof t != "symbol" ? t + "" : t, i);
|
|
4
|
-
class f {
|
|
5
|
-
constructor(t) {
|
|
6
|
-
o(this, "charts", /* @__PURE__ */ new Map());
|
|
7
|
-
o(this, "options");
|
|
8
|
-
o(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
9
|
-
o(this, "isUpdating", !1);
|
|
10
|
-
o(this, "debounceTimers", /* @__PURE__ */ new Map());
|
|
11
|
-
o(this, "rafTimers", /* @__PURE__ */ new Map());
|
|
12
|
-
this.options = {
|
|
13
|
-
axis: "x",
|
|
14
|
-
syncCursor: !0,
|
|
15
|
-
syncSelection: !1,
|
|
16
|
-
syncZoom: !0,
|
|
17
|
-
syncPan: !0,
|
|
18
|
-
debounce: 0,
|
|
19
|
-
bidirectional: !0,
|
|
20
|
-
masterId: void 0,
|
|
21
|
-
...t
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
add(t) {
|
|
25
|
-
const i = t.getId();
|
|
26
|
-
return this.charts.has(i) ? (console.warn(`[ChartGroup] Chart ${i} is already in the group`), this) : (this.charts.set(i, t), this.attachEventHandlers(t), this);
|
|
27
|
-
}
|
|
28
|
-
addAll(...t) {
|
|
29
|
-
for (const i of t) this.add(i);
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
remove(t) {
|
|
33
|
-
const i = t.getId();
|
|
34
|
-
return this.charts.has(i) ? (this.detachEventHandlers(t), this.charts.delete(i), this) : this;
|
|
35
|
-
}
|
|
36
|
-
getCharts() {
|
|
37
|
-
return Array.from(this.charts.values());
|
|
38
|
-
}
|
|
39
|
-
size() {
|
|
40
|
-
return this.charts.size;
|
|
41
|
-
}
|
|
42
|
-
has(t) {
|
|
43
|
-
return this.charts.has(t.getId());
|
|
44
|
-
}
|
|
45
|
-
syncAxis(t) {
|
|
46
|
-
return this.options.axis = t, this;
|
|
47
|
-
}
|
|
48
|
-
syncZoom(t) {
|
|
49
|
-
return this.options.syncZoom === t ? this : this.updateOptions({ syncZoom: t });
|
|
50
|
-
}
|
|
51
|
-
syncPan(t) {
|
|
52
|
-
return this.options.syncPan === t ? this : this.updateOptions({ syncPan: t });
|
|
53
|
-
}
|
|
54
|
-
syncCursor(t) {
|
|
55
|
-
return this.options.syncCursor = t, this;
|
|
56
|
-
}
|
|
57
|
-
syncSelection(t) {
|
|
58
|
-
return this.options.syncSelection = t, this;
|
|
59
|
-
}
|
|
60
|
-
/** Update sync options and re-bind event handlers on all charts */
|
|
61
|
-
updateOptions(t) {
|
|
62
|
-
Object.assign(this.options, t);
|
|
63
|
-
for (const i of this.charts.values())
|
|
64
|
-
this.detachEventHandlers(i), this.attachEventHandlers(i);
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
getOptions() {
|
|
68
|
-
return { ...this.options };
|
|
69
|
-
}
|
|
70
|
-
syncTo(t, i) {
|
|
71
|
-
this.propagateZoom(i || "", t);
|
|
72
|
-
}
|
|
73
|
-
resetAll() {
|
|
74
|
-
this.batch(() => {
|
|
75
|
-
for (const t of this.charts.values())
|
|
76
|
-
t.fit ? t.fit() : t.zoom({ x: void 0, y: void 0 });
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
fitAll(t) {
|
|
80
|
-
this.batch(() => {
|
|
81
|
-
let i = t == null ? void 0 : t.x;
|
|
82
|
-
const n = this.options.masterId, s = n ? this.charts.get(n) : this.charts.values().next().value;
|
|
83
|
-
if (!i && (s != null && s.fit)) {
|
|
84
|
-
s.fit({ padding: t == null ? void 0 : t.padding });
|
|
85
|
-
const e = s.getViewBounds();
|
|
86
|
-
this.hasValidViewBounds(e) && (i = [e.xMin, e.xMax]);
|
|
87
|
-
}
|
|
88
|
-
for (const [e, a] of this.charts.entries())
|
|
89
|
-
a.fit && e !== n && a.fit(
|
|
90
|
-
i ? { x: i, padding: t == null ? void 0 : t.padding } : { padding: t == null ? void 0 : t.padding }
|
|
91
|
-
);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
batch(t) {
|
|
95
|
-
const i = this.isUpdating;
|
|
96
|
-
this.isUpdating = !0;
|
|
97
|
-
try {
|
|
98
|
-
return t();
|
|
99
|
-
} finally {
|
|
100
|
-
this.isUpdating = i;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
clearAllSelections() {
|
|
104
|
-
var t;
|
|
105
|
-
for (const i of this.charts.values())
|
|
106
|
-
(t = i.clearSelection) == null || t.call(i);
|
|
107
|
-
}
|
|
108
|
-
destroy() {
|
|
109
|
-
for (const t of this.charts.values())
|
|
110
|
-
this.detachEventHandlers(t);
|
|
111
|
-
this.charts.clear(), this.eventHandlers.clear();
|
|
112
|
-
for (const t of this.debounceTimers.values()) clearTimeout(t);
|
|
113
|
-
this.debounceTimers.clear();
|
|
114
|
-
for (const t of this.rafTimers.values()) cancelAnimationFrame(t);
|
|
115
|
-
this.rafTimers.clear();
|
|
116
|
-
}
|
|
117
|
-
isSyncSource(t) {
|
|
118
|
-
return this.options.bidirectional ? !0 : this.options.masterId ? t === this.options.masterId : !0;
|
|
119
|
-
}
|
|
120
|
-
canPropagateFrom(t) {
|
|
121
|
-
return this.options.bidirectional ? !0 : this.options.masterId ? t === this.options.masterId : !0;
|
|
122
|
-
}
|
|
123
|
-
hasValidViewBounds(t) {
|
|
124
|
-
const i = t.xMax - t.xMin, n = t.yMax - t.yMin;
|
|
125
|
-
return !(!Number.isFinite(i) || !Number.isFinite(n) || i <= 0 && n <= 0);
|
|
126
|
-
}
|
|
127
|
-
attachEventHandlers(t) {
|
|
128
|
-
const i = t.getId(), n = /* @__PURE__ */ new Map();
|
|
129
|
-
if (this.options.syncZoom && this.isSyncSource(i)) {
|
|
130
|
-
const s = (...e) => {
|
|
131
|
-
this.handleZoom(i, e[0]);
|
|
132
|
-
};
|
|
133
|
-
t.on("zoom", s), n.set("zoom", s);
|
|
134
|
-
}
|
|
135
|
-
if (this.options.syncPan && this.isSyncSource(i)) {
|
|
136
|
-
const s = (...e) => {
|
|
137
|
-
this.handlePan(i, e[0]);
|
|
138
|
-
};
|
|
139
|
-
t.on("pan", s), n.set("pan", s);
|
|
140
|
-
}
|
|
141
|
-
if (this.options.syncCursor) {
|
|
142
|
-
const s = (...e) => {
|
|
143
|
-
this.handleCursor(i, e[0]);
|
|
144
|
-
};
|
|
145
|
-
t.on("hover", s), n.set("hover", s);
|
|
146
|
-
}
|
|
147
|
-
if (this.options.syncSelection) {
|
|
148
|
-
const s = (...e) => {
|
|
149
|
-
this.handleSelection(i, e[0]);
|
|
150
|
-
};
|
|
151
|
-
t.on("selectionChange", s), n.set("selectionChange", s);
|
|
152
|
-
}
|
|
153
|
-
this.eventHandlers.set(i, n);
|
|
154
|
-
}
|
|
155
|
-
detachEventHandlers(t) {
|
|
156
|
-
const i = t.getId(), n = this.eventHandlers.get(i);
|
|
157
|
-
if (n) {
|
|
158
|
-
for (const [s, e] of n.entries())
|
|
159
|
-
t.off(s, e);
|
|
160
|
-
this.eventHandlers.delete(i);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
handleZoom(t, i) {
|
|
164
|
-
if (this.isUpdating || !this.canPropagateFrom(t)) return;
|
|
165
|
-
const n = this.charts.get(t);
|
|
166
|
-
if (n && !this.hasValidViewBounds(n.getViewBounds())) return;
|
|
167
|
-
const s = {};
|
|
168
|
-
if ((this.options.axis === "x" || this.options.axis === "xy") && (s.xMin = i.x[0], s.xMax = i.x[1]), (this.options.axis === "y" || this.options.axis === "xy") && (s.yMin = i.y[0], s.yMax = i.y[1]), s.xMin !== void 0 && s.xMax !== void 0) {
|
|
169
|
-
const e = s.xMax - s.xMin;
|
|
170
|
-
if (!Number.isFinite(e) || e <= 0) return;
|
|
171
|
-
}
|
|
172
|
-
this.scheduleSyncAction(`zoom-${t}`, () => {
|
|
173
|
-
this.propagateZoom(t, s);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
handlePan(t, i) {
|
|
177
|
-
if (this.isUpdating || !this.canPropagateFrom(t)) return;
|
|
178
|
-
const n = this.options.axis === "x" || this.options.axis === "xy" ? i.deltaX : 0, s = this.options.axis === "y" || this.options.axis === "xy" ? i.deltaY : 0;
|
|
179
|
-
n === 0 && s === 0 || this.scheduleSyncAction(`pan-${t}`, () => {
|
|
180
|
-
this.propagatePan(t, n, s);
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
handleCursor(t, i) {
|
|
184
|
-
var n, s;
|
|
185
|
-
if (!this.isUpdating)
|
|
186
|
-
for (const [e, a] of this.charts.entries())
|
|
187
|
-
e !== t && (i != null && i.point ? (n = a.setExternalCursor) == null || n.call(a, i.point.x, i.point.y) : (s = a.clearExternalCursor) == null || s.call(a));
|
|
188
|
-
}
|
|
189
|
-
handleSelection(t, i) {
|
|
190
|
-
this.isUpdating || this.options.syncSelection;
|
|
191
|
-
}
|
|
192
|
-
propagateZoom(t, i) {
|
|
193
|
-
if (!this.isUpdating) {
|
|
194
|
-
this.isUpdating = !0;
|
|
195
|
-
try {
|
|
196
|
-
for (const [n, s] of this.charts.entries()) {
|
|
197
|
-
if (n === t) continue;
|
|
198
|
-
const e = { animate: !1 };
|
|
199
|
-
i.xMin !== void 0 && i.xMax !== void 0 && (e.x = [i.xMin, i.xMax]), i.yMin !== void 0 && i.yMax !== void 0 && (e.y = [i.yMin, i.yMax]), s.zoom(e);
|
|
200
|
-
}
|
|
201
|
-
} finally {
|
|
202
|
-
this.isUpdating = !1;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
propagatePan(t, i, n) {
|
|
207
|
-
if (!this.isUpdating) {
|
|
208
|
-
this.isUpdating = !0;
|
|
209
|
-
try {
|
|
210
|
-
const s = this.charts.get(t);
|
|
211
|
-
if (!s || !this.hasValidViewBounds(s.getViewBounds())) return;
|
|
212
|
-
const e = s.getViewBounds();
|
|
213
|
-
for (const [a, d] of this.charts.entries()) {
|
|
214
|
-
if (a === t) continue;
|
|
215
|
-
const h = { animate: !1 };
|
|
216
|
-
(this.options.axis === "x" || this.options.axis === "xy") && (h.x = [e.xMin, e.xMax]), (this.options.axis === "y" || this.options.axis === "xy") && (h.y = [e.yMin, e.yMax]), (h.x || h.y) && d.zoom(h);
|
|
217
|
-
}
|
|
218
|
-
} finally {
|
|
219
|
-
this.isUpdating = !1;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
scheduleSyncAction(t, i) {
|
|
224
|
-
if (this.options.debounce > 0) {
|
|
225
|
-
this.debounceAction(t, i);
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (this.rafTimers.has(t)) return;
|
|
229
|
-
const n = requestAnimationFrame(() => {
|
|
230
|
-
this.rafTimers.delete(t), i();
|
|
231
|
-
});
|
|
232
|
-
this.rafTimers.set(t, n);
|
|
233
|
-
}
|
|
234
|
-
debounceAction(t, i) {
|
|
235
|
-
const n = this.debounceTimers.get(t);
|
|
236
|
-
n && clearTimeout(n);
|
|
237
|
-
const s = window.setTimeout(() => {
|
|
238
|
-
this.debounceTimers.delete(t), i();
|
|
239
|
-
}, this.options.debounce);
|
|
240
|
-
this.debounceTimers.set(t, s);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function c(r, t) {
|
|
244
|
-
const i = new f(t);
|
|
245
|
-
return i.addAll(...r), i;
|
|
246
|
-
}
|
|
247
|
-
function y(r, t, i) {
|
|
248
|
-
return c([r, t], i);
|
|
249
|
-
}
|
|
250
|
-
function m(r, t, i = "x") {
|
|
251
|
-
return c([r, t], {
|
|
252
|
-
axis: i,
|
|
253
|
-
bidirectional: !1,
|
|
254
|
-
masterId: r.getId(),
|
|
255
|
-
syncCursor: !0,
|
|
256
|
-
syncZoom: !0,
|
|
257
|
-
syncPan: !0
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
const p = {
|
|
1
|
+
import { C as c, c as s, a as i, l } from "../index-CUGS98p4.js";
|
|
2
|
+
const n = {
|
|
261
3
|
name: "velo-plot-sync",
|
|
262
4
|
version: "1.0.0",
|
|
263
5
|
description: "Multi-chart synchronization for velo-plot",
|
|
264
6
|
provides: ["interaction"],
|
|
265
7
|
tags: ["sync", "multi-chart", "coordination"]
|
|
266
8
|
};
|
|
267
|
-
function
|
|
9
|
+
function r(o = {}) {
|
|
268
10
|
return {
|
|
269
|
-
manifest:
|
|
11
|
+
manifest: n,
|
|
270
12
|
onInit(t) {
|
|
271
|
-
|
|
13
|
+
console.warn(
|
|
14
|
+
"[PluginSync] Deprecated: use ChartGroup / createChartGroup from the core sync module instead."
|
|
15
|
+
);
|
|
272
16
|
},
|
|
273
17
|
onDestroy(t) {
|
|
274
18
|
}
|
|
275
19
|
};
|
|
276
20
|
}
|
|
277
21
|
export {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
22
|
+
c as ChartGroup,
|
|
23
|
+
r as PluginSync,
|
|
24
|
+
s as createChartGroup,
|
|
25
|
+
i as createMasterSlave,
|
|
26
|
+
r as default,
|
|
27
|
+
l as linkCharts
|
|
284
28
|
};
|
|
285
29
|
//# sourceMappingURL=sync.js.map
|
package/dist/plugins/sync.js.map
CHANGED
|
@@ -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 * @module sync\n */\n\nimport type { Bounds, Range } from \"../../types\";\n\nexport type SyncAxis = 'x' | 'y' | 'xy' | 'none';\n\nexport interface SyncOptions {\n axis?: SyncAxis;\n syncCursor?: boolean;\n syncSelection?: boolean;\n syncZoom?: boolean;\n syncPan?: boolean;\n debounce?: number;\n bidirectional?: boolean;\n /** When set, used for fitAll; with bidirectional sync any pane can drive pan/zoom */\n masterId?: string;\n}\n\nexport interface ChartLike {\n getId(): string;\n getViewBounds(): Bounds;\n zoom(options: { x?: Range; y?: Range; animate?: boolean }): void;\n pan(dx: number, dy: number): void;\n fit?(options?: { x?: Range; y?: Range; padding?: number | { x?: number; y?: number } }): void;\n getCursorPosition?(): { x: number; y: number } | null;\n setExternalCursor?(x: number, y: number): void;\n clearExternalCursor?(): void;\n getSelectedPoints?(): { seriesId: string; indices: number[] }[];\n selectPoints?(points: { seriesId: string; indices: number[] }[]): void;\n clearSelection?(): void;\n on(event: string, callback: (...args: unknown[]) => void): void;\n off(event: string, callback: (...args: unknown[]) => void): void;\n}\n\nexport interface SyncEvent {\n sourceId: string;\n type: 'zoom' | 'pan' | 'cursor' | 'selection' | 'bounds';\n data: unknown;\n}\n\ntype RequiredSyncOptions = Required<Omit<SyncOptions, 'masterId'>> & Pick<SyncOptions, 'masterId'>;\n\nexport class ChartGroup {\n private charts: Map<string, ChartLike> = new Map();\n private options: RequiredSyncOptions;\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 private rafTimers: 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 masterId: undefined,\n ...options,\n };\n }\n\n add(chart: ChartLike): this {\n const chartId = chart.getId();\n if (this.charts.has(chartId)) {\n console.warn(`[ChartGroup] Chart ${chartId} is already in the group`);\n return this;\n }\n this.charts.set(chartId, chart);\n this.attachEventHandlers(chart);\n return this;\n }\n\n addAll(...charts: ChartLike[]): this {\n for (const chart of charts) this.add(chart);\n return this;\n }\n\n remove(chart: ChartLike): this {\n const chartId = chart.getId();\n if (!this.charts.has(chartId)) return this;\n this.detachEventHandlers(chart);\n this.charts.delete(chartId);\n return this;\n }\n\n getCharts(): ChartLike[] {\n return Array.from(this.charts.values());\n }\n\n size(): number {\n return this.charts.size;\n }\n\n has(chart: ChartLike): boolean {\n return this.charts.has(chart.getId());\n }\n\n syncAxis(axis: SyncAxis): this {\n this.options.axis = axis;\n return this;\n }\n\n syncZoom(enabled: boolean): this {\n if (this.options.syncZoom === enabled) return this;\n return this.updateOptions({ syncZoom: enabled });\n }\n\n syncPan(enabled: boolean): this {\n if (this.options.syncPan === enabled) return this;\n return this.updateOptions({ syncPan: enabled });\n }\n\n syncCursor(enabled: boolean): this {\n this.options.syncCursor = enabled;\n return this;\n }\n\n syncSelection(enabled: boolean): this {\n this.options.syncSelection = enabled;\n return this;\n }\n\n /** Update sync options and re-bind event handlers on all charts */\n updateOptions(partial: Partial<SyncOptions>): this {\n Object.assign(this.options, partial);\n for (const chart of this.charts.values()) {\n this.detachEventHandlers(chart);\n this.attachEventHandlers(chart);\n }\n return this;\n }\n\n getOptions(): Readonly<SyncOptions> {\n return { ...this.options };\n }\n\n syncTo(bounds: Partial<Bounds>, excludeChartId?: string): void {\n this.propagateZoom(excludeChartId || '', bounds);\n }\n\n resetAll(): void {\n this.batch(() => {\n for (const chart of this.charts.values()) {\n if (chart.fit) chart.fit();\n else chart.zoom({ x: undefined, y: undefined });\n }\n });\n }\n\n fitAll(options?: { x?: Range; padding?: number }): void {\n this.batch(() => {\n let sharedX: Range | undefined = options?.x;\n const masterId = this.options.masterId;\n const master = masterId ? this.charts.get(masterId) : this.charts.values().next().value;\n\n if (!sharedX && master?.fit) {\n master.fit({ padding: options?.padding });\n const b = master.getViewBounds();\n if (this.hasValidViewBounds(b)) sharedX = [b.xMin, b.xMax];\n }\n\n for (const [chartId, chart] of this.charts.entries()) {\n if (!chart.fit) continue;\n if (chartId === masterId) continue;\n chart.fit(\n sharedX\n ? { x: sharedX, padding: options?.padding }\n : { padding: options?.padding },\n );\n }\n });\n }\n\n batch<T>(fn: () => T): T {\n const prev = this.isUpdating;\n this.isUpdating = true;\n try {\n return fn();\n } finally {\n this.isUpdating = prev;\n }\n }\n\n clearAllSelections(): void {\n for (const chart of this.charts.values()) {\n chart.clearSelection?.();\n }\n }\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 for (const timerId of this.debounceTimers.values()) clearTimeout(timerId);\n this.debounceTimers.clear();\n for (const rafId of this.rafTimers.values()) cancelAnimationFrame(rafId);\n this.rafTimers.clear();\n }\n\n private isSyncSource(chartId: string): boolean {\n if (this.options.bidirectional) return true;\n if (this.options.masterId) return chartId === this.options.masterId;\n return true;\n }\n\n private canPropagateFrom(sourceId: string): boolean {\n if (this.options.bidirectional) return true;\n if (this.options.masterId) return sourceId === this.options.masterId;\n return true;\n }\n\n private hasValidViewBounds(bounds: Bounds): boolean {\n const xSpan = bounds.xMax - bounds.xMin;\n const ySpan = bounds.yMax - bounds.yMin;\n if (!Number.isFinite(xSpan) || !Number.isFinite(ySpan)) return false;\n if (xSpan <= 0 && ySpan <= 0) return false;\n return true;\n }\n\n private attachEventHandlers(chart: ChartLike): void {\n const chartId = chart.getId();\n const handlers = new Map<string, (...args: unknown[]) => void>();\n\n if (this.options.syncZoom && this.isSyncSource(chartId)) {\n const zoomHandler = (...args: unknown[]) => {\n this.handleZoom(chartId, args[0] as { x: Range; y: Range });\n };\n chart.on('zoom', zoomHandler);\n handlers.set('zoom', zoomHandler);\n }\n\n if (this.options.syncPan && this.isSyncSource(chartId)) {\n const panHandler = (...args: unknown[]) => {\n this.handlePan(chartId, args[0] as { deltaX: number; deltaY: number });\n };\n chart.on('pan', panHandler);\n handlers.set('pan', panHandler);\n }\n\n if (this.options.syncCursor) {\n const hoverHandler = (...args: unknown[]) => {\n this.handleCursor(chartId, args[0] as { point?: { x: number; y: number } } | null);\n };\n chart.on('hover', hoverHandler);\n handlers.set('hover', hoverHandler);\n }\n\n if (this.options.syncSelection) {\n const selectionHandler = (...args: unknown[]) => {\n this.handleSelection(chartId, args[0] as { selected: unknown[] });\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 if (!handlers) return;\n for (const [event, handler] of handlers.entries()) {\n chart.off(event, handler);\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 if (!this.canPropagateFrom(sourceId)) return;\n\n const sourceChart = this.charts.get(sourceId);\n if (sourceChart && !this.hasValidViewBounds(sourceChart.getViewBounds())) return;\n\n const bounds: Partial<Bounds> = {};\n if (this.options.axis === 'x' || this.options.axis === 'xy') {\n bounds.xMin = event.x[0];\n bounds.xMax = event.x[1];\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 if (bounds.xMin !== undefined && bounds.xMax !== undefined) {\n const xSpan = bounds.xMax - bounds.xMin;\n if (!Number.isFinite(xSpan) || xSpan <= 0) return;\n }\n\n this.scheduleSyncAction(`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 if (!this.canPropagateFrom(sourceId)) 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 if (dx === 0 && dy === 0) return;\n\n this.scheduleSyncAction(`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 for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n if (event?.point) chart.setExternalCursor?.(event.point.x, event.point.y);\n else chart.clearExternalCursor?.();\n }\n }\n\n private handleSelection(_sourceId: string, _event: { selected: unknown[] }): void {\n if (this.isUpdating || !this.options.syncSelection) return;\n }\n\n private propagateZoom(sourceId: string, bounds: Partial<Bounds>): void {\n if (this.isUpdating) return;\n this.isUpdating = true;\n try {\n for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n const zoomOptions: { x?: Range; y?: Range; animate?: boolean } = { animate: false };\n if (bounds.xMin !== undefined && bounds.xMax !== undefined) {\n zoomOptions.x = [bounds.xMin, bounds.xMax];\n }\n if (bounds.yMin !== undefined && bounds.yMax !== undefined) {\n zoomOptions.y = [bounds.yMin, bounds.yMax];\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 this.isUpdating = true;\n try {\n const sourceChart = this.charts.get(sourceId);\n if (!sourceChart || !this.hasValidViewBounds(sourceChart.getViewBounds())) return;\n\n const masterBounds = sourceChart.getViewBounds();\n\n for (const [chartId, chart] of this.charts.entries()) {\n if (chartId === sourceId) continue;\n\n const zoomOptions: { x?: Range; y?: Range; animate?: boolean } = { animate: false };\n\n if (this.options.axis === 'x' || this.options.axis === 'xy') {\n zoomOptions.x = [masterBounds.xMin, masterBounds.xMax];\n }\n\n if (this.options.axis === 'y' || this.options.axis === 'xy') {\n zoomOptions.y = [masterBounds.yMin, masterBounds.yMax];\n }\n\n if (zoomOptions.x || zoomOptions.y) {\n chart.zoom(zoomOptions);\n }\n }\n } finally {\n this.isUpdating = false;\n }\n }\n\n private scheduleSyncAction(key: string, action: () => void): void {\n if (this.options.debounce > 0) {\n this.debounceAction(key, action);\n return;\n }\n if (this.rafTimers.has(key)) return;\n const rafId = requestAnimationFrame(() => {\n this.rafTimers.delete(key);\n action();\n });\n this.rafTimers.set(key, rafId);\n }\n\n private debounceAction(key: string, action: () => void): void {\n const existingTimer = this.debounceTimers.get(key);\n if (existingTimer) clearTimeout(existingTimer);\n const timerId = window.setTimeout(() => {\n this.debounceTimers.delete(key);\n action();\n }, this.options.debounce);\n this.debounceTimers.set(key, timerId);\n }\n}\n\nexport function createChartGroup(charts: ChartLike[], options?: SyncOptions): ChartGroup {\n const group = new ChartGroup(options);\n group.addAll(...charts);\n return group;\n}\n\nexport function linkCharts(chart1: ChartLike, chart2: ChartLike, options?: SyncOptions): ChartGroup {\n return createChartGroup([chart1, chart2], options);\n}\n\nexport function createMasterSlave(\n master: ChartLike,\n slave: ChartLike,\n axis: SyncAxis = 'x',\n): ChartGroup {\n return createChartGroup([master, slave], {\n axis,\n bidirectional: false,\n masterId: master.getId(),\n syncCursor: true,\n syncZoom: true,\n syncPan: true,\n });\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","partial","bounds","excludeChartId","sharedX","masterId","master","b","fn","prev","_a","timerId","rafId","sourceId","xSpan","ySpan","handlers","zoomHandler","args","panHandler","hoverHandler","selectionHandler","event","handler","sourceChart","dx","dy","_b","_sourceId","_event","zoomOptions","_dx","_dy","masterBounds","key","action","existingTimer","createChartGroup","group","linkCharts","chart1","chart2","createMasterSlave","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;"}
|
|
@@ -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":"AAgBA,MAAMA,IAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,gBAAgB,aAAa;AAAA,EACxC,MAAM,CAAC,UAAU,SAAS,WAAW;AACvC,GAEMC,IAAsD;AAAA,EAC1D,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,cAAc;AAAA,EACd,UAAU;AAAA,EACV,OAAO;AACT;AAEO,SAASC,EACdC,IAAiD,IACT;AACxC,QAAMC,IAAS,EAAE,GAAGH,GAAgB,GAAGE,EAAA;AACvC,MAAIE,IAA4B,MAE5BC,IAAsC,MACtCC,IAAyB,CAAA,GACzBC,IAAc,IACdC,IAAW,IAGXC,IAA4C,MAC5CC,IAAgD,MAChDC,IAAkC;AAEtC,WAASC,IAAwB;AApCnC,QAAAC;AAqCI,QAAI,CAACT,EAAK;AAGV,UAAMU,KAAaD,IAAAT,EAAI,OAAO,OAAX,gBAAAS,EAAe;AAElC,IAAKC,MAELL,IAAkB,SAAS,cAAc,QAAQ,GACjDA,EAAgB,QAAQK,EAAW,OACnCL,EAAgB,SAASK,EAAW,QACpCJ,IAAeD,EAAgB,WAAW,IAAI;AAAA,EAChD;AAEA,WAASM,IAAkB;AAlD7B,QAAAF,GAAAG,GAAAC,GAAAC,GAAAC;AAmDI,QAAI,CAACf,KAAO,CAACM,KAAgB,CAACD,EAAiB;AAE/C,UAAMK,KAAaD,IAAAT,EAAI,OAAO,OAAX,gBAAAS,EAAe,QAC5BO,KAAgBJ,IAAAZ,EAAI,OAAO,UAAX,gBAAAY,EAAkB;AAGxC,IAAIb,EAAO,kBACPO,EAAa,YAAYP,EAAO,qBAAoBgB,KAAAD,KAAAD,IAAAb,EAAI,OAAc,aAAlB,gBAAAc,EAAA,KAAAD,OAAA,gBAAAE,EAAgC,eAAc,WAClGT,EAAa,SAAS,GAAG,GAAGD,EAAgB,OAAOA,EAAgB,MAAM,KAEzEC,EAAa,UAAU,GAAG,GAAGD,EAAgB,OAAOA,EAAgB,MAAM,GAI1EK,KAAYJ,EAAa,UAAUI,GAAY,GAAG,CAAC,GACnDM,KAAeV,EAAa,UAAUU,GAAe,GAAG,CAAC,GAEzDb,KAAe,CAACC,MACZG,0BAAuCA,CAAgB,GAC3DA,IAAmB,sBAAsBI,CAAe;AAAA,EAE9D;AA6GA,SAAO;AAAA,IACL,UAAAhB;AAAA,IACA,OAAOsB,GAAM;AACX,MAAAjB,IAAMiB;AAAA,IACR;AAAA,IACA,YAAY;AACV,MAAId,MACAF,KAAA,QAAAA,EAAe,QACXM,0BAAuCA,CAAgB,IAE/DP,IAAM;AAAA,IACR;AAAA,IACA,KAvH4B;AAAA,MAC5B,QAAQ;AACJ,YAAIG,KAAe,CAACH,EAAK;AAGzB,YADAQ,EAAA,GACI,CAACH,GAAiB;AAClB,kBAAQ,MAAM,qDAAqD;AACnE;AAAA,QACJ;AAEA,QAAAH,IAAiB,CAAA;AACjB,cAAMgB,IAASb,EAAgB,cAAcN,EAAO,GAAG,GAEjDoB,IAAgC;AAAA,UAClC,UAAUpB,EAAO,WAAW,QAAQ,0BAA0B;AAAA,UAC9D,oBAAoBA,EAAO;AAAA,QAAA;AAI/B,QAAK,cAAc,gBAAgBoB,EAAQ,QAAS,MAChDA,EAAQ,WAAW;AAGvB,YAAI;AACA,UAAAlB,IAAgB,IAAI,cAAciB,GAAQC,CAAO,GAEjDlB,EAAc,kBAAkB,CAACmB,MAAU;AACvC,YAAIA,EAAM,KAAK,OAAO,KAClBlB,EAAe,KAAKkB,EAAM,IAAI;AAAA,UAEtC,GAEAnB,EAAc,SAAS,MAAM;AACzB,YAAAE,IAAc,IACVI,0BAAuCA,CAAgB;AAAA,UAC/D,GAEAJ,IAAc,IACdC,IAAW,IACXH,EAAc,MAAM,GAAG,GAEnBM,0BAAuCA,CAAgB,GAC3DI,EAAA,GAEIZ,EAAO,SAAO,QAAQ,IAAI,mCAAmC;AAAA,QACrE,SAASsB,GAAG;AACR,kBAAQ,MAAM,kDAAkDA,CAAC;AAAA,QACrE;AAAA,MACJ;AAAA,MAEA,MAAM,OAAsB;AACxB,eAAO,IAAI,QAAQ,CAACC,MAAY;AAC5B,cAAI,CAACrB,KAAiB,CAACE,GAAa;AAChC,YAAAmB,EAAQ,IAAI,KAAK,CAAA,GAAI,EAAE,MAAM,aAAA,CAAc,CAAC;AAC5C;AAAA,UACJ;AAEA,UAAArB,EAAc,SAAS,MAAM;AACzB,kBAAMsB,IAAO,IAAI,KAAKrB,GAAgB;AAAA,cAClC,MAAMH,EAAO,WAAW,QAAQ,cAAc;AAAA,YAAA,CACjD;AAED,gBAAIA,EAAO,cAAc;AACrB,oBAAMyB,IAAM,IAAI,gBAAgBD,CAAI,GAC9BE,IAAI,SAAS,cAAc,GAAG;AACpC,cAAAA,EAAE,OAAOD,GACTC,EAAE,WAAW,GAAG1B,EAAO,QAAQ,IAAIA,EAAO,MAAM,IAChD0B,EAAE,MAAA,GACF,WAAW,MAAM,IAAI,gBAAgBD,CAAG,GAAG,GAAG;AAAA,YAClD;AAEA,YAAAF,EAAQC,CAAI,GACZpB,IAAc,IACVI,0BAAuCA,CAAgB,GACvDR,EAAO,SAAO,QAAQ,IAAI,4CAA4CwB,EAAK,IAAI;AAAA,UACvF,GAEAtB,EAAc,KAAA;AAAA,QAClB,CAAC;AAAA,MACL;AAAA,MAEA,QAAQ;AACJ,QAAIA,KAAiBE,KAAe,CAACC,MACjCH,EAAc,MAAA,GACdG,IAAW;AAAA,MAEnB;AAAA,MAEA,SAAS;AACL,QAAIH,KAAiBE,KAAeC,MAChCH,EAAc,OAAA,GACdG,IAAW,IACPG,0BAAuCA,CAAgB,GAC3DI,EAAA;AAAA,MAER;AAAA,MAEA,cAAc;AAAE,eAAOR;AAAA,MAAa;AAAA,MACpC,WAAW;AAAE,eAAOC;AAAA,MAAU;AAAA,MAE9B,aAAasB,GAA0C;AACnD,eAAO,OAAO3B,GAAQ2B,CAAS;AAAA,MACnC;AAAA,IAAA;AAAA,EAiBK;AAET;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtualization.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/react.d.ts
ADDED
|
@@ -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;"}
|