@rm-graph/core 0.1.2 → 0.1.3

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/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { __require, ThemeManager } from './chunk-Q2ZHY445.mjs';
2
2
  export { ThemeManager, darkTheme, getThemeManager, lightTheme, midnightTheme, modernTheme } from './chunk-Q2ZHY445.mjs';
3
- import { SciChartSurface, NumericAxis, EAutoRange, NumberRange, RolloverModifier, ZoomPanModifier, MouseWheelZoomModifier, XyDataSeries, FastLineRenderableSeries, EllipsePointMarker, SweepAnimation, FastColumnRenderableSeries, WaveAnimation, GradientParams, Point, FastMountainRenderableSeries, UniformHeatmapDataSeries, UniformHeatmapRenderableSeries, HeatmapColorMap, SciChart3DSurface, NumericAxis3D, MouseWheelZoomModifier3D, OrbitModifier3D, CameraController, Vector3, UniformGridDataSeries3D, GradientColorPalette, SurfaceMeshRenderableSeries3D, EDrawMeshAs, XyzDataSeries3D, ColumnRenderableSeries3D, PointLineRenderableSeries3D, TooltipModifier3D, SciChartJSDarkTheme, SciChartJSLightTheme } from 'scichart';
3
+ import { SciChart3DSurface, NumericAxis3D, MouseWheelZoomModifier3D, OrbitModifier3D, CameraController, Vector3, UniformGridDataSeries3D, GradientColorPalette, SurfaceMeshRenderableSeries3D, EDrawMeshAs, NumberRange, XyzDataSeries3D, ColumnRenderableSeries3D, PointLineRenderableSeries3D, TooltipModifier3D, SciChartSurface, NumericAxis, EAxisAlignment, ENumericFormat, EAutoRange, CursorModifier, RubberBandXyZoomModifier, ZoomExtentsModifier, HeatmapColorMap, UniformHeatmapDataSeries, UniformHeatmapRenderableSeries, XyDataSeries, FastLineRenderableSeries, HeatmapLegend } from 'scichart';
4
4
  export { SciChartSurface } from 'scichart';
5
+ import { SciChartJSLightTheme } from 'scichart/Charting/Themes/SciChartJSLightTheme';
5
6
 
6
7
  // src/utils/helpers.ts
7
8
  function generateId(prefix = "chart") {
@@ -128,7 +129,7 @@ function hexToRgba(hex, alpha = 1) {
128
129
  }
129
130
 
130
131
  // src/charts/BaseChart.ts
131
- var SCICHART_VERSION = "3.5.750";
132
+ var SCICHART_VERSION = "4.0.933";
132
133
  var sciChartConfigured = false;
133
134
  function ensureSciChartConfigured() {
134
135
  if (sciChartConfigured) return;
@@ -138,8 +139,7 @@ function ensureSciChartConfigured() {
138
139
  } catch {
139
140
  try {
140
141
  SciChartSurface.configure({
141
- wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION}/_wasm/scichart2d.wasm`,
142
- dataUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION}/_wasm/scichart2d.data`
142
+ wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION}/_wasm/scichart2d.wasm`
143
143
  });
144
144
  sciChartConfigured = true;
145
145
  } catch {
@@ -224,6 +224,42 @@ var BaseChart = class {
224
224
  applyTheme() {
225
225
  if (!this.surface) return;
226
226
  this.surface.background = this.theme.backgroundColor ?? "#ffffff";
227
+ try {
228
+ const themeName = this.config.theme;
229
+ const { SciChartJSDarkTheme, SciChartJSLightTheme: SciChartJSLightTheme2 } = __require("scichart");
230
+ const nextThemeProvider = themeName === "light" ? new SciChartJSLightTheme2() : new SciChartJSDarkTheme();
231
+ this.surface.applyTheme?.(nextThemeProvider);
232
+ } catch {
233
+ }
234
+ try {
235
+ const applyAxisTheme = (axis) => {
236
+ if (!axis) return;
237
+ axis.axisTitleStyle = {
238
+ ...axis.axisTitleStyle ?? {},
239
+ color: this.theme.axis?.titleColor,
240
+ fontFamily: this.theme.fontFamily
241
+ };
242
+ axis.labelStyle = {
243
+ ...axis.labelStyle ?? {},
244
+ color: this.theme.axis?.labelColor,
245
+ fontFamily: this.theme.fontFamily
246
+ };
247
+ axis.majorGridLineStyle = {
248
+ ...axis.majorGridLineStyle ?? {},
249
+ color: this.theme.axis?.gridLineColor
250
+ };
251
+ axis.axisBorder = {
252
+ ...axis.axisBorder ?? {},
253
+ color: this.theme.axis?.lineColor
254
+ };
255
+ };
256
+ const xAxes = this.surface.xAxes;
257
+ const yAxes = this.surface.yAxes;
258
+ const toArray = (axes) => axes?.asArray?.() ?? axes?.itemsArray ?? axes?.items ?? [];
259
+ for (const axis of toArray(xAxes)) applyAxisTheme(axis);
260
+ for (const axis of toArray(yAxes)) applyAxisTheme(axis);
261
+ } catch {
262
+ }
227
263
  }
228
264
  /**
229
265
  * Set up resize observer for responsive charts
@@ -255,6 +291,17 @@ var BaseChart = class {
255
291
  }
256
292
  this.handleResize();
257
293
  }
294
+ /**
295
+ * Reset zoom to fit all data (zoom extents)
296
+ * Note: not part of the ChartInstance interface, but available on concrete chart classes.
297
+ */
298
+ resetZoom() {
299
+ if (!this.surface) return;
300
+ try {
301
+ this.surface.zoomExtents?.();
302
+ } catch {
303
+ }
304
+ }
258
305
  /**
259
306
  * Export chart as image
260
307
  */
@@ -270,901 +317,72 @@ var BaseChart = class {
270
317
  return canvas.toDataURL(mimeType);
271
318
  }
272
319
  /**
273
- * Add event listener
274
- */
275
- on(event, handler) {
276
- if (!this.eventHandlers.has(event)) {
277
- this.eventHandlers.set(event, /* @__PURE__ */ new Set());
278
- }
279
- this.eventHandlers.get(event).add(handler);
280
- }
281
- /**
282
- * Remove event listener
283
- */
284
- off(event, handler) {
285
- const handlers = this.eventHandlers.get(event);
286
- if (handlers) {
287
- handlers.delete(handler);
288
- }
289
- }
290
- /**
291
- * Emit an event
292
- */
293
- emit(event, data) {
294
- const handlers = this.eventHandlers.get(event);
295
- if (handlers) {
296
- handlers.forEach((handler) => handler(data));
297
- }
298
- }
299
- /**
300
- * Destroy the chart and clean up resources
301
- */
302
- destroy() {
303
- if (this.isDestroyed) return;
304
- if (this.resizeObserver) {
305
- this.resizeObserver.disconnect();
306
- this.resizeObserver = null;
307
- }
308
- this.eventHandlers.clear();
309
- if (this.surface) {
310
- this.surface.delete();
311
- this.surface = null;
312
- }
313
- if (this.container) {
314
- this.container.innerHTML = "";
315
- }
316
- this.isDestroyed = true;
317
- this.isInitialized = false;
318
- }
319
- /**
320
- * Get current configuration
321
- */
322
- getConfig() {
323
- return { ...this.config };
324
- }
325
- /**
326
- * Get current theme
327
- */
328
- getTheme() {
329
- return { ...this.theme };
330
- }
331
- /**
332
- * Check if chart is initialized
333
- */
334
- isReady() {
335
- return this.isInitialized && !this.isDestroyed;
336
- }
337
- };
338
- function getSciChartTheme(themeName) {
339
- switch (themeName) {
340
- case "light":
341
- return new SciChartJSLightTheme();
342
- case "dark":
343
- case "modern":
344
- case "midnight":
345
- default:
346
- return new SciChartJSDarkTheme();
347
- }
348
- }
349
- var LineChart = class extends BaseChart {
350
- constructor(config) {
351
- super(config);
352
- this.dataSeries = /* @__PURE__ */ new Map();
353
- this.renderableSeries = [];
354
- this.wasmContext = null;
355
- }
356
- /**
357
- * Create the SciChart surface for line chart
358
- */
359
- async createSurface() {
360
- if (!this.container) {
361
- throw new Error("Container not set");
362
- }
363
- const sciChartTheme = getSciChartTheme(this.config.theme);
364
- if (!this.container.id) {
365
- this.container.id = this.id;
366
- }
367
- const { sciChartSurface, wasmContext } = await SciChartSurface.create(
368
- this.container,
369
- {
370
- theme: sciChartTheme
371
- }
372
- );
373
- this.surface = sciChartSurface;
374
- this.wasmContext = wasmContext;
375
- const xAxis = new NumericAxis(wasmContext, {
376
- axisTitle: this.config.xAxis?.title,
377
- drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? true,
378
- drawMinorGridLines: false,
379
- axisTitleStyle: {
380
- fontSize: 14,
381
- fontFamily: this.theme.fontFamily,
382
- color: this.theme.axis?.titleColor
383
- },
384
- labelStyle: {
385
- fontSize: 12,
386
- fontFamily: this.theme.fontFamily,
387
- color: this.theme.axis?.labelColor
388
- },
389
- majorGridLineStyle: {
390
- color: this.theme.axis?.gridLineColor ?? "#e9ecef",
391
- strokeThickness: 1
392
- },
393
- axisBorder: {
394
- color: this.theme.axis?.lineColor ?? "#dee2e6"
395
- },
396
- autoRange: EAutoRange.Always
397
- });
398
- const yAxis = new NumericAxis(wasmContext, {
399
- axisTitle: this.config.yAxis?.title,
400
- drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
401
- drawMinorGridLines: false,
402
- axisTitleStyle: {
403
- fontSize: 14,
404
- fontFamily: this.theme.fontFamily,
405
- color: this.theme.axis?.titleColor
406
- },
407
- labelStyle: {
408
- fontSize: 12,
409
- fontFamily: this.theme.fontFamily,
410
- color: this.theme.axis?.labelColor
411
- },
412
- majorGridLineStyle: {
413
- color: this.theme.axis?.gridLineColor ?? "#e9ecef",
414
- strokeThickness: 1
415
- },
416
- axisBorder: {
417
- color: this.theme.axis?.lineColor ?? "#dee2e6"
418
- },
419
- autoRange: EAutoRange.Always
420
- });
421
- if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
422
- xAxis.visibleRange = new NumberRange(this.config.xAxis.min, this.config.xAxis.max);
423
- xAxis.autoRange = EAutoRange.Never;
424
- }
425
- if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
426
- yAxis.visibleRange = new NumberRange(this.config.yAxis.min, this.config.yAxis.max);
427
- yAxis.autoRange = EAutoRange.Never;
428
- }
429
- sciChartSurface.xAxes.add(xAxis);
430
- sciChartSurface.yAxes.add(yAxis);
431
- if (this.config.tooltip?.enabled !== false) {
432
- sciChartSurface.chartModifiers.add(
433
- new RolloverModifier({
434
- showTooltip: true,
435
- showAxisLabel: true
436
- })
437
- );
438
- }
439
- sciChartSurface.chartModifiers.add(new ZoomPanModifier());
440
- sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
441
- this.addSeries(this.config.series);
442
- }
443
- /**
444
- * Add series to the chart
445
- */
446
- addSeries(seriesConfigs) {
447
- if (!this.surface || !this.wasmContext) return;
448
- const wasmContext = this.wasmContext;
449
- const colorPalette = this.theme.colorPalette ?? [];
450
- seriesConfigs.forEach((seriesConfig, index) => {
451
- const data = normalizeDataPoints(seriesConfig.data);
452
- const xValues = extractXValues(data);
453
- const yValues = extractYValues(data);
454
- const dataSeries = new XyDataSeries(wasmContext, {
455
- xValues,
456
- yValues,
457
- dataSeriesName: seriesConfig.name
458
- });
459
- this.dataSeries.set(seriesConfig.name, dataSeries);
460
- const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
461
- const lineSeries = new FastLineRenderableSeries(wasmContext);
462
- lineSeries.dataSeries = dataSeries;
463
- lineSeries.stroke = color;
464
- lineSeries.strokeThickness = this.config.lineWidth ?? 2;
465
- if (this.config.showPoints) {
466
- lineSeries.pointMarker = new EllipsePointMarker(wasmContext, {
467
- width: this.config.pointSize ?? 8,
468
- height: this.config.pointSize ?? 8,
469
- fill: color,
470
- stroke: color,
471
- strokeThickness: 0
472
- });
473
- }
474
- if (this.config.animation !== false) {
475
- lineSeries.animation = new SweepAnimation({
476
- duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
477
- });
478
- }
479
- this.renderableSeries.push(lineSeries);
480
- this.surface.renderableSeries.add(lineSeries);
481
- });
482
- }
483
- /**
484
- * Set new data for the chart
485
- */
486
- setData(data) {
487
- if (!this.surface) {
488
- this.config.series = data;
489
- return;
490
- }
491
- this.clearSeries();
492
- this.config.series = data;
493
- this.addSeries(data);
494
- }
495
- /**
496
- * Update specific series data
497
- */
498
- updateSeriesData(seriesName, data) {
499
- const dataSeries = this.dataSeries.get(seriesName);
500
- if (!dataSeries) {
501
- console.warn(`Series "${seriesName}" not found`);
502
- return;
503
- }
504
- const normalized = normalizeDataPoints(data);
505
- const xValues = extractXValues(normalized);
506
- const yValues = extractYValues(normalized);
507
- dataSeries.clear();
508
- dataSeries.appendRange(xValues, yValues);
509
- }
510
- /**
511
- * Append data to a series
512
- */
513
- appendData(seriesName, data) {
514
- const dataSeries = this.dataSeries.get(seriesName);
515
- if (!dataSeries) {
516
- console.warn(`Series "${seriesName}" not found`);
517
- return;
518
- }
519
- const points = Array.isArray(data) ? data : [data];
520
- const normalized = normalizeDataPoints(points);
521
- const xValues = extractXValues(normalized);
522
- const yValues = extractYValues(normalized);
523
- dataSeries.appendRange(xValues, yValues);
524
- }
525
- /**
526
- * Clear all series
527
- */
528
- clearSeries() {
529
- if (!this.surface) return;
530
- this.renderableSeries.forEach((series) => {
531
- this.surface.renderableSeries.remove(series);
532
- series.delete();
533
- });
534
- this.renderableSeries = [];
535
- this.dataSeries.forEach((ds) => ds.delete());
536
- this.dataSeries.clear();
537
- }
538
- /**
539
- * Update chart
540
- */
541
- update() {
542
- if (!this.surface) return;
543
- this.applyTheme();
544
- this.surface.invalidateElement();
545
- }
546
- /**
547
- * Apply theme to line chart
548
- */
549
- applyTheme() {
550
- super.applyTheme();
551
- if (!this.surface) return;
552
- const colorPalette = this.theme.colorPalette ?? [];
553
- this.renderableSeries.forEach((series, index) => {
554
- const originalColor = this.config.series[index]?.color;
555
- if (!originalColor) {
556
- series.stroke = colorPalette[index % colorPalette.length];
557
- }
558
- });
559
- }
560
- /**
561
- * Destroy and clean up
562
- */
563
- destroy() {
564
- this.clearSeries();
565
- super.destroy();
566
- }
567
- };
568
- async function createLineChart(container, config) {
569
- const chart = new LineChart(config);
570
- await chart.init(container);
571
- return chart;
572
- }
573
- function getSciChartTheme2(themeName) {
574
- switch (themeName) {
575
- case "light":
576
- return new SciChartJSLightTheme();
577
- case "dark":
578
- case "modern":
579
- case "midnight":
580
- default:
581
- return new SciChartJSDarkTheme();
582
- }
583
- }
584
- var BarChart = class extends BaseChart {
585
- constructor(config) {
586
- super(config);
587
- this.dataSeries = /* @__PURE__ */ new Map();
588
- this.renderableSeries = [];
589
- this.wasmContext = null;
590
- }
591
- /**
592
- * Create the SciChart surface for bar chart
593
- */
594
- async createSurface() {
595
- if (!this.container) {
596
- throw new Error("Container not set");
597
- }
598
- const sciChartTheme = getSciChartTheme2(this.config.theme);
599
- if (!this.container.id) {
600
- this.container.id = this.id;
601
- }
602
- const { sciChartSurface, wasmContext } = await SciChartSurface.create(
603
- this.container,
604
- {
605
- theme: sciChartTheme
606
- }
607
- );
608
- this.surface = sciChartSurface;
609
- this.wasmContext = wasmContext;
610
- const xAxis = new NumericAxis(wasmContext, {
611
- axisTitle: this.config.xAxis?.title,
612
- drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? false,
613
- drawMinorGridLines: false,
614
- axisTitleStyle: {
615
- fontSize: 14,
616
- fontFamily: this.theme.fontFamily,
617
- color: this.theme.axis?.titleColor
618
- },
619
- labelStyle: {
620
- fontSize: 12,
621
- fontFamily: this.theme.fontFamily,
622
- color: this.theme.axis?.labelColor
623
- },
624
- autoRange: EAutoRange.Always
625
- });
626
- const yAxis = new NumericAxis(wasmContext, {
627
- axisTitle: this.config.yAxis?.title,
628
- drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
629
- drawMinorGridLines: false,
630
- axisTitleStyle: {
631
- fontSize: 14,
632
- fontFamily: this.theme.fontFamily,
633
- color: this.theme.axis?.titleColor
634
- },
635
- labelStyle: {
636
- fontSize: 12,
637
- fontFamily: this.theme.fontFamily,
638
- color: this.theme.axis?.labelColor
639
- },
640
- autoRange: EAutoRange.Always,
641
- growBy: new NumberRange(0, 0.1)
642
- // Add 10% padding at top
643
- });
644
- if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
645
- xAxis.visibleRange = new NumberRange(this.config.xAxis.min, this.config.xAxis.max);
646
- xAxis.autoRange = EAutoRange.Never;
647
- }
648
- if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
649
- yAxis.visibleRange = new NumberRange(this.config.yAxis.min, this.config.yAxis.max);
650
- yAxis.autoRange = EAutoRange.Never;
651
- }
652
- sciChartSurface.xAxes.add(xAxis);
653
- sciChartSurface.yAxes.add(yAxis);
654
- if (this.config.tooltip?.enabled !== false) {
655
- sciChartSurface.chartModifiers.add(
656
- new RolloverModifier({
657
- showTooltip: true,
658
- showAxisLabel: true
659
- })
660
- );
661
- }
662
- sciChartSurface.chartModifiers.add(new ZoomPanModifier());
663
- this.addSeries(this.config.series);
664
- }
665
- /**
666
- * Add series to the chart
667
- */
668
- addSeries(seriesConfigs) {
669
- if (!this.surface || !this.wasmContext) return;
670
- const wasmContext = this.wasmContext;
671
- const colorPalette = this.theme.colorPalette ?? [];
672
- const seriesCount = seriesConfigs.length;
673
- const dataPointWidth = this.config.barWidth ?? 0.7;
674
- seriesConfigs.forEach((seriesConfig, index) => {
675
- const data = normalizeDataPoints(seriesConfig.data);
676
- let xValues = extractXValues(data);
677
- if (!this.config.stacked && seriesCount > 1) {
678
- const offset = (index - (seriesCount - 1) / 2) * (dataPointWidth / seriesCount);
679
- xValues = xValues.map((x) => x + offset);
680
- }
681
- const yValues = extractYValues(data);
682
- const dataSeries = new XyDataSeries(wasmContext, {
683
- xValues,
684
- yValues,
685
- dataSeriesName: seriesConfig.name
686
- });
687
- this.dataSeries.set(seriesConfig.name, dataSeries);
688
- const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
689
- const columnSeries = new FastColumnRenderableSeries(wasmContext);
690
- columnSeries.dataSeries = dataSeries;
691
- columnSeries.fill = color;
692
- columnSeries.stroke = color;
693
- columnSeries.strokeThickness = 0;
694
- columnSeries.dataPointWidth = this.config.stacked ? dataPointWidth : dataPointWidth / seriesCount;
695
- columnSeries.cornerRadius = this.config.borderRadius ?? 0;
696
- if (this.config.animation !== false) {
697
- columnSeries.animation = new WaveAnimation({
698
- duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
699
- });
700
- }
701
- columnSeries.fillLinearGradient = new GradientParams(
702
- new Point(0, 0),
703
- new Point(0, 1),
704
- [
705
- { color, offset: 0 },
706
- { color: hexToRgba(color, 0.7), offset: 1 }
707
- ]
708
- );
709
- this.renderableSeries.push(columnSeries);
710
- this.surface.renderableSeries.add(columnSeries);
711
- });
712
- }
713
- /**
714
- * Set new data for the chart
715
- */
716
- setData(data) {
717
- if (!this.surface) {
718
- this.config.series = data;
719
- return;
720
- }
721
- this.clearSeries();
722
- this.config.series = data;
723
- this.addSeries(data);
724
- }
725
- /**
726
- * Update specific series data
727
- */
728
- updateSeriesData(seriesName, data) {
729
- const dataSeries = this.dataSeries.get(seriesName);
730
- if (!dataSeries) {
731
- console.warn(`Series "${seriesName}" not found`);
732
- return;
733
- }
734
- const normalized = normalizeDataPoints(data);
735
- const xValues = extractXValues(normalized);
736
- const yValues = extractYValues(normalized);
737
- dataSeries.clear();
738
- dataSeries.appendRange(xValues, yValues);
739
- }
740
- /**
741
- * Clear all series
742
- */
743
- clearSeries() {
744
- if (!this.surface) return;
745
- this.renderableSeries.forEach((series) => {
746
- this.surface.renderableSeries.remove(series);
747
- series.delete();
748
- });
749
- this.renderableSeries = [];
750
- this.dataSeries.forEach((ds) => ds.delete());
751
- this.dataSeries.clear();
752
- }
753
- /**
754
- * Update chart
755
- */
756
- update() {
757
- if (!this.surface) return;
758
- this.applyTheme();
759
- this.surface.invalidateElement();
760
- }
761
- /**
762
- * Destroy and clean up
763
- */
764
- destroy() {
765
- this.clearSeries();
766
- super.destroy();
767
- }
768
- };
769
- async function createBarChart(container, config) {
770
- const chart = new BarChart(config);
771
- await chart.init(container);
772
- return chart;
773
- }
774
- function getSciChartTheme3(themeName) {
775
- switch (themeName) {
776
- case "light":
777
- return new SciChartJSLightTheme();
778
- case "dark":
779
- case "modern":
780
- case "midnight":
781
- default:
782
- return new SciChartJSDarkTheme();
783
- }
784
- }
785
- var AreaChart = class extends BaseChart {
786
- constructor(config) {
787
- super(config);
788
- this.dataSeries = /* @__PURE__ */ new Map();
789
- this.renderableSeries = [];
790
- this.wasmContext = null;
791
- }
792
- /**
793
- * Create the SciChart surface for area chart
794
- */
795
- async createSurface() {
796
- if (!this.container) {
797
- throw new Error("Container not set");
798
- }
799
- const sciChartTheme = getSciChartTheme3(this.config.theme);
800
- if (!this.container.id) {
801
- this.container.id = this.id;
802
- }
803
- const { sciChartSurface, wasmContext } = await SciChartSurface.create(
804
- this.container,
805
- {
806
- theme: sciChartTheme
807
- }
808
- );
809
- this.surface = sciChartSurface;
810
- this.wasmContext = wasmContext;
811
- const xAxis = new NumericAxis(wasmContext, {
812
- axisTitle: this.config.xAxis?.title,
813
- drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? true,
814
- drawMinorGridLines: false,
815
- axisTitleStyle: {
816
- fontSize: 14,
817
- fontFamily: this.theme.fontFamily,
818
- color: this.theme.axis?.titleColor
819
- },
820
- labelStyle: {
821
- fontSize: 12,
822
- fontFamily: this.theme.fontFamily,
823
- color: this.theme.axis?.labelColor
824
- },
825
- autoRange: EAutoRange.Always
826
- });
827
- const yAxis = new NumericAxis(wasmContext, {
828
- axisTitle: this.config.yAxis?.title,
829
- drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
830
- drawMinorGridLines: false,
831
- axisTitleStyle: {
832
- fontSize: 14,
833
- fontFamily: this.theme.fontFamily,
834
- color: this.theme.axis?.titleColor
835
- },
836
- labelStyle: {
837
- fontSize: 12,
838
- fontFamily: this.theme.fontFamily,
839
- color: this.theme.axis?.labelColor
840
- },
841
- autoRange: EAutoRange.Always,
842
- growBy: new NumberRange(0, 0.1)
843
- });
844
- if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
845
- xAxis.visibleRange = new NumberRange(this.config.xAxis.min, this.config.xAxis.max);
846
- xAxis.autoRange = EAutoRange.Never;
847
- }
848
- if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
849
- yAxis.visibleRange = new NumberRange(this.config.yAxis.min, this.config.yAxis.max);
850
- yAxis.autoRange = EAutoRange.Never;
851
- }
852
- sciChartSurface.xAxes.add(xAxis);
853
- sciChartSurface.yAxes.add(yAxis);
854
- if (this.config.tooltip?.enabled !== false) {
855
- sciChartSurface.chartModifiers.add(
856
- new RolloverModifier({
857
- showTooltip: true,
858
- showAxisLabel: true
859
- })
860
- );
861
- }
862
- sciChartSurface.chartModifiers.add(new ZoomPanModifier());
863
- sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
864
- this.addSeries(this.config.series);
865
- }
866
- /**
867
- * Add series to the chart
868
- */
869
- addSeries(seriesConfigs) {
870
- if (!this.surface || !this.wasmContext) return;
871
- const wasmContext = this.wasmContext;
872
- const colorPalette = this.theme.colorPalette ?? [];
873
- const fillOpacity = this.config.fillOpacity ?? 0.5;
874
- seriesConfigs.forEach((seriesConfig, index) => {
875
- const data = normalizeDataPoints(seriesConfig.data);
876
- const xValues = extractXValues(data);
877
- const yValues = extractYValues(data);
878
- const dataSeries = new XyDataSeries(wasmContext, {
879
- xValues,
880
- yValues,
881
- dataSeriesName: seriesConfig.name
882
- });
883
- this.dataSeries.set(seriesConfig.name, dataSeries);
884
- const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
885
- const areaSeries = new FastMountainRenderableSeries(wasmContext, {
886
- dataSeries,
887
- stroke: color,
888
- strokeThickness: this.config.lineWidth ?? 2,
889
- fill: hexToRgba(color, fillOpacity),
890
- ...this.config.animation !== false && {
891
- animation: new SweepAnimation({
892
- duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
893
- })
894
- }
895
- });
896
- areaSeries.fillLinearGradient = new GradientParams(
897
- new Point(0, 0),
898
- new Point(0, 1),
899
- [
900
- { color: hexToRgba(color, fillOpacity), offset: 0 },
901
- { color: hexToRgba(color, 0.05), offset: 1 }
902
- ]
903
- );
904
- this.renderableSeries.push(areaSeries);
905
- this.surface.renderableSeries.add(areaSeries);
906
- });
907
- }
908
- /**
909
- * Set new data for the chart
910
- */
911
- setData(data) {
912
- if (!this.surface) {
913
- this.config.series = data;
914
- return;
915
- }
916
- this.clearSeries();
917
- this.config.series = data;
918
- this.addSeries(data);
919
- }
920
- /**
921
- * Update specific series data
922
- */
923
- updateSeriesData(seriesName, data) {
924
- const dataSeries = this.dataSeries.get(seriesName);
925
- if (!dataSeries) {
926
- console.warn(`Series "${seriesName}" not found`);
927
- return;
928
- }
929
- const normalized = normalizeDataPoints(data);
930
- const xValues = extractXValues(normalized);
931
- const yValues = extractYValues(normalized);
932
- dataSeries.clear();
933
- dataSeries.appendRange(xValues, yValues);
934
- }
935
- /**
936
- * Clear all series
937
- */
938
- clearSeries() {
939
- if (!this.surface) return;
940
- this.renderableSeries.forEach((series) => {
941
- this.surface.renderableSeries.remove(series);
942
- series.delete();
943
- });
944
- this.renderableSeries = [];
945
- this.dataSeries.forEach((ds) => ds.delete());
946
- this.dataSeries.clear();
947
- }
948
- /**
949
- * Update chart
950
- */
951
- update() {
952
- if (!this.surface) return;
953
- this.applyTheme();
954
- this.surface.invalidateElement();
955
- }
956
- /**
957
- * Destroy and clean up
958
- */
959
- destroy() {
960
- this.clearSeries();
961
- super.destroy();
962
- }
963
- };
964
- async function createAreaChart(container, config) {
965
- const chart = new AreaChart(config);
966
- await chart.init(container);
967
- return chart;
968
- }
969
- function getSciChartTheme4(themeName) {
970
- switch (themeName) {
971
- case "light":
972
- return new SciChartJSLightTheme();
973
- case "dark":
974
- case "modern":
975
- case "midnight":
976
- default:
977
- return new SciChartJSDarkTheme();
978
- }
979
- }
980
- var defaultColorStops = [
981
- { offset: 0, color: "#000080" },
982
- // Dark blue
983
- { offset: 0.2, color: "#0000ff" },
984
- // Blue
985
- { offset: 0.4, color: "#00ffff" },
986
- // Cyan
987
- { offset: 0.6, color: "#00ff00" },
988
- // Green
989
- { offset: 0.8, color: "#ffff00" },
990
- // Yellow
991
- { offset: 1, color: "#ff0000" }
992
- // Red
993
- ];
994
- var HeatmapChart = class extends BaseChart {
995
- constructor(config) {
996
- super(config);
997
- this.heatmapDataSeries = null;
998
- this.heatmapSeries = null;
999
- this.wasmContext = null;
1000
- }
1001
- /**
1002
- * Create the SciChart surface for heatmap chart
1003
- */
1004
- async createSurface() {
1005
- if (!this.container) {
1006
- throw new Error("Container not set");
1007
- }
1008
- const sciChartTheme = getSciChartTheme4(this.config.theme);
1009
- if (!this.container.id) {
1010
- this.container.id = this.id;
1011
- }
1012
- const { sciChartSurface, wasmContext } = await SciChartSurface.create(
1013
- this.container,
1014
- {
1015
- theme: sciChartTheme
1016
- }
1017
- );
1018
- this.surface = sciChartSurface;
1019
- this.wasmContext = wasmContext;
1020
- const xAxis = new NumericAxis(wasmContext, {
1021
- axisTitle: this.config.xAxis?.title,
1022
- drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? false,
1023
- drawMinorGridLines: false,
1024
- axisTitleStyle: {
1025
- fontSize: 14,
1026
- fontFamily: this.theme.fontFamily,
1027
- color: this.theme.axis?.titleColor
1028
- },
1029
- labelStyle: {
1030
- fontSize: 12,
1031
- fontFamily: this.theme.fontFamily,
1032
- color: this.theme.axis?.labelColor
1033
- },
1034
- autoRange: EAutoRange.Always
1035
- });
1036
- const yAxis = new NumericAxis(wasmContext, {
1037
- axisTitle: this.config.yAxis?.title,
1038
- drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? false,
1039
- drawMinorGridLines: false,
1040
- axisTitleStyle: {
1041
- fontSize: 14,
1042
- fontFamily: this.theme.fontFamily,
1043
- color: this.theme.axis?.titleColor
1044
- },
1045
- labelStyle: {
1046
- fontSize: 12,
1047
- fontFamily: this.theme.fontFamily,
1048
- color: this.theme.axis?.labelColor
1049
- },
1050
- autoRange: EAutoRange.Always
1051
- });
1052
- if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
1053
- xAxis.visibleRange = new NumberRange(this.config.xAxis.min, this.config.xAxis.max);
1054
- xAxis.autoRange = EAutoRange.Never;
1055
- }
1056
- if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
1057
- yAxis.visibleRange = new NumberRange(this.config.yAxis.min, this.config.yAxis.max);
1058
- yAxis.autoRange = EAutoRange.Never;
1059
- }
1060
- sciChartSurface.xAxes.add(xAxis);
1061
- sciChartSurface.yAxes.add(yAxis);
1062
- if (this.config.tooltip?.enabled !== false) {
1063
- sciChartSurface.chartModifiers.add(
1064
- new RolloverModifier({
1065
- showTooltip: true,
1066
- showAxisLabel: true
1067
- })
1068
- );
1069
- }
1070
- sciChartSurface.chartModifiers.add(new ZoomPanModifier());
1071
- sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
1072
- this.addHeatmapData(this.config.zValues);
1073
- }
1074
- /**
1075
- * Add heatmap data to the chart
320
+ * Add event listener
1076
321
  */
1077
- addHeatmapData(zValues) {
1078
- if (!this.surface || !this.wasmContext) return;
1079
- const wasmContext = this.wasmContext;
1080
- let min = this.config.colorMin;
1081
- let max = this.config.colorMax;
1082
- if (min === void 0 || max === void 0) {
1083
- const flatValues = zValues.flat();
1084
- min = min ?? Math.min(...flatValues);
1085
- max = max ?? Math.max(...flatValues);
1086
- }
1087
- this.heatmapDataSeries = new UniformHeatmapDataSeries(wasmContext, {
1088
- zValues,
1089
- xStart: this.config.xStart ?? 0,
1090
- xStep: this.config.xStep ?? 1,
1091
- yStart: this.config.yStart ?? 0,
1092
- yStep: this.config.yStep ?? 1
1093
- });
1094
- const colorStops = this.config.colorStops ?? defaultColorStops;
1095
- this.heatmapSeries = new UniformHeatmapRenderableSeries(wasmContext, {
1096
- dataSeries: this.heatmapDataSeries,
1097
- colorMap: new HeatmapColorMap({
1098
- minimum: min,
1099
- maximum: max,
1100
- gradientStops: colorStops
1101
- })
1102
- });
1103
- this.surface.renderableSeries.add(this.heatmapSeries);
322
+ on(event, handler) {
323
+ if (!this.eventHandlers.has(event)) {
324
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
325
+ }
326
+ this.eventHandlers.get(event).add(handler);
1104
327
  }
1105
328
  /**
1106
- * Set new data for the chart (for heatmap, this updates zValues)
329
+ * Remove event listener
1107
330
  */
1108
- setData(_data) {
1109
- console.warn("HeatmapChart.setData() - use setZValues() for updating heatmap data");
331
+ off(event, handler) {
332
+ const handlers = this.eventHandlers.get(event);
333
+ if (handlers) {
334
+ handlers.delete(handler);
335
+ }
1110
336
  }
1111
337
  /**
1112
- * Set new z-values for the heatmap
338
+ * Emit an event
1113
339
  */
1114
- setZValues(zValues) {
1115
- if (!this.surface) {
1116
- this.config.zValues = zValues;
1117
- return;
340
+ emit(event, data) {
341
+ const handlers = this.eventHandlers.get(event);
342
+ if (handlers) {
343
+ handlers.forEach((handler) => handler(data));
1118
344
  }
1119
- this.clearHeatmap();
1120
- this.config.zValues = zValues;
1121
- this.addHeatmapData(zValues);
1122
345
  }
1123
346
  /**
1124
- * Update specific cell values
347
+ * Destroy the chart and clean up resources
1125
348
  */
1126
- updateCell(x, y, value) {
1127
- if (this.heatmapDataSeries) {
1128
- this.heatmapDataSeries.setZValue(x, y, value);
349
+ destroy() {
350
+ if (this.isDestroyed) return;
351
+ if (this.resizeObserver) {
352
+ this.resizeObserver.disconnect();
353
+ this.resizeObserver = null;
354
+ }
355
+ this.eventHandlers.clear();
356
+ if (this.surface) {
357
+ this.surface.delete();
358
+ this.surface = null;
359
+ }
360
+ if (this.container) {
361
+ this.container.innerHTML = "";
1129
362
  }
363
+ this.isDestroyed = true;
364
+ this.isInitialized = false;
1130
365
  }
1131
366
  /**
1132
- * Clear heatmap data
367
+ * Get current configuration
1133
368
  */
1134
- clearHeatmap() {
1135
- if (!this.surface) return;
1136
- if (this.heatmapSeries) {
1137
- this.surface.renderableSeries.remove(this.heatmapSeries);
1138
- this.heatmapSeries.delete();
1139
- this.heatmapSeries = null;
1140
- }
1141
- if (this.heatmapDataSeries) {
1142
- this.heatmapDataSeries.delete();
1143
- this.heatmapDataSeries = null;
1144
- }
369
+ getConfig() {
370
+ return { ...this.config };
1145
371
  }
1146
372
  /**
1147
- * Update chart
373
+ * Get current theme
1148
374
  */
1149
- update() {
1150
- if (!this.surface) return;
1151
- this.applyTheme();
1152
- this.surface.invalidateElement();
375
+ getTheme() {
376
+ return { ...this.theme };
1153
377
  }
1154
378
  /**
1155
- * Destroy and clean up
379
+ * Check if chart is initialized
1156
380
  */
1157
- destroy() {
1158
- this.clearHeatmap();
1159
- super.destroy();
381
+ isReady() {
382
+ return this.isInitialized && !this.isDestroyed;
1160
383
  }
1161
384
  };
1162
- async function createHeatmapChart(container, config) {
1163
- const chart = new HeatmapChart(config);
1164
- await chart.init(container);
1165
- return chart;
1166
- }
1167
- var SCICHART_VERSION2 = "3.5.750";
385
+ var SCICHART_VERSION2 = "4.0.933";
1168
386
  var sciChart3DConfigured = false;
1169
387
  function ensureSciChart3DConfigured() {
1170
388
  if (sciChart3DConfigured) return;
@@ -1174,15 +392,14 @@ function ensureSciChart3DConfigured() {
1174
392
  } catch {
1175
393
  try {
1176
394
  SciChart3DSurface.configure({
1177
- wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION2}/_wasm/scichart3d.wasm`,
1178
- dataUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION2}/_wasm/scichart3d.data`
395
+ wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION2}/_wasm/scichart3d.wasm`
1179
396
  });
1180
397
  sciChart3DConfigured = true;
1181
398
  } catch {
1182
399
  }
1183
400
  }
1184
401
  }
1185
- var defaultColorStops2 = [
402
+ var defaultColorStops = [
1186
403
  { offset: 0, color: "#1e3a8a" },
1187
404
  // Dark blue
1188
405
  { offset: 0.25, color: "#3b82f6" },
@@ -1279,7 +496,7 @@ var Surface3DChart = class {
1279
496
  xStep: this.config.xStep ?? 1,
1280
497
  zStep: this.config.zStep ?? 1
1281
498
  });
1282
- const colorStops = this.config.colorStops ?? defaultColorStops2;
499
+ const colorStops = this.config.colorStops ?? defaultColorStops;
1283
500
  const colorPalette = new GradientColorPalette(wasmContext, {
1284
501
  gradientStops: colorStops
1285
502
  });
@@ -1382,7 +599,7 @@ async function createSurface3DChart(container, config) {
1382
599
  await chart.init(container);
1383
600
  return chart;
1384
601
  }
1385
- var SCICHART_VERSION3 = "3.5.750";
602
+ var SCICHART_VERSION3 = "4.0.933";
1386
603
  var sciChart3DConfigured2 = false;
1387
604
  function ensureSciChart3DConfigured2() {
1388
605
  if (sciChart3DConfigured2) return;
@@ -1392,8 +609,7 @@ function ensureSciChart3DConfigured2() {
1392
609
  } catch {
1393
610
  try {
1394
611
  SciChart3DSurface.configure({
1395
- wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION3}/_wasm/scichart3d.wasm`,
1396
- dataUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION3}/_wasm/scichart3d.data`
612
+ wasmUrl: `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION3}/_wasm/scichart3d.wasm`
1397
613
  });
1398
614
  sciChart3DConfigured2 = true;
1399
615
  } catch {
@@ -1641,18 +857,555 @@ async function createColumn3DChart(container, config) {
1641
857
  await chart.init(container);
1642
858
  return chart;
1643
859
  }
860
+ var HORIZONTAL_RESOLUTION = 360;
861
+ var VERTICAL_SCALE_MAX_DEFAULT = 5e3;
862
+ var HORIZONTAL_RESOLUTION_MULTIPLIER = 1;
863
+ var RESOLUTION_CONFIG = {
864
+ UNI: {
865
+ HI: { VERTICAL_RESOLUTION: 256, VERTICAL_OFFSET: 0, MIN_PEAK_ZERO: true },
866
+ LO: { VERTICAL_RESOLUTION: 100, VERTICAL_OFFSET: 0, MIN_PEAK_ZERO: true }
867
+ },
868
+ BI: {
869
+ HI: { VERTICAL_RESOLUTION: 512, VERTICAL_OFFSET: 256, MIN_PEAK_ZERO: false },
870
+ LO: { VERTICAL_RESOLUTION: 200, VERTICAL_OFFSET: 100, MIN_PEAK_ZERO: false }
871
+ }
872
+ };
873
+ var defaultPRPDColorStops = [
874
+ { offset: 0, color: "transparent" },
875
+ { offset: 5e-3, color: "transparent" },
876
+ { offset: 9e-3, color: "transparent" },
877
+ { offset: 0.01, color: "CornflowerBlue" },
878
+ { offset: 0.4, color: "DarkGreen" },
879
+ { offset: 0.6, color: "Chartreuse" },
880
+ { offset: 0.8, color: "Yellow" },
881
+ { offset: 1, color: "Red" }
882
+ ];
883
+ var createPRPDTheme = () => {
884
+ const theme = new SciChartJSLightTheme();
885
+ theme.sciChartBackground = "#f9f9f9";
886
+ theme.gridBackgroundBrush = "grey";
887
+ theme.axisBandsFill = "#dcdcdc";
888
+ theme.majorGridLineBrush = "#888888";
889
+ theme.minorGridLineBrush = "transparent";
890
+ return theme;
891
+ };
892
+ var createLegendTheme = () => {
893
+ const theme = new SciChartJSLightTheme();
894
+ theme.sciChartBackground = "#ffffff";
895
+ theme.gridBackgroundBrush = "#ffffff";
896
+ theme.axisBandsFill = "#ffffff";
897
+ theme.majorGridLineBrush = "transparent";
898
+ theme.minorGridLineBrush = "transparent";
899
+ return theme;
900
+ };
901
+ function getResolutionConfig(uniBiLabel, hiLoLabel, maxPeak, minPeak, isLowResolution) {
902
+ const cfg = isLowResolution ? RESOLUTION_CONFIG.UNI.HI : RESOLUTION_CONFIG?.[uniBiLabel]?.[hiLoLabel] ?? RESOLUTION_CONFIG.BI.HI;
903
+ const newMinPeak = cfg.MIN_PEAK_ZERO ? 0 : minPeak ?? -5e3;
904
+ const newMaxPeak = maxPeak ?? 5e3;
905
+ return {
906
+ verticalResolution: cfg.VERTICAL_RESOLUTION,
907
+ verticalOffset: cfg.VERTICAL_OFFSET,
908
+ newMinPeak,
909
+ newMaxPeak,
910
+ isUnipolar: uniBiLabel === "UNI" || isLowResolution
911
+ };
912
+ }
913
+ function getPhaseColumnIndex(phaseAngle, maxPhaseAngle) {
914
+ const maxPhase = maxPhaseAngle || 360;
915
+ if (maxPhase <= 0) return 0;
916
+ const clampedPhase = Math.min(Math.max(phaseAngle, 0), maxPhase);
917
+ const ratio = clampedPhase / maxPhase;
918
+ return Math.min(HORIZONTAL_RESOLUTION - 1, Math.floor(ratio * (HORIZONTAL_RESOLUTION - 1)));
919
+ }
920
+ function generateSineWaveData(startX, endX, amplitude, frequency = 1, phaseShift = 0, step = 1, offset = 0) {
921
+ const data = [];
922
+ for (let x = startX; x <= endX; x += step) {
923
+ const rad = (x - phaseShift) * Math.PI * frequency / 180;
924
+ const y = offset + amplitude * Math.sin(rad);
925
+ data.push([x, y]);
926
+ }
927
+ return data;
928
+ }
929
+ function buildZValues(data, scalingFactor, minPeak, maxPhaseAngle, verticalScaleMax, uniBiLabel, hiLoLabel, windowingData = [], isLowResolution) {
930
+ const { verticalResolution, verticalOffset, newMinPeak, newMaxPeak, isUnipolar } = getResolutionConfig(uniBiLabel, hiLoLabel, verticalScaleMax, minPeak, isLowResolution);
931
+ const zValues = Array.from(
932
+ { length: verticalResolution },
933
+ () => new Array(HORIZONTAL_RESOLUTION).fill(0)
934
+ );
935
+ const vResolution = newMinPeak === 0 ? verticalResolution : verticalResolution / 2;
936
+ const multiplier = newMaxPeak * scalingFactor / vResolution;
937
+ let maxValue = 0;
938
+ let totalCount = 0;
939
+ const isInsideWindow = (phaseDeg, ampVal) => {
940
+ if (!windowingData?.length) return false;
941
+ return windowingData.some(
942
+ (w) => phaseDeg >= w.minPhase && phaseDeg <= w.maxPhase && ampVal >= w.minAmp && ampVal <= w.maxAmp
943
+ );
944
+ };
945
+ data?.forEach(([phase_angle, amplitude, count]) => {
946
+ const colIndex = getPhaseColumnIndex(phase_angle, maxPhaseAngle);
947
+ const scaledAmp = Math.floor(
948
+ (isUnipolar ? Math.abs(amplitude) : amplitude) * scalingFactor
949
+ );
950
+ if (isInsideWindow(phase_angle, scaledAmp)) {
951
+ return;
952
+ }
953
+ let rowIndex = Math.floor(scaledAmp / multiplier + verticalOffset);
954
+ rowIndex = Math.max(0, Math.min(verticalResolution - 1, rowIndex));
955
+ zValues[rowIndex][colIndex] += count;
956
+ if (Math.abs(scaledAmp) > Math.abs(maxValue)) maxValue = scaledAmp;
957
+ totalCount += count;
958
+ });
959
+ return {
960
+ zValues,
961
+ multiplier,
962
+ maxValue,
963
+ totalCount,
964
+ verticalResolution,
965
+ isUnipolar,
966
+ newMinPeak
967
+ };
968
+ }
969
+ var PRPDChart = class {
970
+ constructor(config) {
971
+ this.container = null;
972
+ // Root container (may contain sub-divs)
973
+ this.chartHost = null;
974
+ // Div where SciChartSurface is mounted
975
+ this.surface = null;
976
+ this.wasmContext = null;
977
+ this.isDestroyed = false;
978
+ // Chart components
979
+ this.heatmapDataSeries = null;
980
+ this.heatmapSeries = null;
981
+ this.heatmapColorMap = null;
982
+ this.heatmapLegend = null;
983
+ this.heatmapLegendDiv = null;
984
+ this.sineDataSeries = null;
985
+ this.sineLineSeries = null;
986
+ this.xAxis = null;
987
+ this.yAxis = null;
988
+ // Statistics
989
+ this.stats = { peakValue: 0, totalCount: 0 };
990
+ this.id = config.id ?? generateId("prpd");
991
+ this.config = {
992
+ scalingFactor: 1,
993
+ unitOfMeasurement: "mVp",
994
+ maxPeak: 5e3,
995
+ minPeak: -5e3,
996
+ maxPhaseAngle: 360,
997
+ resolutionLabel: { UniBi: "BI", HiLo: "HI" },
998
+ windowingData: [],
999
+ yAxisRange: 5e3,
1000
+ isLowResolution: false,
1001
+ showColorPalette: true,
1002
+ showSineWave: true,
1003
+ colorMin: 0,
1004
+ colorMax: 100,
1005
+ ...config
1006
+ };
1007
+ }
1008
+ /**
1009
+ * Initialize the chart in the given container
1010
+ */
1011
+ async init(container) {
1012
+ if (this.isDestroyed) {
1013
+ throw new Error("Cannot initialize a destroyed chart");
1014
+ }
1015
+ if (typeof container === "string") {
1016
+ const el = document.getElementById(container);
1017
+ if (!el) {
1018
+ throw new Error(`Container element "${container}" not found`);
1019
+ }
1020
+ this.container = el;
1021
+ } else {
1022
+ this.container = container;
1023
+ }
1024
+ if (!this.container.id) {
1025
+ this.container.id = this.id;
1026
+ }
1027
+ const chartGraph = this.container.querySelector(".chart-graph");
1028
+ this.chartHost = chartGraph ?? this.container;
1029
+ if (!this.chartHost.id) {
1030
+ this.chartHost.id = `${this.id}_host`;
1031
+ }
1032
+ await this.createSurface();
1033
+ }
1034
+ /**
1035
+ * Create the SciChart surface
1036
+ */
1037
+ async createSurface() {
1038
+ if (!this.container || !this.chartHost) {
1039
+ throw new Error("Container not set");
1040
+ }
1041
+ const theme = createPRPDTheme();
1042
+ const { sciChartSurface, wasmContext } = await SciChartSurface.create(
1043
+ this.chartHost,
1044
+ { theme }
1045
+ );
1046
+ this.surface = sciChartSurface;
1047
+ this.wasmContext = wasmContext;
1048
+ const verticalScaleMax = this.config.maxPeak || VERTICAL_SCALE_MAX_DEFAULT;
1049
+ const { zValues, multiplier, maxValue, totalCount, verticalResolution, isUnipolar } = buildZValues(
1050
+ this.config.data,
1051
+ this.config.scalingFactor,
1052
+ this.config.minPeak,
1053
+ this.config.maxPhaseAngle,
1054
+ verticalScaleMax,
1055
+ this.config.resolutionLabel?.UniBi ?? "BI",
1056
+ this.config.resolutionLabel?.HiLo ?? "HI",
1057
+ this.config.windowingData,
1058
+ this.config.isLowResolution
1059
+ );
1060
+ this.stats = { peakValue: maxValue, totalCount };
1061
+ const yAxisRange = this.config.yAxisRange || verticalScaleMax;
1062
+ this.xAxis = new NumericAxis(wasmContext, {
1063
+ autoRange: EAutoRange.Never,
1064
+ labelFormat: ENumericFormat.Decimal,
1065
+ labelPrecision: 0,
1066
+ labelPostfix: "\xB0",
1067
+ minorDelta: 2,
1068
+ majorDelta: 45,
1069
+ drawMajorBands: true,
1070
+ autoTicks: false,
1071
+ axisAlignment: EAxisAlignment.Bottom,
1072
+ axisTitle: "Phase Angle (\xB0)",
1073
+ axisTitleStyle: {
1074
+ fontSize: 14,
1075
+ fontWeight: "bold",
1076
+ color: "black"
1077
+ },
1078
+ visibleRange: new NumberRange(0, 360),
1079
+ visibleRangeLimit: new NumberRange(0, 360)
1080
+ });
1081
+ const yRange = isUnipolar ? new NumberRange(0, yAxisRange) : new NumberRange(-yAxisRange, yAxisRange);
1082
+ this.yAxis = new NumericAxis(wasmContext, {
1083
+ autoRange: EAutoRange.Never,
1084
+ labelFormat: ENumericFormat.Decimal,
1085
+ labelPrecision: 0,
1086
+ drawMajorBands: true,
1087
+ axisAlignment: EAxisAlignment.Right,
1088
+ axisTitle: `Amplitude (${this.config.unitOfMeasurement})`,
1089
+ axisTitleStyle: {
1090
+ fontSize: 14,
1091
+ fontWeight: "bold",
1092
+ color: "black",
1093
+ rotation: 270
1094
+ },
1095
+ visibleRange: yRange,
1096
+ visibleRangeLimit: yRange
1097
+ });
1098
+ sciChartSurface.xAxes.add(this.xAxis);
1099
+ sciChartSurface.yAxes.add(this.yAxis);
1100
+ this.createHeatmap(zValues, multiplier, verticalResolution, isUnipolar);
1101
+ if (this.config.showSineWave) {
1102
+ this.createSineWave(yAxisRange, isUnipolar);
1103
+ }
1104
+ const cursorModifier = new CursorModifier();
1105
+ cursorModifier.axisLabelFill = "#FFFFFF";
1106
+ cursorModifier.axisLabelStroke = "#000000";
1107
+ sciChartSurface.chartModifiers.add(
1108
+ cursorModifier,
1109
+ new RubberBandXyZoomModifier(),
1110
+ new ZoomExtentsModifier()
1111
+ );
1112
+ if (this.config.showColorPalette) {
1113
+ await this.createHeatmapLegend();
1114
+ }
1115
+ this.onStatsChange?.(this.stats);
1116
+ }
1117
+ createHeatmap(zValues, multiplier, verticalResolution, isUnipolar) {
1118
+ if (!this.surface || !this.wasmContext) return;
1119
+ const colorStops = this.config.colorStops ?? defaultPRPDColorStops;
1120
+ this.heatmapColorMap = new HeatmapColorMap({
1121
+ minimum: this.config.colorMin ?? 0,
1122
+ maximum: this.config.colorMax ?? 100,
1123
+ gradientStops: colorStops
1124
+ });
1125
+ this.heatmapDataSeries = new UniformHeatmapDataSeries(this.wasmContext, {
1126
+ zValues,
1127
+ xStart: 0,
1128
+ xStep: HORIZONTAL_RESOLUTION_MULTIPLIER,
1129
+ yStart: isUnipolar ? 0 : -1 * verticalResolution * multiplier / 2,
1130
+ yStep: multiplier
1131
+ });
1132
+ this.heatmapSeries = new UniformHeatmapRenderableSeries(this.wasmContext, {
1133
+ dataSeries: this.heatmapDataSeries,
1134
+ colorMap: this.heatmapColorMap
1135
+ });
1136
+ this.surface.renderableSeries.add(this.heatmapSeries);
1137
+ }
1138
+ createSineWave(yAxisRange, isUnipolar) {
1139
+ if (!this.surface || !this.wasmContext) return;
1140
+ const sineAmplitude = isUnipolar ? yAxisRange / 2 : yAxisRange;
1141
+ const sineOffset = isUnipolar ? yAxisRange / 2 : 0;
1142
+ const sineWaveData = generateSineWaveData(0, 360, sineAmplitude, 1, 0, 1, sineOffset);
1143
+ this.sineDataSeries = new XyDataSeries(this.wasmContext);
1144
+ sineWaveData.forEach(([x, y]) => this.sineDataSeries.append(x, y));
1145
+ this.sineLineSeries = new FastLineRenderableSeries(this.wasmContext, {
1146
+ dataSeries: this.sineDataSeries,
1147
+ stroke: "Black",
1148
+ strokeThickness: 3
1149
+ });
1150
+ this.surface.renderableSeries.add(this.sineLineSeries);
1151
+ }
1152
+ async createHeatmapLegend() {
1153
+ if (!this.container || !this.heatmapColorMap) return;
1154
+ this.clearHeatmapLegend();
1155
+ let div = this.container.querySelector(".heatmap-chart");
1156
+ if (!div) {
1157
+ div = document.createElement("div");
1158
+ div.className = "heatmap-chart";
1159
+ div.style.position = "absolute";
1160
+ div.style.top = "40px";
1161
+ div.style.left = "0px";
1162
+ div.style.bottom = "40px";
1163
+ div.style.width = "65px";
1164
+ div.style.pointerEvents = "none";
1165
+ this.container.appendChild(div);
1166
+ }
1167
+ if (!div.id) {
1168
+ div.id = `${this.id}_legend`;
1169
+ }
1170
+ this.heatmapLegendDiv = div;
1171
+ const min = this.config.colorMin ?? 0;
1172
+ const max = this.config.colorMax ?? 100;
1173
+ const { heatmapLegend } = await HeatmapLegend.create(div, {
1174
+ theme: createLegendTheme(),
1175
+ yAxisOptions: {
1176
+ visibleRange: new NumberRange(min, max),
1177
+ majorDelta: (max - min) / 5,
1178
+ minorDelta: (max - min) / 10,
1179
+ labelFormat: ENumericFormat.Decimal,
1180
+ labelPrecision: 0,
1181
+ labelPadding: 6,
1182
+ axisTitleGap: 8,
1183
+ labelStyle: { fontSize: 12, color: "#A0A0A0" },
1184
+ majorTickLineStyle: {
1185
+ color: "#A0A0A0",
1186
+ tickSize: 8,
1187
+ strokeThickness: 1
1188
+ },
1189
+ minorTickLineStyle: {
1190
+ color: "gray",
1191
+ tickSize: 5,
1192
+ strokeThickness: 1
1193
+ },
1194
+ axisBorder: {
1195
+ borderLeft: 0,
1196
+ borderRight: 0,
1197
+ borderTop: 0,
1198
+ borderBottom: 0,
1199
+ color: "transparent"
1200
+ }
1201
+ },
1202
+ colorMap: this.heatmapColorMap
1203
+ });
1204
+ this.heatmapLegend = heatmapLegend;
1205
+ }
1206
+ clearHeatmapLegend() {
1207
+ if (this.heatmapLegend) {
1208
+ try {
1209
+ this.heatmapLegend.delete();
1210
+ } catch (e) {
1211
+ }
1212
+ this.heatmapLegend = null;
1213
+ }
1214
+ if (this.heatmapLegendDiv) {
1215
+ this.heatmapLegendDiv.remove();
1216
+ this.heatmapLegendDiv = null;
1217
+ }
1218
+ }
1219
+ /**
1220
+ * Update chart with new data
1221
+ */
1222
+ updateData(data) {
1223
+ this.config.data = data;
1224
+ this.refresh();
1225
+ }
1226
+ /**
1227
+ * Update resolution label (UNI/BI, HI/LO)
1228
+ */
1229
+ setResolutionLabel(label) {
1230
+ this.config.resolutionLabel = label;
1231
+ this.refresh();
1232
+ }
1233
+ /**
1234
+ * Update windowing data
1235
+ */
1236
+ setWindowingData(windowingData) {
1237
+ this.config.windowingData = windowingData;
1238
+ this.refresh();
1239
+ }
1240
+ /**
1241
+ * Update Y-axis range
1242
+ */
1243
+ setYAxisRange(range) {
1244
+ this.config.yAxisRange = range;
1245
+ this.refresh();
1246
+ }
1247
+ /**
1248
+ * Set stats change callback
1249
+ */
1250
+ onStats(callback) {
1251
+ this.onStatsChange = callback;
1252
+ }
1253
+ /**
1254
+ * Get current statistics
1255
+ */
1256
+ getStats() {
1257
+ return { ...this.stats };
1258
+ }
1259
+ /**
1260
+ * Refresh the chart with current configuration
1261
+ */
1262
+ refresh() {
1263
+ if (!this.surface || !this.wasmContext) return;
1264
+ const verticalScaleMax = this.config.maxPeak || VERTICAL_SCALE_MAX_DEFAULT;
1265
+ const yAxisRange = this.config.yAxisRange || verticalScaleMax;
1266
+ const { zValues, multiplier, maxValue, totalCount, verticalResolution, isUnipolar } = buildZValues(
1267
+ this.config.data,
1268
+ this.config.scalingFactor,
1269
+ this.config.minPeak,
1270
+ this.config.maxPhaseAngle,
1271
+ verticalScaleMax,
1272
+ this.config.resolutionLabel?.UniBi ?? "BI",
1273
+ this.config.resolutionLabel?.HiLo ?? "HI",
1274
+ this.config.windowingData,
1275
+ this.config.isLowResolution
1276
+ );
1277
+ this.stats = { peakValue: maxValue, totalCount };
1278
+ if (this.yAxis) {
1279
+ const yRange = isUnipolar ? new NumberRange(0, yAxisRange) : new NumberRange(-yAxisRange, yAxisRange);
1280
+ this.yAxis.visibleRange = yRange;
1281
+ this.yAxis.visibleRangeLimit = yRange;
1282
+ }
1283
+ if (this.heatmapDataSeries) {
1284
+ const needNewDs = this.heatmapDataSeries.arrayHeight !== verticalResolution || this.heatmapDataSeries.arrayWidth !== HORIZONTAL_RESOLUTION;
1285
+ if (needNewDs) {
1286
+ if (this.heatmapSeries) {
1287
+ this.surface.renderableSeries.remove(this.heatmapSeries);
1288
+ this.heatmapSeries.delete();
1289
+ }
1290
+ this.heatmapDataSeries.delete();
1291
+ this.heatmapDataSeries = new UniformHeatmapDataSeries(this.wasmContext, {
1292
+ zValues,
1293
+ xStart: 0,
1294
+ xStep: HORIZONTAL_RESOLUTION_MULTIPLIER,
1295
+ yStart: isUnipolar ? 0 : -1 * verticalResolution * multiplier / 2,
1296
+ yStep: multiplier
1297
+ });
1298
+ this.heatmapSeries = new UniformHeatmapRenderableSeries(this.wasmContext, {
1299
+ dataSeries: this.heatmapDataSeries,
1300
+ colorMap: this.heatmapColorMap
1301
+ });
1302
+ this.surface.renderableSeries.add(this.heatmapSeries);
1303
+ } else {
1304
+ if (typeof this.heatmapDataSeries.setZValues === "function") {
1305
+ this.heatmapDataSeries.setZValues(zValues);
1306
+ } else {
1307
+ this.heatmapDataSeries.zValues = zValues;
1308
+ }
1309
+ this.heatmapDataSeries.yStart = isUnipolar ? 0 : -1 * verticalResolution * multiplier / 2;
1310
+ this.heatmapDataSeries.yStep = multiplier;
1311
+ }
1312
+ }
1313
+ if (this.sineDataSeries && this.config.showSineWave) {
1314
+ this.sineDataSeries.clear();
1315
+ const sineAmplitude = isUnipolar ? yAxisRange / 2 : yAxisRange;
1316
+ const sineOffset = isUnipolar ? yAxisRange / 2 : 0;
1317
+ const sineWaveData = generateSineWaveData(0, 360, sineAmplitude, 1, 0, 1, sineOffset);
1318
+ sineWaveData.forEach(([x, y]) => this.sineDataSeries.append(x, y));
1319
+ }
1320
+ this.surface.invalidateElement();
1321
+ this.onStatsChange?.(this.stats);
1322
+ }
1323
+ /**
1324
+ * Set chart options
1325
+ */
1326
+ setOptions(options) {
1327
+ this.config = { ...this.config, ...options };
1328
+ this.refresh();
1329
+ }
1330
+ /**
1331
+ * Reset zoom to full extent
1332
+ */
1333
+ resetZoom() {
1334
+ if (!this.surface) return;
1335
+ this.surface.zoomExtents();
1336
+ }
1337
+ /**
1338
+ * Export chart as image
1339
+ */
1340
+ async exportImage(format = "png") {
1341
+ if (!this.container) {
1342
+ throw new Error("Chart not initialized");
1343
+ }
1344
+ const canvas = this.container.querySelector("canvas");
1345
+ if (!canvas) {
1346
+ throw new Error("Canvas not found");
1347
+ }
1348
+ const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
1349
+ return canvas.toDataURL(mimeType);
1350
+ }
1351
+ /**
1352
+ * Get current configuration
1353
+ */
1354
+ getConfig() {
1355
+ return { ...this.config };
1356
+ }
1357
+ /**
1358
+ * Check if chart is ready
1359
+ */
1360
+ isReady() {
1361
+ return this.surface !== null && !this.isDestroyed;
1362
+ }
1363
+ /**
1364
+ * Destroy and clean up
1365
+ */
1366
+ destroy() {
1367
+ if (this.isDestroyed) return;
1368
+ this.clearHeatmapLegend();
1369
+ if (this.sineLineSeries && this.surface) {
1370
+ this.surface.renderableSeries.remove(this.sineLineSeries);
1371
+ this.sineLineSeries.delete();
1372
+ this.sineLineSeries = null;
1373
+ }
1374
+ if (this.sineDataSeries) {
1375
+ this.sineDataSeries.delete();
1376
+ this.sineDataSeries = null;
1377
+ }
1378
+ if (this.heatmapSeries && this.surface) {
1379
+ this.surface.renderableSeries.remove(this.heatmapSeries);
1380
+ this.heatmapSeries.delete();
1381
+ this.heatmapSeries = null;
1382
+ }
1383
+ if (this.heatmapDataSeries) {
1384
+ this.heatmapDataSeries.delete();
1385
+ this.heatmapDataSeries = null;
1386
+ }
1387
+ if (this.surface) {
1388
+ this.surface.delete();
1389
+ this.surface = null;
1390
+ }
1391
+ this.isDestroyed = true;
1392
+ }
1393
+ };
1394
+ async function createPRPDChart(container, config) {
1395
+ const chart = new PRPDChart(config);
1396
+ await chart.init(container);
1397
+ return chart;
1398
+ }
1644
1399
  var VERSION = "0.1.1";
1645
- var SCICHART_VERSION4 = "3.5.750";
1400
+ var SCICHART_VERSION4 = "4.0.933";
1646
1401
  var DEFAULT_WASM_URL = `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION4}/_wasm/scichart2d.wasm`;
1647
- var DEFAULT_DATA_URL = `https://cdn.jsdelivr.net/npm/scichart@${SCICHART_VERSION4}/_wasm/scichart2d.data`;
1648
1402
  var isConfigured = false;
1649
1403
  function autoConfigureSciChart() {
1650
1404
  if (isConfigured) return;
1651
1405
  try {
1652
- const { SciChartSurface: SciChartSurface7 } = __require("scichart");
1653
- SciChartSurface7.configure({
1654
- wasmUrl: DEFAULT_WASM_URL,
1655
- dataUrl: DEFAULT_DATA_URL
1406
+ const { SciChartSurface: SciChartSurface4 } = __require("scichart");
1407
+ SciChartSurface4.configure({
1408
+ wasmUrl: DEFAULT_WASM_URL
1656
1409
  });
1657
1410
  isConfigured = true;
1658
1411
  } catch {
@@ -1661,16 +1414,15 @@ function autoConfigureSciChart() {
1661
1414
  autoConfigureSciChart();
1662
1415
  function configureSciChart(options) {
1663
1416
  try {
1664
- const { SciChartSurface: SciChartSurface7 } = __require("scichart");
1665
- SciChartSurface7.configure({
1666
- wasmUrl: options.wasmUrl || DEFAULT_WASM_URL,
1667
- dataUrl: options.dataUrl || DEFAULT_DATA_URL
1417
+ const { SciChartSurface: SciChartSurface4 } = __require("scichart");
1418
+ SciChartSurface4.configure({
1419
+ wasmUrl: options.wasmUrl || DEFAULT_WASM_URL
1668
1420
  });
1669
1421
  isConfigured = true;
1670
1422
  } catch {
1671
1423
  }
1672
1424
  }
1673
1425
 
1674
- export { AreaChart, BarChart, BaseChart, Column3DChart, HeatmapChart, LineChart, Surface3DChart, VERSION, calculateDataRange, clamp, configureSciChart, createAreaChart, createBarChart, createColumn3DChart, createHeatmapChart, createLineChart, createSurface3DChart, debounce, deepMerge, extractXValues, extractYValues, formatNumber, generateId, hexToRgba, lerp, normalizeDataPoints, parseSize, throttle };
1426
+ export { BaseChart, Column3DChart, PRPDChart, Surface3DChart, VERSION, calculateDataRange, clamp, configureSciChart, createColumn3DChart, createPRPDChart, createSurface3DChart, debounce, deepMerge, extractXValues, extractYValues, formatNumber, generateId, hexToRgba, lerp, normalizeDataPoints, parseSize, throttle };
1675
1427
  //# sourceMappingURL=index.mjs.map
1676
1428
  //# sourceMappingURL=index.mjs.map