@tetacom/svg-charts 1.1.10 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/chart/base/series-base.component.d.ts +4 -6
  2. package/chart/chart/chart.component.d.ts +10 -3
  3. package/chart/chart-container/annotation/annotation.component.d.ts +22 -13
  4. package/chart/chart-container/chart-container.component.d.ts +3 -3
  5. package/chart/chart-container/gridlines/gridlines.component.d.ts +3 -1
  6. package/chart/chart-container/plotband/plot-band.component.d.ts +5 -2
  7. package/chart/chart-container/plotline/plotline.component.d.ts +4 -2
  8. package/chart/chart-container/series/area-series/area-series.component.d.ts +6 -14
  9. package/chart/chart-container/series/line/line-series.component.d.ts +3 -14
  10. package/chart/chart-container/series/linear-series-base.d.ts +30 -0
  11. package/chart/chart-container/series-host/series-host.component.d.ts +4 -8
  12. package/chart/chart-container/tooltip/tooltip.component.d.ts +1 -1
  13. package/chart/chart.module.d.ts +18 -17
  14. package/chart/directives/zoomable.directive.d.ts +9 -4
  15. package/chart/model/annotation.d.ts +8 -18
  16. package/chart/model/i-chart-config.d.ts +9 -1
  17. package/chart/service/brush.service.d.ts +3 -2
  18. package/chart/service/chart.service.d.ts +8 -0
  19. package/esm2020/chart/base/series-base.component.mjs +8 -6
  20. package/esm2020/chart/chart/chart.component.mjs +75 -19
  21. package/esm2020/chart/chart-container/annotation/annotation.component.mjs +66 -44
  22. package/esm2020/chart/chart-container/chart-container.component.mjs +11 -7
  23. package/esm2020/chart/chart-container/gridlines/gridlines.component.mjs +5 -3
  24. package/esm2020/chart/chart-container/plotband/plot-band.component.mjs +12 -6
  25. package/esm2020/chart/chart-container/plotline/plotline.component.mjs +7 -3
  26. package/esm2020/chart/chart-container/series/area-series/area-series.component.mjs +13 -138
  27. package/esm2020/chart/chart-container/series/block-series/block-series.component.mjs +2 -2
  28. package/esm2020/chart/chart-container/series/line/line-series.component.mjs +3 -159
  29. package/esm2020/chart/chart-container/series/linear-series-base.mjs +188 -0
  30. package/esm2020/chart/chart-container/series-host/series-host.component.mjs +9 -24
  31. package/esm2020/chart/chart-container/tooltip/tooltip.component.mjs +5 -5
  32. package/esm2020/chart/chart.module.mjs +4 -1
  33. package/esm2020/chart/default/default-chart-config.mjs +4 -2
  34. package/esm2020/chart/directives/brushable.directive.mjs +3 -2
  35. package/esm2020/chart/directives/zoomable.directive.mjs +79 -54
  36. package/esm2020/chart/model/annotation.mjs +2 -13
  37. package/esm2020/chart/model/i-broadcast-message.mjs +1 -1
  38. package/esm2020/chart/model/i-chart-config.mjs +1 -1
  39. package/esm2020/chart/service/broadcast.service.mjs +9 -3
  40. package/esm2020/chart/service/brush.service.mjs +58 -19
  41. package/esm2020/chart/service/chart.service.mjs +17 -3
  42. package/esm2020/chart/service/scale.service.mjs +9 -3
  43. package/esm2020/chart/service/zoom.service.mjs +5 -2
  44. package/fesm2015/tetacom-svg-charts.mjs +416 -354
  45. package/fesm2015/tetacom-svg-charts.mjs.map +1 -1
  46. package/fesm2020/tetacom-svg-charts.mjs +399 -334
  47. package/fesm2020/tetacom-svg-charts.mjs.map +1 -1
  48. package/package.json +1 -1
@@ -2,14 +2,12 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, Component, ChangeDetectionStrategy, Input, ViewChild, HostListener, ChangeDetectorRef, Directive, HostBinding, EventEmitter, Output, NgModule } from '@angular/core';
3
3
  import * as i4 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
- import { BehaviorSubject, Subject, map, shareReplay, filter, combineLatest, withLatestFrom, ReplaySubject, tap, takeWhile } from 'rxjs';
5
+ import { BehaviorSubject, Subject, map, shareReplay, filter, combineLatest, withLatestFrom, ReplaySubject, animationFrameScheduler, tap, takeWhile } from 'rxjs';
6
6
  import * as d3 from 'd3';
7
7
  import { zoomIdentity } from 'd3';
8
8
  import { maxIndex } from 'd3-array';
9
- import { throttleTime, tap as tap$1 } from 'rxjs/operators';
9
+ import { throttleTime, debounceTime, tap as tap$1 } from 'rxjs/operators';
10
10
  import * as i3 from '@angular/platform-browser';
11
- import * as d3annotation from 'd3-svg-annotation';
12
- import { annotationBadge, annotationLabel, annotationCallout, annotationCalloutCircle, annotationCalloutCurve, annotationCalloutElbow, annotationCalloutRect, annotationCustomType, annotationXYThreshold } from 'd3-svg-annotation';
13
11
 
14
12
  var ZoomType;
15
13
  (function (ZoomType) {
@@ -54,7 +52,9 @@ const defaultChartConfig = () => ({
54
52
  xAxis: [],
55
53
  yAxis: [],
56
54
  series: [],
57
- gridLines: true,
55
+ gridLines: {
56
+ enable: true
57
+ }
58
58
  });
59
59
 
60
60
  var ScaleType;
@@ -110,16 +110,21 @@ class ChartService {
110
110
  constructor() {
111
111
  this.config$ = new BehaviorSubject(defaultChartConfig());
112
112
  this.size$ = new BehaviorSubject(new DOMRectReadOnly());
113
- this.pointerMove$ = new BehaviorSubject(null);
113
+ this.pointerMove$ = new Subject();
114
114
  this.tooltips$ = new BehaviorSubject(new Map());
115
115
  this.plotBandEvent$ = new Subject();
116
116
  this.plotLineMove$ = new Subject();
117
117
  this.pointMove$ = new Subject();
118
118
  this.chartClick$ = new Subject();
119
119
  this.chartContextMenu$ = new Subject();
120
+ this.annotationEvent$ = new Subject();
121
+ this.annotationMove$ = new Subject();
120
122
  this.config = this.config$
121
123
  .asObservable()
122
- .pipe(map(this.setDefaults), map(this.setPreparationData), shareReplay(1));
124
+ .pipe(map(this.setDefaults), map(this.setPreparationData), shareReplay({
125
+ bufferSize: 1,
126
+ refCount: true
127
+ }));
123
128
  this.size = this.size$.asObservable();
124
129
  this.pointerMove = this.pointerMove$.asObservable();
125
130
  this.tooltips = this.tooltips$.asObservable();
@@ -128,6 +133,9 @@ class ChartService {
128
133
  this.pointMove = this.pointMove$.asObservable();
129
134
  this.chartClick = this.chartClick$.asObservable();
130
135
  this.chartContextMenu = this.chartContextMenu$.asObservable();
136
+ this.annotationClick = this.annotationEvent$.asObservable().pipe(filter((_) => _?.event?.type === 'click'));
137
+ this.annotationContextMenu = this.annotationEvent$.asObservable().pipe(filter((_) => _?.event?.type === 'contextmenu'));
138
+ this.annotationMove = this.annotationMove$.asObservable();
131
139
  this.plotBandClick = this.plotBandEvent$
132
140
  .asObservable()
133
141
  .pipe(filter((_) => _?.event?.type === 'click'));
@@ -158,6 +166,12 @@ class ChartService {
158
166
  clearTooltips() {
159
167
  this.tooltips$.next(new Map());
160
168
  }
169
+ emitMoveAnnotation(event) {
170
+ this.annotationMove$.next(event);
171
+ }
172
+ emitAnnotation(event) {
173
+ this.annotationEvent$.next(event);
174
+ }
161
175
  emitPlotband(event) {
162
176
  this.plotBandEvent$.next(event);
163
177
  }
@@ -239,7 +253,10 @@ class ZoomService {
239
253
  constructor() {
240
254
  this.broadcastSubscription = [];
241
255
  this.zoomed$ = new BehaviorSubject(null);
242
- this.zoomed = this.zoomed$.asObservable().pipe(shareReplay(1));
256
+ this.zoomed = this.zoomed$.asObservable().pipe(shareReplay({
257
+ bufferSize: 1,
258
+ refCount: true
259
+ }));
243
260
  }
244
261
  setZoom(zoom) {
245
262
  this.zoomed$.next(zoom);
@@ -510,7 +527,10 @@ class ScaleService {
510
527
  }
511
528
  }
512
529
  return map;
513
- }), shareReplay(1));
530
+ }), shareReplay({
531
+ bufferSize: 1,
532
+ refCount: true
533
+ }));
514
534
  this.yScaleMap = combineLatest([
515
535
  this.chartService.size,
516
536
  this.chartService.config,
@@ -563,7 +583,10 @@ class ScaleService {
563
583
  }
564
584
  }
565
585
  return map;
566
- }), shareReplay(1));
586
+ }), shareReplay({
587
+ bufferSize: 1,
588
+ refCount: true
589
+ }));
567
590
  }
568
591
  }
569
592
  ScaleService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ScaleService, deps: [{ token: ChartService }, { token: ZoomService }], target: i0.ɵɵFactoryTarget.Injectable });
@@ -610,10 +633,16 @@ class BroadcastService {
610
633
  this.brushEmitter.next(value);
611
634
  }
612
635
  subscribeToZoom(channel) {
613
- return this.zoomEmitter.asObservable().pipe(filter((msg) => channel && msg.channel === channel), shareReplay(1));
636
+ return this.zoomEmitter.asObservable().pipe(filter((msg) => channel && msg.channel === channel), shareReplay({
637
+ bufferSize: 1,
638
+ refCount: true
639
+ }));
614
640
  }
615
641
  subscribeToBrush(channel) {
616
- return this.brushEmitter.asObservable().pipe(filter((msg) => channel && msg.channel === channel), shareReplay(1));
642
+ return this.brushEmitter.asObservable().pipe(filter((msg) => channel && msg.channel === channel), shareReplay({
643
+ bufferSize: 1,
644
+ refCount: true
645
+ }));
617
646
  }
618
647
  }
619
648
  BroadcastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: BroadcastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -626,14 +655,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
626
655
  }], ctorParameters: function () { return []; } });
627
656
 
628
657
  class BrushService {
629
- constructor(broadcastService) {
658
+ constructor(broadcastService, zone) {
630
659
  this.broadcastService = broadcastService;
660
+ this.zone = zone;
631
661
  this.brushMap = new Map()
632
662
  .set(BrushType.x, d3.brushX())
633
663
  .set(BrushType.y, d3.brushY());
634
664
  }
635
665
  applyBrush(svgElement, config, brushScale) {
636
666
  this.broadcastSubscribtion?.unsubscribe();
667
+ this.brush?.on('start brush end', null);
637
668
  if (config.brush?.enable) {
638
669
  this.brush = this.brushMap.get(config?.brush?.type ?? BrushType.x);
639
670
  const container = d3.select(svgElement.nativeElement);
@@ -642,14 +673,37 @@ class BrushService {
642
673
  if (!_.selection)
643
674
  return;
644
675
  const [from, to] = _.selection;
645
- if (_.type === 'end' && _.sourceEvent instanceof MouseEvent) {
676
+ if (to - from === 0) {
677
+ const selection = this.selection?.map(brushScale) ?? [config.brush?.from, config.brush?.to].map(brushScale);
678
+ const halfBrushHeight = (selection[1] - selection[0]) / 2;
679
+ const invertedSelection = [from - halfBrushHeight, to + halfBrushHeight].map(brushScale.invert);
680
+ if (invertedSelection[1] - invertedSelection[0] > config.brush?.max) {
681
+ container.call(this.brush.move, [invertedSelection[0], invertedSelection[0] + config.brush?.max].map(brushScale));
682
+ return;
683
+ }
684
+ if (invertedSelection[1] - invertedSelection[0] < config.brush?.min) {
685
+ container.call(this.brush.move, [invertedSelection[0], invertedSelection[0] + config.brush?.min].map(brushScale));
686
+ return;
687
+ }
688
+ container.call(this.brush.move, [from - halfBrushHeight, to + halfBrushHeight]);
689
+ return;
690
+ }
691
+ if (brushScale.invert(to) - brushScale.invert(from) > config.brush?.max) {
692
+ container.call(this.brush.move, this.selection ? [this.selection[0], this.selection[0] + config.brush?.max].map(brushScale) : [config.brush?.from, config.brush?.to].map(brushScale));
693
+ return;
694
+ }
695
+ if (brushScale.invert(to) - brushScale.invert(from) < config.brush?.min) {
696
+ container.call(this.brush.move, this.selection ? [this.selection[0], this.selection[0] + config.brush?.min].map(brushScale) : [config.brush?.from, config.brush?.to].map(brushScale));
697
+ return;
698
+ }
699
+ if (_.sourceEvent instanceof MouseEvent) {
646
700
  this.selection = _.selection.map(brushScale.invert);
647
701
  }
648
702
  const brushMessage = new BrushMessage({
649
703
  event: _,
650
704
  selection: [brushScale.invert(from), brushScale.invert(to)],
651
705
  brushType: config?.brush?.type ?? BrushType.x,
652
- brushScale,
706
+ brushScale
653
707
  });
654
708
  this.broadcastService.broadcastBrush({
655
709
  channel: config?.zoom?.syncChannel,
@@ -657,25 +711,39 @@ class BrushService {
657
711
  });
658
712
  }
659
713
  });
660
- setTimeout(() => {
661
- container.call(this.brush);
662
- let domain = brushScale.domain();
663
- if (config?.brush?.from) {
664
- domain[0] = config.brush.from;
665
- }
666
- if (config?.brush?.to) {
667
- domain[1] = config.brush.to;
668
- }
669
- container.call(this.brush.move, this.selection ? this.selection.map(brushScale) : domain.map(brushScale), {});
670
- }, 0);
714
+ this.zone.runOutsideAngular(() => {
715
+ setTimeout(() => {
716
+ container.call(this.brush);
717
+ let domain = brushScale.domain();
718
+ if (config?.brush?.from) {
719
+ domain[0] = config.brush.from;
720
+ }
721
+ if (config?.brush?.to) {
722
+ domain[1] = config.brush.to;
723
+ }
724
+ container.call(this.brush.move, this.selection ? this.selection.map(brushScale) : domain.map(brushScale), {});
725
+ }, 0);
726
+ });
671
727
  this.broadcastSubscribtion = this.broadcastService.subscribeToZoom(config?.zoom?.syncChannel).pipe(filter((m) => {
672
728
  return m.message.event.sourceEvent instanceof MouseEvent || m.message.event.sourceEvent instanceof WheelEvent;
673
- }), throttleTime(50, undefined, { trailing: true }), tap((m) => {
729
+ }), throttleTime(0, animationFrameScheduler, { trailing: true }), tap((m) => {
674
730
  const { message: { brushDomain } } = m;
675
731
  container.call(this.brush.move, [
676
732
  brushScale(brushDomain[0]),
677
733
  brushScale(brushDomain[1]),
678
734
  ]);
735
+ if (m.message.event.type === 'end') {
736
+ const brushMessage = new BrushMessage({
737
+ event: null,
738
+ selection: brushDomain,
739
+ brushType: config?.brush?.type ?? BrushType.x,
740
+ brushScale,
741
+ });
742
+ this.broadcastService.broadcastBrush({
743
+ channel: config?.zoom?.syncChannel,
744
+ message: brushMessage,
745
+ });
746
+ }
679
747
  this.selection = brushDomain;
680
748
  })).subscribe();
681
749
  }
@@ -684,14 +752,14 @@ class BrushService {
684
752
  this.selection = null;
685
753
  }
686
754
  }
687
- BrushService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: BrushService, deps: [{ token: BroadcastService }], target: i0.ɵɵFactoryTarget.Injectable });
755
+ BrushService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: BrushService, deps: [{ token: BroadcastService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
688
756
  BrushService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: BrushService, providedIn: 'root' });
689
757
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: BrushService, decorators: [{
690
758
  type: Injectable,
691
759
  args: [{
692
760
  providedIn: 'root',
693
761
  }]
694
- }], ctorParameters: function () { return [{ type: BroadcastService }]; } });
762
+ }], ctorParameters: function () { return [{ type: BroadcastService }, { type: i0.NgZone }]; } });
695
763
 
696
764
  class TooltipComponent {
697
765
  constructor(svc, cdr, zoomService, sanitizer, _zone) {
@@ -710,7 +778,7 @@ class TooltipComponent {
710
778
  });
711
779
  }));
712
780
  this.position = this.svc.pointerMove.pipe(filter((event) => !!event), map((_) => {
713
- return this.getPoisition(_);
781
+ return this.getPosition(_);
714
782
  }), tap(() => this.cdr.detectChanges()));
715
783
  const transformHtml = (html) => {
716
784
  return this.sanitizer.bypassSecurityTrustHtml(html);
@@ -737,7 +805,7 @@ class TooltipComponent {
737
805
  return formatted;
738
806
  }));
739
807
  }
740
- getPoisition(event) {
808
+ getPosition(event) {
741
809
  const centerX = this.size.width / 2;
742
810
  const centerY = this.size.height / 2;
743
811
  const padding = { x: 10, y: 10 };
@@ -755,10 +823,10 @@ class TooltipComponent {
755
823
  }
756
824
  }
757
825
  TooltipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: TooltipComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ZoomService }, { token: i3.DomSanitizer }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
758
- TooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: TooltipComponent, selector: "teta-tooltip", inputs: { size: "size", config: "config" }, ngImport: i0, template: "<ng-container *ngIf=\"position | async as p\">\n\n <div class=\"chart-tooltip color-text-90 bg-background-50 shadow-2 padding-2 border-radius-1\"\n *ngIf=\"displayTooltips | async as tool\"\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n style=\"pointer-events: none; min-width: 200px;\"\n [style.left]=\"p.left\"\n [style.top]=\"p.top\"\n [style.bottom]=\"p.bottom\"\n [style.right]=\"p.right\"\n [innerHTML]=\"tool\">\n </div>\n</ng-container>\n\n", styles: [":host{position:absolute;z-index:2}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
826
+ TooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: TooltipComponent, selector: "teta-tooltip", inputs: { size: "size", config: "config" }, ngImport: i0, template: "<ng-container *ngIf=\"position | async as p\">\n <div class=\"chart-tooltip color-text-90 bg-background-50 shadow-2 padding-2 border-radius-1\"\n *ngIf=\"displayTooltips | async as tool\"\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n style=\"pointer-events: none; min-width: 200px;\"\n [style.left]=\"p.left\"\n [style.top]=\"p.top\"\n [style.bottom]=\"p.bottom\"\n [style.right]=\"p.right\"\n [innerHTML]=\"tool\">\n </div>\n</ng-container>\n", styles: [":host{position:absolute;z-index:2}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
759
827
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: TooltipComponent, decorators: [{
760
828
  type: Component,
761
- args: [{ selector: 'teta-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"position | async as p\">\n\n <div class=\"chart-tooltip color-text-90 bg-background-50 shadow-2 padding-2 border-radius-1\"\n *ngIf=\"displayTooltips | async as tool\"\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n style=\"pointer-events: none; min-width: 200px;\"\n [style.left]=\"p.left\"\n [style.top]=\"p.top\"\n [style.bottom]=\"p.bottom\"\n [style.right]=\"p.right\"\n [innerHTML]=\"tool\">\n </div>\n</ng-container>\n\n", styles: [":host{position:absolute;z-index:2}\n"] }]
829
+ args: [{ selector: 'teta-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"position | async as p\">\n <div class=\"chart-tooltip color-text-90 bg-background-50 shadow-2 padding-2 border-radius-1\"\n *ngIf=\"displayTooltips | async as tool\"\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n style=\"pointer-events: none; min-width: 200px;\"\n [style.left]=\"p.left\"\n [style.top]=\"p.top\"\n [style.bottom]=\"p.bottom\"\n [style.right]=\"p.right\"\n [innerHTML]=\"tool\">\n </div>\n</ng-container>\n", styles: [":host{position:absolute;z-index:2}\n"] }]
762
830
  }], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ZoomService }, { type: i3.DomSanitizer }, { type: i0.NgZone }]; }, propDecorators: { size: [{
763
831
  type: Input
764
832
  }], config: [{
@@ -885,16 +953,18 @@ class GridlinesComponent {
885
953
  }
886
954
  }
887
955
  GridlinesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GridlinesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
888
- GridlinesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: GridlinesComponent, selector: "[teta-gridlines]", inputs: { size: "size", xScaleMap: "xScaleMap", yScaleMap: "yScaleMap" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let tick of tickYValues\">\n <svg:line [attr.x1]=\"0\" stroke=\"red\"\n [attr.y1]=\"yScaleMap.get(0)(tick)\"\n [attr.x2]=\"size?.width\"\n [attr.y2]=\"yScaleMap.get(0)(tick)\"></svg:line>\n</ng-container>\n\n<ng-container *ngFor=\"let tick of tickXValues\">\n <svg:line [attr.x1]=\"xScaleMap.get(0)(tick)\"\n stroke=\"red\"\n [attr.y1]=\"0\"\n [attr.x2]=\"xScaleMap.get(0)(tick)\"\n [attr.y2]=\"size?.height\"></svg:line>\n</ng-container>\n", styles: [":host{shape-rendering:crispEdges}:host line{stroke-dasharray:1,4;stroke:var(--color-text-20)}\n"], directives: [{ type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
956
+ GridlinesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: GridlinesComponent, selector: "[teta-gridlines]", inputs: { size: "size", xScaleMap: "xScaleMap", yScaleMap: "yScaleMap", config: "config" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"config.gridLines?.showY !== false\" >\n <ng-container *ngFor=\"let tick of tickYValues\">\n <svg:line [attr.x1]=\"0\" stroke=\"red\"\n [attr.y1]=\"yScaleMap.get(0)(tick)\"\n [attr.x2]=\"size?.width\"\n [attr.y2]=\"yScaleMap.get(0)(tick)\"></svg:line>\n </ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"config.gridLines?.showX !== false\" >\n <ng-container *ngFor=\"let tick of tickXValues\">\n <svg:line [attr.x1]=\"xScaleMap.get(0)(tick)\"\n stroke=\"red\"\n [attr.y1]=\"0\"\n [attr.x2]=\"xScaleMap.get(0)(tick)\"\n [attr.y2]=\"size?.height\"></svg:line>\n </ng-container>\n</ng-container>\n", styles: [":host{shape-rendering:crispEdges}:host line{stroke-dasharray:1,4;stroke:var(--color-text-20)}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
889
957
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GridlinesComponent, decorators: [{
890
958
  type: Component,
891
- args: [{ selector: '[teta-gridlines]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngFor=\"let tick of tickYValues\">\n <svg:line [attr.x1]=\"0\" stroke=\"red\"\n [attr.y1]=\"yScaleMap.get(0)(tick)\"\n [attr.x2]=\"size?.width\"\n [attr.y2]=\"yScaleMap.get(0)(tick)\"></svg:line>\n</ng-container>\n\n<ng-container *ngFor=\"let tick of tickXValues\">\n <svg:line [attr.x1]=\"xScaleMap.get(0)(tick)\"\n stroke=\"red\"\n [attr.y1]=\"0\"\n [attr.x2]=\"xScaleMap.get(0)(tick)\"\n [attr.y2]=\"size?.height\"></svg:line>\n</ng-container>\n", styles: [":host{shape-rendering:crispEdges}:host line{stroke-dasharray:1,4;stroke:var(--color-text-20)}\n"] }]
959
+ args: [{ selector: '[teta-gridlines]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"config.gridLines?.showY !== false\" >\n <ng-container *ngFor=\"let tick of tickYValues\">\n <svg:line [attr.x1]=\"0\" stroke=\"red\"\n [attr.y1]=\"yScaleMap.get(0)(tick)\"\n [attr.x2]=\"size?.width\"\n [attr.y2]=\"yScaleMap.get(0)(tick)\"></svg:line>\n </ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"config.gridLines?.showX !== false\" >\n <ng-container *ngFor=\"let tick of tickXValues\">\n <svg:line [attr.x1]=\"xScaleMap.get(0)(tick)\"\n stroke=\"red\"\n [attr.y1]=\"0\"\n [attr.x2]=\"xScaleMap.get(0)(tick)\"\n [attr.y2]=\"size?.height\"></svg:line>\n </ng-container>\n</ng-container>\n", styles: [":host{shape-rendering:crispEdges}:host line{stroke-dasharray:1,4;stroke:var(--color-text-20)}\n"] }]
892
960
  }], ctorParameters: function () { return []; }, propDecorators: { size: [{
893
961
  type: Input
894
962
  }], xScaleMap: [{
895
963
  type: Input
896
964
  }], yScaleMap: [{
897
965
  type: Input
966
+ }], config: [{
967
+ type: Input
898
968
  }] } });
899
969
 
900
970
  class PlotBandComponent {
@@ -930,7 +1000,7 @@ class PlotBandComponent {
930
1000
  const grabElements = d3
931
1001
  .select(this.element.nativeElement)
932
1002
  .selectAll('.grabber');
933
- const drag = d3
1003
+ this.dragElements = d3
934
1004
  .drag()
935
1005
  .subject(() => {
936
1006
  if (this.axis.orientation === AxisOrientation.x) {
@@ -939,7 +1009,8 @@ class PlotBandComponent {
939
1009
  if (this.axis.orientation === AxisOrientation.y) {
940
1010
  return { y: plotbandElement.attr('y') };
941
1011
  }
942
- })
1012
+ });
1013
+ const drag = this.dragElements
943
1014
  .on('start drag end', (event, d) => {
944
1015
  let bandSize = parseFloat(plotbandElement.attr(this.axis.orientation === AxisOrientation.x ? 'width' : 'height'));
945
1016
  d.from = this.scale.invert(event[AxisOrientation[this.axis.orientation]]);
@@ -951,8 +1022,9 @@ class PlotBandComponent {
951
1022
  this.cdr.detectChanges();
952
1023
  });
953
1024
  let grabberKey;
954
- const resize = d3
955
- .drag()
1025
+ this.resizeElements = d3
1026
+ .drag();
1027
+ const resize = this.resizeElements
956
1028
  .on('start drag end', (event, d) => {
957
1029
  requestAnimationFrame(() => {
958
1030
  if (event?.type === 'start') {
@@ -998,6 +1070,10 @@ class PlotBandComponent {
998
1070
  grabElements.call(resize);
999
1071
  }
1000
1072
  }
1073
+ ngOnDestroy() {
1074
+ this.dragElements.on('start drag end', null);
1075
+ this.resizeElements.on('start drag end', null);
1076
+ }
1001
1077
  get bandSize() {
1002
1078
  return Math.abs(this.scale(this.plotBand.to) - this.scale(this.plotBand.from));
1003
1079
  }
@@ -1058,7 +1134,7 @@ class PlotlineComponent {
1058
1134
  const grabElement = d3
1059
1135
  .select(this.element.nativeElement)
1060
1136
  .selectAll('.grabber');
1061
- const drag = d3
1137
+ this.dragElements = d3
1062
1138
  .drag()
1063
1139
  .subject(() => {
1064
1140
  if (this.axis.orientation === AxisOrientation.y) {
@@ -1067,7 +1143,8 @@ class PlotlineComponent {
1067
1143
  if (this.axis.orientation === AxisOrientation.x) {
1068
1144
  return { x: plotlineElement.attr('x1') };
1069
1145
  }
1070
- })
1146
+ });
1147
+ const drag = this.dragElements
1071
1148
  .on('start drag end', (event, d) => {
1072
1149
  d.value = this.scale.invert(event[AxisOrientation[this.axis.orientation]]);
1073
1150
  this.emit({
@@ -1082,6 +1159,9 @@ class PlotlineComponent {
1082
1159
  grabElement.call(drag);
1083
1160
  }
1084
1161
  }
1162
+ ngOnDestroy() {
1163
+ this.dragElements.on('start drag end', null);
1164
+ }
1085
1165
  emit(event) {
1086
1166
  this.chartService.emitPlotline(event);
1087
1167
  }
@@ -1110,59 +1190,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
1110
1190
  type: Input
1111
1191
  }] } });
1112
1192
 
1113
- class AnnotationComponent {
1114
- constructor() { }
1115
- ngOnInit() { }
1116
- ngAfterViewInit() {
1117
- this._node = d3.select(this.node.nativeElement);
1118
- this.drawAnnotations();
1119
- }
1120
- drawAnnotations() {
1121
- if (!this.node)
1122
- return;
1123
- const annotations = this.annotations?.map((annotation) => {
1124
- const x = this.xScaleMap.get(annotation.xAxisIndex);
1125
- const y = this.yScaleMap.get(annotation.yAxisIndex);
1126
- return {
1127
- note: annotation.note,
1128
- connector: annotation.connector,
1129
- x: x(annotation.point?.x),
1130
- y: y(annotation.point?.y),
1131
- dx: annotation.dx,
1132
- dy: annotation.dy,
1133
- type: annotation.type ?? d3annotation.annotationLabel,
1134
- className: annotation.className,
1135
- };
1136
- });
1137
- this._makeAnnotations = d3annotation
1138
- .annotation()
1139
- .annotations(annotations ?? [])
1140
- .editMode(false);
1141
- this._node.call(this._makeAnnotations);
1142
- }
1143
- ngOnChanges(changes) {
1144
- if (changes.hasOwnProperty('xScaleMap') &&
1145
- changes.hasOwnProperty('yScaleMap')) {
1146
- this.drawAnnotations();
1147
- }
1148
- }
1149
- }
1150
- AnnotationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AnnotationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1151
- AnnotationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: AnnotationComponent, selector: "[teta-annotation]", inputs: { annotations: "annotations", xScaleMap: "xScaleMap", yScaleMap: "yScaleMap" }, viewQueries: [{ propertyName: "node", first: true, predicate: ["svg"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<svg:g #svg></svg:g>\n", styles: [""] });
1152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AnnotationComponent, decorators: [{
1153
- type: Component,
1154
- args: [{ selector: '[teta-annotation]', template: "<svg:g #svg></svg:g>\n", styles: [""] }]
1155
- }], ctorParameters: function () { return []; }, propDecorators: { annotations: [{
1156
- type: Input
1157
- }], xScaleMap: [{
1158
- type: Input
1159
- }], yScaleMap: [{
1160
- type: Input
1161
- }], node: [{
1162
- type: ViewChild,
1163
- args: ['svg']
1164
- }] } });
1165
-
1166
1193
  class SeriesBaseComponent {
1167
1194
  constructor(svc, cdr, scaleService, zoomService, element) {
1168
1195
  this.svc = svc;
@@ -1171,6 +1198,12 @@ class SeriesBaseComponent {
1171
1198
  this.zoomService = zoomService;
1172
1199
  this.element = element;
1173
1200
  }
1201
+ set config(config) {
1202
+ this._config = config;
1203
+ }
1204
+ get config() {
1205
+ return this._config;
1206
+ }
1174
1207
  set series(series) {
1175
1208
  this._series = series;
1176
1209
  }
@@ -1181,7 +1214,7 @@ class SeriesBaseComponent {
1181
1214
  }
1182
1215
  }
1183
1216
  SeriesBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SeriesBaseComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1184
- SeriesBaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SeriesBaseComponent, selector: "ng-component", inputs: { config: "config", series: "series", size: "size", rect: "rect" }, ngImport: i0, template: '', isInline: true });
1217
+ SeriesBaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SeriesBaseComponent, selector: "ng-component", inputs: { config: "config", series: "series" }, ngImport: i0, template: '', isInline: true });
1185
1218
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SeriesBaseComponent, decorators: [{
1186
1219
  type: Component,
1187
1220
  args: [{
@@ -1191,10 +1224,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
1191
1224
  type: Input
1192
1225
  }], series: [{
1193
1226
  type: Input
1194
- }], size: [{
1195
- type: Input
1196
- }], rect: [{
1197
- type: Input
1198
1227
  }] } });
1199
1228
 
1200
1229
  var DragPointType;
@@ -1204,7 +1233,7 @@ var DragPointType;
1204
1233
  DragPointType[DragPointType["xy"] = 2] = "xy";
1205
1234
  })(DragPointType || (DragPointType = {}));
1206
1235
 
1207
- class LineSeriesComponent extends SeriesBaseComponent {
1236
+ class LinearSeriesBase extends SeriesBaseComponent {
1208
1237
  constructor(svc, cdr, scaleService, zoomService, element) {
1209
1238
  super(svc, cdr, scaleService, zoomService, element);
1210
1239
  this.svc = svc;
@@ -1238,6 +1267,13 @@ class LineSeriesComponent extends SeriesBaseComponent {
1238
1267
  return line(this.series.data);
1239
1268
  }));
1240
1269
  }
1270
+ ngOnDestroy() {
1271
+ this.markers?.on('start drag end', null);
1272
+ this.svc.setTooltip({
1273
+ point: null,
1274
+ series: this.series,
1275
+ });
1276
+ }
1241
1277
  ngAfterViewInit() {
1242
1278
  const drag = (node, event, d) => {
1243
1279
  if (d.marker?.dragType === DragPointType.x ||
@@ -1257,13 +1293,13 @@ class LineSeriesComponent extends SeriesBaseComponent {
1257
1293
  });
1258
1294
  this.cdr.detectChanges();
1259
1295
  };
1260
- const dragMarkers = d3
1296
+ this.markers = d3
1261
1297
  .drag()
1262
1298
  .subject(function (event, d) {
1263
1299
  const node = d3.select(this);
1264
1300
  return { x: node.attr('cx'), y: node.attr('cy') };
1265
- })
1266
- .on('start drag end', function (event, d) {
1301
+ });
1302
+ const dragMarkers = this.markers.on('start drag end', function (event, d) {
1267
1303
  const node = d3.select(this);
1268
1304
  drag(node, event, d);
1269
1305
  });
@@ -1366,6 +1402,25 @@ class LineSeriesComponent extends SeriesBaseComponent {
1366
1402
  }
1367
1403
  }
1368
1404
  }
1405
+ LinearSeriesBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: LinearSeriesBase, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1406
+ LinearSeriesBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: LinearSeriesBase, selector: "ng-component", usesInheritance: true, ngImport: i0, template: '', isInline: true });
1407
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: LinearSeriesBase, decorators: [{
1408
+ type: Component,
1409
+ args: [{
1410
+ template: '',
1411
+ }]
1412
+ }], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ScaleService }, { type: ZoomService }, { type: i0.ElementRef }]; } });
1413
+
1414
+ class LineSeriesComponent extends LinearSeriesBase {
1415
+ constructor(svc, cdr, scaleService, zoomService, element) {
1416
+ super(svc, cdr, scaleService, zoomService, element);
1417
+ this.svc = svc;
1418
+ this.cdr = cdr;
1419
+ this.scaleService = scaleService;
1420
+ this.zoomService = zoomService;
1421
+ this.element = element;
1422
+ }
1423
+ }
1369
1424
  LineSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: LineSeriesComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1370
1425
  LineSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: LineSeriesComponent, selector: "svg:svg[teta-line-series]", usesInheritance: true, ngImport: i0, template: "<svg:path\n class=\"line\"\n [attr.d]=\"path | async\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n fill=\"none\">\n</svg:path>\n<ng-container *ngIf=\"transform | async as t\">\n <svg:circle\n *ngIf=\"t.x !== undefined && t.y!== undefined\"\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate('+ t.x +', '+ t.y +')'\"\n >\n </svg:circle>\n</ng-container>\n\n<ng-container *ngIf=\"getMarkers() as markers\">\n <svg:circle\n class=\"marker\"\n *ngFor=\"let point of markers\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n [attr.r]=\"point.marker.style?.radius ?? 5\"\n [attr.fill]=\"point.marker.style?.fill ?? 'transparent'\"\n [attr.stroke]=\"point.marker.style?.stroke ?? 'none'\"\n [attr.stroke-width]=\"point.marker.style?.strokeWidth\"\n [attr.stroke-dasharray]=\"point.marker.style?.strokeDasharray\"\n [attr.cx]=\"x(point.x)\"\n [attr.cy]=\"y(point.y)\"\n >\n </svg:circle>\n</ng-container>\n\n\n\n", styles: [".draggable-marker{cursor:move}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1371
1426
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: LineSeriesComponent, decorators: [{
@@ -1469,7 +1524,7 @@ class BlockSeriesComponent extends SeriesBaseComponent {
1469
1524
  this.id = (Date.now() + Math.random()).toString(36);
1470
1525
  }
1471
1526
  ngOnInit() {
1472
- const defaultVisiblePixels = 1;
1527
+ const defaultVisiblePixels = 0;
1473
1528
  this.x = this.scaleService.xScaleMap.pipe(map((_) => _.get(this.series.xAxisIndex)));
1474
1529
  this.y = this.scaleService.yScaleMap.pipe(map((_) => _.get(this.series.yAxisIndex)));
1475
1530
  this.displayPoints = this.y.pipe(map((y) => {
@@ -1565,7 +1620,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
1565
1620
  args: [{ selector: 'svg:svg[teta-block-area-series]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n y: y | async,\n x: x | async,\n points: displayPoints | async\n} as data\">\n <svg:defs *ngIf=\"series?.fillType === fillType.gradient\">\n <svg:linearGradient [id]=\"'gradient-fill-' + id\"\n gradientUnits=\"userSpaceOnUse\"\n x1=\"0%\"\n [attr.y1]=\"config?.inverted ? '0%' : '100%'\"\n [attr.x2]=\"config?.inverted ? '100%' : '0%'\"\n y2=\"0%\">\n <svg:stop offset=\"0%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0\"></svg:stop>\n <svg:stop offset=\"5%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.1\"></svg:stop>\n <svg:stop offset=\"20%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.2\"></svg:stop>\n <svg:stop offset=\"60%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.5\"></svg:stop>\n <svg:stop offset=\"100%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.9\"></svg:stop>\n </svg:linearGradient>\n </svg:defs>\n <ng-container *ngFor=\"let point of data.points\">\n <svg:g (mouseenter)=\"mouseenter(point)\"\n (mouseleave)=\"mouseleave(point)\">\n <svg:rect\n *ngIf=\"!!config.inverted\"\n [attr.x]=\"data.x(0) < data.x(point.x) ? data.x(0) : data.x(point.x)\"\n [attr.y]=\"data.y(point.y)\"\n [attr.height]=\"data.y(point.y1) - data.y(point.y)\"\n [attr.width]=\"data.x(0) < data.x(point.x) ? data.x(point.x) - data.x(0) : data.x(0) - data.x(point.x)\"\n [attr.stroke]=\"point.iconId ? '' : point.color ?? series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : point.iconId ? 'url(#pattern'+point.iconId+')' : point.color ?? series.color\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\">\n </svg:rect>\n <svg:rect\n *ngIf=\"!config.inverted\"\n [attr.x]=\"data.x(point.x)\"\n [attr.y]=\"data.y(0)\"\n [attr.height]=\"data.y(0) - data.y(point.y)\"\n [attr.width]=\"data.x(point.x1) - data.x(point.x)\"\n [attr.stroke]=\"point.iconId ? '' : point.color ?? series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : point.iconId ? 'url(#pattern'+point.iconId+')' : point.color ?? series.color\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\">\n </svg:rect>\n <svg:text *ngIf=\"point.text\"\n x=\"50%\"\n [attr.y]=\"(data.y(point.y1) + data.y(point.y)) / 2\"\n alignment-baseline=\"middle\"\n text-anchor=\"middle\">{{ point.text }}\n </svg:text>\n\n <!-- <svg:line x1=\"0\" x2=\"100%\" [attr.y1]=\"data.y(point.y)\" [attr.y2]=\"data.y(point.y)\" [attr.stroke]=\"point.iconId ? 'var(&#45;&#45;color-text-10)' : point.color ?? series.color\"></svg:line>-->\n <!-- <svg:line x1=\"0\" x2=\"100%\" [attr.y1]=\"data.y(point.y1)\" [attr.y2]=\"data.y(point.y1)\" [attr.stroke]=\"point.iconId ? 'var(&#45;&#45;color-text-10)' : point.color ?? series.color\"></svg:line>-->\n\n </svg:g>\n </ng-container>\n\n\n</ng-container>\n", styles: [""] }]
1566
1621
  }], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ScaleService }, { type: ZoomService }, { type: i0.ElementRef }]; } });
1567
1622
 
1568
- class AreaSeriesComponent extends SeriesBaseComponent {
1623
+ class AreaSeriesComponent extends LinearSeriesBase {
1569
1624
  constructor(svc, cdr, scaleService, zoomService, element) {
1570
1625
  super(svc, cdr, scaleService, zoomService, element);
1571
1626
  this.svc = svc;
@@ -1578,15 +1633,14 @@ class AreaSeriesComponent extends SeriesBaseComponent {
1578
1633
  this.id = (Date.now() + Math.random()).toString(36);
1579
1634
  }
1580
1635
  ngOnInit() {
1581
- this.transform = this.svc.pointerMove.pipe(withLatestFrom(this.scaleService.xScaleMap, this.scaleService.yScaleMap), map((data) => {
1582
- const [event, x, y] = data;
1583
- return this.getTransform(event, x, y);
1584
- }), tap(() => this.cdr.detectChanges()));
1585
- this.path = combineLatest([
1636
+ super.ngOnInit();
1637
+ this.areaPath = combineLatest([
1586
1638
  this.scaleService.xScaleMap,
1587
1639
  this.scaleService.yScaleMap,
1588
- ]).pipe(withLatestFrom(this.scaleService.xAxisMap, this.scaleService.yAxisMap), map((data) => {
1589
- const [[x, y], xAxisMap, yAxisMap] = data;
1640
+ ]).pipe(map((data) => {
1641
+ const [x, y] = data;
1642
+ this.x = x.get(this.series.xAxisIndex);
1643
+ this.y = y.get(this.series.yAxisIndex);
1590
1644
  this.x = x.get(this.series.xAxisIndex);
1591
1645
  this.y = y.get(this.series.yAxisIndex);
1592
1646
  const area = d3
@@ -1602,134 +1656,12 @@ class AreaSeriesComponent extends SeriesBaseComponent {
1602
1656
  return area(this.series.data);
1603
1657
  }));
1604
1658
  }
1605
- ngAfterViewInit() {
1606
- const drag = (node, event, d) => {
1607
- if (d.marker?.dragType === DragPointType.x ||
1608
- d.marker?.dragType === DragPointType.xy) {
1609
- d.x = this.x.invert(event.x);
1610
- }
1611
- if (d.marker?.dragType === DragPointType.y ||
1612
- d.marker?.dragType === DragPointType.xy) {
1613
- d.y = this.y.invert(event.y);
1614
- }
1615
- this.svc.emitPoint({
1616
- target: {
1617
- series: this.series,
1618
- point: d,
1619
- },
1620
- event,
1621
- });
1622
- this.cdr.detectChanges();
1623
- };
1624
- const dragMarkers = d3
1625
- .drag()
1626
- .subject(function (event, d) {
1627
- const node = d3.select(this);
1628
- return { x: node.attr('cx'), y: node.attr('cy') };
1629
- })
1630
- .on('start drag end', function (event, d) {
1631
- const node = d3.select(this);
1632
- drag(node, event, d);
1633
- });
1634
- const draggableMarkers = this.series.data?.filter((_) => _?.marker && _?.marker?.draggable);
1635
- const element = d3
1636
- .select(this.element.nativeElement)
1637
- .selectAll('.draggable-marker')
1638
- .data(draggableMarkers);
1639
- element.call(dragMarkers);
1640
- this.svgElement = d3
1641
- .select(this.element.nativeElement)
1642
- .select('.line')
1643
- .node();
1644
- }
1645
- getMarkers() {
1646
- return this.series.data?.filter((_) => _?.marker);
1647
- }
1648
- getTransform(event, x, y) {
1649
- const mouse = [event?.offsetX, event?.offsetY];
1650
- const foundX = x.get(this.series.xAxisIndex);
1651
- const foundY = y.get(this.series.yAxisIndex);
1652
- const tooltipTracking = this.config?.tooltip?.tracking;
1653
- const lineIntersection = (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) => {
1654
- const rV = {};
1655
- let s1_x, s1_y, s2_x, s2_y;
1656
- s1_x = p1_x - p0_x;
1657
- s1_y = p1_y - p0_y;
1658
- s2_x = p3_x - p2_x;
1659
- s2_y = p3_y - p2_y;
1660
- let s, t;
1661
- s =
1662
- (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) /
1663
- (-s2_x * s1_y + s1_x * s2_y);
1664
- t =
1665
- (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) /
1666
- (-s2_x * s1_y + s1_x * s2_y);
1667
- if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
1668
- // Collision detected
1669
- rV.x = p0_x + t * s1_x;
1670
- rV.y = p0_y + t * s1_y;
1671
- }
1672
- return rV;
1673
- };
1674
- if (tooltipTracking === TooltipTracking.x) {
1675
- const bisect = d3.bisector((_) => _.x).right;
1676
- const pointer = mouse[0];
1677
- const x0 = foundX.invert(pointer);
1678
- const filtered = this.series.data.filter((_) => _.y !== null && _.x !== null);
1679
- const rightId = bisect(filtered, x0);
1680
- const range = foundY.range();
1681
- const intersect = lineIntersection(pointer, range[0], pointer, range[1], foundX(filtered[rightId - 1]?.x), foundY(filtered[rightId - 1]?.y), foundX(filtered[rightId]?.x), foundY(filtered[rightId]?.y));
1682
- const x = foundX.invert(intersect.x);
1683
- const y = foundY.invert(intersect.y);
1684
- if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
1685
- this.svc.setTooltip({
1686
- point: { x: foundX.invert(intersect.x), y: foundY.invert(intersect.y) },
1687
- series: this.series,
1688
- });
1689
- }
1690
- else {
1691
- this.svc.setTooltip({
1692
- point: null,
1693
- series: this.series,
1694
- });
1695
- }
1696
- return {
1697
- x: intersect.x,
1698
- y: intersect.y,
1699
- };
1700
- }
1701
- if (tooltipTracking === TooltipTracking.y) {
1702
- const bisect = d3.bisector((_) => _.y).right;
1703
- const y0 = foundY.invert(mouse[1]);
1704
- const rightId = bisect(this.series.data, y0);
1705
- const range = foundX.range();
1706
- const intersect = lineIntersection(range[0], mouse[1], range[1], mouse[1], foundX(this.series.data[rightId - 1]?.x), foundY(this.series.data[rightId - 1]?.y), foundX(this.series.data[rightId]?.x), foundY(this.series.data[rightId]?.y));
1707
- const x = foundX.invert(intersect.x);
1708
- const y = foundY.invert(intersect.y);
1709
- if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
1710
- this.svc.setTooltip({
1711
- point: { x: foundX.invert(intersect.x), y: foundY.invert(intersect.y) },
1712
- series: this.series,
1713
- });
1714
- }
1715
- else {
1716
- this.svc.setTooltip({
1717
- point: null,
1718
- series: this.series,
1719
- });
1720
- }
1721
- return {
1722
- x: intersect.x,
1723
- y: intersect.y,
1724
- };
1725
- }
1726
- }
1727
1659
  }
1728
1660
  AreaSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AreaSeriesComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1729
- AreaSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: AreaSeriesComponent, selector: "svg:svg[teta-area-series]", usesInheritance: true, ngImport: i0, template: "<svg:defs *ngIf=\"series?.fillType === fillType.gradient\">\n <svg:linearGradient [id]=\"'gradient-fill-' + id\" gradientUnits=\"userSpaceOnUse\"\n x1=\"0%\"\n [attr.y1]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '0%' : '100%'\"\n [attr.x2]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '100%' : '0%'\"\n y2=\"0%\">\n <svg:stop offset=\"0%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0\"></svg:stop>\n <svg:stop offset=\"5%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.1\"></svg:stop>\n <svg:stop offset=\"20%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.2\"></svg:stop>\n <svg:stop offset=\"60%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.5\"></svg:stop>\n <svg:stop offset=\"100%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.9\"></svg:stop>\n </svg:linearGradient>\n</svg:defs>\n<svg:path\n class=\"area\"\n [attr.d]=\"path | async\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : series.style.fill ?? series.color\">\n</svg:path>\n<ng-container *ngIf=\"transform | async as t\">\n <svg:circle\n *ngIf=\"t.x !== undefined && t.y!== undefined\"\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate('+ t.x +', '+ t.y +')'\"\n >\n </svg:circle>\n</ng-container>\n\n<ng-container *ngIf=\"getMarkers() as markers\">\n <svg:circle\n class=\"marker\"\n *ngFor=\"let point of markers\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n [attr.r]=\"point.marker.style?.radius ?? 5\"\n [attr.fill]=\"point.marker.style?.fill ?? 'transparent'\"\n [attr.stroke]=\"point.marker.style?.stroke ?? 'none'\"\n [attr.stroke-width]=\"point.marker.style?.strokeWidth\"\n [attr.stroke-dasharray]=\"point.marker.style?.strokeDasharray\"\n [attr.cx]=\"x(point.x)\"\n [attr.cy]=\"y(point.y)\"\n >\n </svg:circle>\n</ng-container>\n\n\n\n", styles: [""], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1661
+ AreaSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: AreaSeriesComponent, selector: "svg:svg[teta-area-series]", usesInheritance: true, ngImport: i0, template: "<svg:defs *ngIf=\"series?.fillType === fillType.gradient\">\n <svg:linearGradient [id]=\"'gradient-fill-' + id\" gradientUnits=\"userSpaceOnUse\"\n x1=\"0%\"\n [attr.y1]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '0%' : '100%'\"\n [attr.x2]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '100%' : '0%'\"\n y2=\"0%\">\n <svg:stop offset=\"0%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0\"></svg:stop>\n <svg:stop offset=\"5%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.1\"></svg:stop>\n <svg:stop offset=\"20%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.2\"></svg:stop>\n <svg:stop offset=\"60%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.5\"></svg:stop>\n <svg:stop offset=\"100%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.8\"></svg:stop>\n </svg:linearGradient>\n</svg:defs>\n<svg:path\n class=\"area\"\n *ngIf=\"series?.fillType === fillType.gradient\"\n [attr.d]=\"areaPath | async\"\n [attr.stroke-width]=\"0\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : series.style.fill ?? series.color\">\n</svg:path>\n<svg:path\n class=\"area\"\n fill=\"none\"\n [attr.d]=\"path | async\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\">\n</svg:path>\n<ng-container *ngIf=\"transform | async as t\">\n <svg:circle\n *ngIf=\"t.x !== undefined && t.y!== undefined\"\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate('+ t.x +', '+ t.y +')'\"\n >\n </svg:circle>\n</ng-container>\n<ng-container *ngIf=\"getMarkers() as markers\">\n <svg:circle\n class=\"marker\"\n *ngFor=\"let point of markers\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n [attr.r]=\"point.marker.style?.radius ?? 5\"\n [attr.fill]=\"point.marker.style?.fill ?? 'transparent'\"\n [attr.stroke]=\"point.marker.style?.stroke ?? 'none'\"\n [attr.stroke-width]=\"point.marker.style?.strokeWidth\"\n [attr.stroke-dasharray]=\"point.marker.style?.strokeDasharray\"\n [attr.cx]=\"x(point.x)\"\n [attr.cy]=\"y(point.y)\"\n >\n </svg:circle>\n</ng-container>\n\n\n\n", styles: [""], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1730
1662
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AreaSeriesComponent, decorators: [{
1731
1663
  type: Component,
1732
- args: [{ selector: 'svg:svg[teta-area-series]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:defs *ngIf=\"series?.fillType === fillType.gradient\">\n <svg:linearGradient [id]=\"'gradient-fill-' + id\" gradientUnits=\"userSpaceOnUse\"\n x1=\"0%\"\n [attr.y1]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '0%' : '100%'\"\n [attr.x2]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '100%' : '0%'\"\n y2=\"0%\">\n <svg:stop offset=\"0%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0\"></svg:stop>\n <svg:stop offset=\"5%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.1\"></svg:stop>\n <svg:stop offset=\"20%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.2\"></svg:stop>\n <svg:stop offset=\"60%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.5\"></svg:stop>\n <svg:stop offset=\"100%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.9\"></svg:stop>\n </svg:linearGradient>\n</svg:defs>\n<svg:path\n class=\"area\"\n [attr.d]=\"path | async\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : series.style.fill ?? series.color\">\n</svg:path>\n<ng-container *ngIf=\"transform | async as t\">\n <svg:circle\n *ngIf=\"t.x !== undefined && t.y!== undefined\"\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate('+ t.x +', '+ t.y +')'\"\n >\n </svg:circle>\n</ng-container>\n\n<ng-container *ngIf=\"getMarkers() as markers\">\n <svg:circle\n class=\"marker\"\n *ngFor=\"let point of markers\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n [attr.r]=\"point.marker.style?.radius ?? 5\"\n [attr.fill]=\"point.marker.style?.fill ?? 'transparent'\"\n [attr.stroke]=\"point.marker.style?.stroke ?? 'none'\"\n [attr.stroke-width]=\"point.marker.style?.strokeWidth\"\n [attr.stroke-dasharray]=\"point.marker.style?.strokeDasharray\"\n [attr.cx]=\"x(point.x)\"\n [attr.cy]=\"y(point.y)\"\n >\n </svg:circle>\n</ng-container>\n\n\n\n", styles: [""] }]
1664
+ args: [{ selector: 'svg:svg[teta-area-series]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:defs *ngIf=\"series?.fillType === fillType.gradient\">\n <svg:linearGradient [id]=\"'gradient-fill-' + id\" gradientUnits=\"userSpaceOnUse\"\n x1=\"0%\"\n [attr.y1]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '0%' : '100%'\"\n [attr.x2]=\"config?.inverted || series?.fillDirection === fillDirection.y ? '100%' : '0%'\"\n y2=\"0%\">\n <svg:stop offset=\"0%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0\"></svg:stop>\n <svg:stop offset=\"5%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.1\"></svg:stop>\n <svg:stop offset=\"20%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.2\"></svg:stop>\n <svg:stop offset=\"60%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.5\"></svg:stop>\n <svg:stop offset=\"100%\" [attr.stop-color]=\"series.color\" stop-opacity=\"0.8\"></svg:stop>\n </svg:linearGradient>\n</svg:defs>\n<svg:path\n class=\"area\"\n *ngIf=\"series?.fillType === fillType.gradient\"\n [attr.d]=\"areaPath | async\"\n [attr.stroke-width]=\"0\"\n [attr.fill-opacity]=\"series.style?.fillOpacity\"\n [attr.fill]=\"series.fillType === fillType.gradient ? 'url(#gradient-fill-'+id+')' : series.style.fill ?? series.color\">\n</svg:path>\n<svg:path\n class=\"area\"\n fill=\"none\"\n [attr.d]=\"path | async\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\">\n</svg:path>\n<ng-container *ngIf=\"transform | async as t\">\n <svg:circle\n *ngIf=\"t.x !== undefined && t.y!== undefined\"\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate('+ t.x +', '+ t.y +')'\"\n >\n </svg:circle>\n</ng-container>\n<ng-container *ngIf=\"getMarkers() as markers\">\n <svg:circle\n class=\"marker\"\n *ngFor=\"let point of markers\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n [attr.r]=\"point.marker.style?.radius ?? 5\"\n [attr.fill]=\"point.marker.style?.fill ?? 'transparent'\"\n [attr.stroke]=\"point.marker.style?.stroke ?? 'none'\"\n [attr.stroke-width]=\"point.marker.style?.strokeWidth\"\n [attr.stroke-dasharray]=\"point.marker.style?.strokeDasharray\"\n [attr.cx]=\"x(point.x)\"\n [attr.cy]=\"y(point.y)\"\n >\n </svg:circle>\n</ng-container>\n\n\n\n", styles: [""] }]
1733
1665
  }], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ScaleService }, { type: ZoomService }, { type: i0.ElementRef }]; } });
1734
1666
 
1735
1667
  const defaultSeriesTypeMapping = new Map()
@@ -1741,15 +1673,9 @@ const defaultSeriesTypeMapping = new Map()
1741
1673
  .set(SeriesType.blockArea, BlockAreaSeriesComponent);
1742
1674
 
1743
1675
  class SeriesHostComponent {
1744
- constructor(viewContainerRef, chartService) {
1676
+ constructor(viewContainerRef) {
1745
1677
  this.viewContainerRef = viewContainerRef;
1746
- this.chartService = chartService;
1747
1678
  this._init = false;
1748
- this.chartService.size
1749
- .pipe(tap(() => {
1750
- this._componentRef?.injector.get(ChangeDetectorRef).detectChanges();
1751
- }))
1752
- .subscribe();
1753
1679
  }
1754
1680
  ngOnInit() {
1755
1681
  if (!SeriesBaseComponent.isPrototypeOf(this.series.component)) {
@@ -1759,24 +1685,21 @@ class SeriesHostComponent {
1759
1685
  this._componentRef = this.viewContainerRef.createComponent(this.series.component);
1760
1686
  this._componentRef.instance.config = this.config;
1761
1687
  this._componentRef.instance.series = this.series;
1762
- this._componentRef.instance.size = this.size;
1763
- this._componentRef.instance.rect = this.rect;
1764
1688
  this._init = true;
1765
1689
  }
1766
- ngOnDestroy() { }
1690
+ ngOnDestroy() {
1691
+ this._componentRef.destroy();
1692
+ }
1767
1693
  ngOnChanges(changes) {
1768
- if (this._init && changes.hasOwnProperty('series')) {
1694
+ if (this._init && (changes.hasOwnProperty('series') || changes.hasOwnProperty('config'))) {
1769
1695
  this._componentRef.instance.config = this.config;
1770
1696
  this._componentRef.instance.series = this.series;
1771
- this._componentRef.instance.size = this.size;
1772
- this._componentRef.instance.rect = this.rect;
1773
- this._componentRef.injector.get(ChangeDetectorRef).markForCheck();
1774
1697
  this._componentRef.injector.get(ChangeDetectorRef).detectChanges();
1775
1698
  }
1776
1699
  }
1777
1700
  }
1778
- SeriesHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SeriesHostComponent, deps: [{ token: i0.ViewContainerRef }, { token: ChartService }], target: i0.ɵɵFactoryTarget.Component });
1779
- SeriesHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SeriesHostComponent, selector: "[teta-series-host]", inputs: { config: "config", series: "series", size: "size", rect: "rect" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1701
+ SeriesHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SeriesHostComponent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
1702
+ SeriesHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SeriesHostComponent, selector: "[teta-series-host]", inputs: { config: "config", series: "series" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1780
1703
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SeriesHostComponent, decorators: [{
1781
1704
  type: Component,
1782
1705
  args: [{
@@ -1784,23 +1707,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
1784
1707
  template: '',
1785
1708
  changeDetection: ChangeDetectionStrategy.OnPush,
1786
1709
  }]
1787
- }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: ChartService }]; }, propDecorators: { config: [{
1710
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }]; }, propDecorators: { config: [{
1788
1711
  type: Input
1789
1712
  }], series: [{
1790
1713
  type: Input
1791
- }], size: [{
1792
- type: Input
1793
- }], rect: [{
1714
+ }] } });
1715
+
1716
+ class AnnotationComponent {
1717
+ constructor(scaleService, cdr, chartService) {
1718
+ this.scaleService = scaleService;
1719
+ this.cdr = cdr;
1720
+ this.chartService = chartService;
1721
+ this.x = this.scaleService.xScaleMap.pipe(map((_) => _.get(this.annotation.xAxisIndex ?? 0)));
1722
+ this.y = this.scaleService.yScaleMap.pipe(map((_) => _.get(this.annotation.yAxisIndex ?? 0)));
1723
+ this.drag = d3.drag();
1724
+ }
1725
+ set annotation(annotation) {
1726
+ this._annotation = annotation;
1727
+ }
1728
+ get annotation() {
1729
+ return this._annotation;
1730
+ }
1731
+ set node(node) {
1732
+ this._node = node;
1733
+ this.init();
1734
+ this.cdr.detectChanges();
1735
+ }
1736
+ get node() {
1737
+ return this._node;
1738
+ }
1739
+ click(event) {
1740
+ this.chartService.emitAnnotation({
1741
+ event,
1742
+ target: this.annotation
1743
+ });
1744
+ }
1745
+ contextMenu(event) {
1746
+ this.chartService.emitAnnotation({
1747
+ event,
1748
+ target: this.annotation
1749
+ });
1750
+ }
1751
+ ngOnDestroy() {
1752
+ this.drag.on('drag end', null);
1753
+ }
1754
+ init() {
1755
+ d3.select(this.node.nativeElement).datum(this.annotation);
1756
+ if (this.annotation.draggable) {
1757
+ this.drag.on('drag end', (event, d) => {
1758
+ d.dx += event.dx;
1759
+ d.dy += event.dy;
1760
+ this.cdr.detectChanges();
1761
+ this.chartService.emitMoveAnnotation({
1762
+ event,
1763
+ target: d
1764
+ });
1765
+ });
1766
+ d3.select(this.node.nativeElement).call(this.drag);
1767
+ }
1768
+ }
1769
+ }
1770
+ AnnotationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AnnotationComponent, deps: [{ token: ScaleService }, { token: i0.ChangeDetectorRef }, { token: ChartService }], target: i0.ɵɵFactoryTarget.Component });
1771
+ AnnotationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: AnnotationComponent, selector: "[teta-annotation]", inputs: { annotation: "annotation" }, host: { listeners: { "click": "click($event)", "contextmenu": "contextMenu($event)" } }, viewQueries: [{ propertyName: "node", first: true, predicate: ["annotationNode"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"{\n x: x | async,\n y: y | async\n } as data\">\n <svg:circle\n [attr.r]=\"annotation.style?.radius ?? 5\"\n [attr.cx]=\"data.x(annotation.point.x)\"\n [attr.fill]=\"annotation?.style?.fill ?? 'var(--color-text-90)'\"\n [attr.cy]=\"data.y(annotation.point.y)\">\n </svg:circle>\n <svg:line\n [attr.x1]=\"data.x(annotation.point.x)\"\n [attr.y1]=\"data.y(annotation.point.y)\"\n [attr.x2]=\"data.x(annotation.point.x) + (annotation.dx ?? 0)\"\n [attr.y2]=\"data.y(annotation.point.y) + (annotation.dy ?? 0)\"\n [attr.stroke]=\"annotation.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"annotation.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"annotation.style?.strokeDasharray ?? null\"\n >\n </svg:line>\n <svg:foreignObject\n class=\"position-absolute\"\n [attr.width]=\"node?.nativeElement.offsetWidth ?? 0\"\n [attr.height]=\"node?.nativeElement.offsetHeight ?? 0\"\n [attr.x]=\"data.x(annotation.point.x) + (annotation.dx ?? 0) - 10\"\n [attr.y]=\"data.y(annotation.point.y) + (annotation.dy ?? 0) - 10\">\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-text-90)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n class=\"color-text-10 padding-h-2\"\n style=\"border-radius: 2px; display: inline-block;\">\n <ng-container *ngIf=\"annotation.template;else default\">\n <ng-container *ngTemplateOutlet=\"annotation.template;context: {$implicit: annotation}\"></ng-container>\n </ng-container>\n </div>\n </svg:foreignObject>\n</ng-container>\n<ng-template #default>\n {{ annotation.note?.label}}\n</ng-template>\n", styles: [""], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1772
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: AnnotationComponent, decorators: [{
1773
+ type: Component,
1774
+ args: [{ selector: '[teta-annotation]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n x: x | async,\n y: y | async\n } as data\">\n <svg:circle\n [attr.r]=\"annotation.style?.radius ?? 5\"\n [attr.cx]=\"data.x(annotation.point.x)\"\n [attr.fill]=\"annotation?.style?.fill ?? 'var(--color-text-90)'\"\n [attr.cy]=\"data.y(annotation.point.y)\">\n </svg:circle>\n <svg:line\n [attr.x1]=\"data.x(annotation.point.x)\"\n [attr.y1]=\"data.y(annotation.point.y)\"\n [attr.x2]=\"data.x(annotation.point.x) + (annotation.dx ?? 0)\"\n [attr.y2]=\"data.y(annotation.point.y) + (annotation.dy ?? 0)\"\n [attr.stroke]=\"annotation.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"annotation.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"annotation.style?.strokeDasharray ?? null\"\n >\n </svg:line>\n <svg:foreignObject\n class=\"position-absolute\"\n [attr.width]=\"node?.nativeElement.offsetWidth ?? 0\"\n [attr.height]=\"node?.nativeElement.offsetHeight ?? 0\"\n [attr.x]=\"data.x(annotation.point.x) + (annotation.dx ?? 0) - 10\"\n [attr.y]=\"data.y(annotation.point.y) + (annotation.dy ?? 0) - 10\">\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-text-90)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n class=\"color-text-10 padding-h-2\"\n style=\"border-radius: 2px; display: inline-block;\">\n <ng-container *ngIf=\"annotation.template;else default\">\n <ng-container *ngTemplateOutlet=\"annotation.template;context: {$implicit: annotation}\"></ng-container>\n </ng-container>\n </div>\n </svg:foreignObject>\n</ng-container>\n<ng-template #default>\n {{ annotation.note?.label}}\n</ng-template>\n", styles: [""] }]
1775
+ }], ctorParameters: function () { return [{ type: ScaleService }, { type: i0.ChangeDetectorRef }, { type: ChartService }]; }, propDecorators: { annotation: [{
1794
1776
  type: Input
1777
+ }], node: [{
1778
+ type: ViewChild,
1779
+ args: ['annotationNode', { static: false }]
1780
+ }], click: [{
1781
+ type: HostListener,
1782
+ args: ['click', ['$event']]
1783
+ }], contextMenu: [{
1784
+ type: HostListener,
1785
+ args: ['contextmenu', ['$event']]
1795
1786
  }] } });
1796
1787
 
1797
1788
  class ZoomableDirective {
1798
- constructor(elementRef, zoomService, broadcastService) {
1789
+ constructor(elementRef, zoomService, broadcastService, zone) {
1799
1790
  this.elementRef = elementRef;
1800
1791
  this.zoomService = zoomService;
1801
1792
  this.broadcastService = broadcastService;
1793
+ this.zone = zone;
1802
1794
  this.zoomable = false;
1803
1795
  this.alive = true;
1796
+ this.currentTransform = zoomIdentity;
1797
+ this.zoomed = (event) => {
1798
+ if (event.sourceEvent) {
1799
+ if (Object.keys(event.sourceEvent).length !== 0) {
1800
+ if (this.currentTransform === event.transform && event.type !== 'end') {
1801
+ return;
1802
+ }
1803
+ const origin = this.brushScale.copy().domain(this.zoomAxis.extremes);
1804
+ let domain = this.config.zoom?.type === ZoomType.y ?
1805
+ event.transform.rescaleY(origin).domain() :
1806
+ event.transform.rescaleX(origin).domain();
1807
+ const message = new ZoomMessage({
1808
+ event,
1809
+ axis: this.zoomAxis,
1810
+ brushDomain: domain
1811
+ });
1812
+ this.broadcastService.broadcastZoom({
1813
+ channel: this.config?.zoom?.syncChannel,
1814
+ message,
1815
+ });
1816
+ }
1817
+ this.zoomService.setZoom({
1818
+ event,
1819
+ target: this.zoomAxis
1820
+ });
1821
+ this.currentTransform = event.transform;
1822
+ }
1823
+ };
1804
1824
  }
1805
1825
  ngOnInit() {
1806
1826
  if (this.axis?.options?.zoom || this.config?.zoom?.enable) {
@@ -1808,84 +1828,80 @@ class ZoomableDirective {
1808
1828
  }
1809
1829
  }
1810
1830
  ngAfterViewInit() {
1811
- const enable = this.axis?.options?.zoom || this.config?.zoom?.enable;
1831
+ const enable = this.axis?.options?.zoom && this.axis?.options.visible || this.config?.zoom?.enable;
1812
1832
  if (!enable) {
1813
1833
  return;
1814
1834
  }
1815
1835
  this._element = d3.select(this.elementRef.nativeElement);
1816
1836
  this.zoom = d3
1817
1837
  .zoom()
1818
- .scaleExtent([0, Infinity])
1819
1838
  .extent([
1820
1839
  [0, 0],
1821
1840
  [this.size.width, this.size.height],
1822
1841
  ]);
1823
1842
  const commonZoomAxis = Axis.createAxis(this.config?.zoom.type === ZoomType.x ? AxisOrientation.x : AxisOrientation.y, this.config, 0, true);
1824
1843
  this.zoomAxis = this.axis ?? commonZoomAxis;
1825
- const zoomed = (event) => {
1826
- if (enable) {
1827
- if (event.sourceEvent) {
1828
- this.zoomService.setZoom({
1829
- event,
1830
- target: this.zoomAxis
1831
- });
1832
- const message = new ZoomMessage({
1833
- event,
1834
- axis: this.zoomAxis,
1835
- brushDomain: this.config.brush?.type === BrushType.x
1836
- ? this.brushScale.domain()
1837
- : this.brushScale.domain(),
1838
- });
1839
- this.broadcastService.broadcastZoom({
1840
- channel: this.config?.zoom?.syncChannel,
1841
- message,
1842
- });
1843
- }
1844
- }
1845
- };
1846
- this.zoom.on('start zoom end', zoomed);
1847
- this._element.call(this.zoom);
1844
+ if (enable) {
1845
+ const maxZoom = this.config.zoom?.max ? (this.zoomAxis.extremes[1] - this.zoomAxis.extremes[0]) / this.config.zoom?.max : 0;
1846
+ const minZoom = this.config.zoom?.min ? (this.zoomAxis.extremes[1] - this.zoomAxis.extremes[0]) / this.config.zoom?.min : Infinity;
1847
+ this.zoom.scaleExtent([maxZoom, minZoom]);
1848
+ console.log(this.zoom.scaleExtent());
1849
+ this.zoom.on('start zoom end', this.zoomed);
1850
+ this._element.call(this.zoom);
1851
+ }
1848
1852
  // Subscribe to zoom events
1849
- this.broadcastService.subscribeToZoom(this.config?.zoom.syncChannel).pipe(takeWhile((_) => this.alive), filter((m) => m.message.event.sourceEvent instanceof MouseEvent || m.message.event.sourceEvent instanceof WheelEvent), throttleTime(50, undefined, { trailing: true }), filter((m) => {
1853
+ this.broadcastService.subscribeToZoom(this.config?.zoom.syncChannel).pipe(filter((m) => m.message.event.sourceEvent instanceof MouseEvent || m.message.event.sourceEvent instanceof WheelEvent), debounceTime(30), filter((m) => {
1850
1854
  return this.zoomAxis.index === m.message?.axis?.index && this.zoomAxis.orientation === m.message?.axis?.orientation;
1851
1855
  }), tap$1((m) => {
1852
1856
  const currentTransform = d3.zoomTransform(this.elementRef.nativeElement);
1853
1857
  if (currentTransform !== m.message.event.transform) {
1854
1858
  this._element.call(this.zoom.transform, m.message.event.transform, null, {});
1855
1859
  }
1856
- })).subscribe();
1860
+ }), takeWhile((_) => this.alive)).subscribe();
1857
1861
  // Subscribe to brush events x or y
1858
- if ((this.config.brush?.type === BrushType.x && this.zoomAxis.orientation === AxisOrientation.x) || (this.config.brush?.type === BrushType.y && this.zoomAxis.orientation === AxisOrientation.y)) {
1859
- this.broadcastService.subscribeToBrush(this.config?.zoom.syncChannel).pipe(takeWhile((_) => this.alive), throttleTime(50, undefined, { trailing: true }), filter((m) => Boolean(m.message.selection)), tap$1((m) => {
1860
- const s = m.message.selection;
1861
- this.brushScale.domain(m.message.brushScale.domain());
1862
- const domain = this.brushScale.domain();
1863
- const scale = (domain[1] - domain[0]) / (s[1] - s[0]);
1864
- let transform = zoomIdentity.scale(scale);
1865
- if (m.message?.brushType === BrushType.x) {
1866
- transform = transform.translate(-this.brushScale(s[0]), 0);
1867
- }
1868
- if (m.message?.brushType === BrushType.y) {
1869
- transform = transform.translate(0, -this.brushScale(s[0]));
1862
+ if ((this.config.brush?.type === BrushType.x && this.zoomAxis.orientation === AxisOrientation.x) ||
1863
+ (this.config.brush?.type === BrushType.y && this.zoomAxis.orientation === AxisOrientation.y)) {
1864
+ this.broadcastService.subscribeToBrush(this.config?.zoom.syncChannel).pipe(debounceTime(30), filter((m) => Boolean(m.message.selection)), tap$1((m) => {
1865
+ const currentTransform = d3.zoomTransform(this.elementRef.nativeElement);
1866
+ if (!m.message.event && this.currentSelection && currentTransform.k !== 1) {
1867
+ return;
1870
1868
  }
1871
- this._element.call(this.zoom.transform, transform, null, {});
1872
- })).subscribe();
1869
+ this.currentSelection = m.message.selection;
1870
+ this.zone.runOutsideAngular(() => {
1871
+ setTimeout(() => {
1872
+ this.updateZoom(m);
1873
+ }, 100);
1874
+ });
1875
+ }), takeWhile((_) => this.alive)).subscribe();
1873
1876
  }
1874
1877
  }
1875
- ngOnChanges(changes) {
1876
- }
1877
1878
  ngOnDestroy() {
1879
+ this.zoom?.on('start zoom end', null);
1878
1880
  this.alive = false;
1879
1881
  }
1882
+ updateZoom(m) {
1883
+ const s = m.message.selection;
1884
+ this.brushScale.domain(this.zoomAxis.extremes);
1885
+ const domain = this.brushScale.domain();
1886
+ const scale = (domain[1] - domain[0]) / (s[1] - s[0]);
1887
+ let transform = zoomIdentity.scale(scale);
1888
+ if (m.message?.brushType === BrushType.x) {
1889
+ transform = transform.translate(-this.brushScale(s[0]), 0);
1890
+ }
1891
+ if (m.message?.brushType === BrushType.y) {
1892
+ transform = transform.translate(0, -this.brushScale(s[0]));
1893
+ }
1894
+ this._element.transition().duration(150).call(this.zoom.transform, transform, null, {});
1895
+ }
1880
1896
  }
1881
- ZoomableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ZoomableDirective, deps: [{ token: i0.ElementRef }, { token: ZoomService }, { token: BroadcastService }], target: i0.ɵɵFactoryTarget.Directive });
1882
- ZoomableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.1", type: ZoomableDirective, selector: "[tetaZoomable]", inputs: { config: "config", axis: "axis", size: "size", brushScale: "brushScale" }, host: { properties: { "class.zoomable": "this.zoomable" } }, usesOnChanges: true, ngImport: i0 });
1897
+ ZoomableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ZoomableDirective, deps: [{ token: i0.ElementRef }, { token: ZoomService }, { token: BroadcastService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
1898
+ ZoomableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.1", type: ZoomableDirective, selector: "[tetaZoomable]", inputs: { config: "config", axis: "axis", size: "size", brushScale: "brushScale" }, host: { properties: { "class.zoomable": "this.zoomable" } }, ngImport: i0 });
1883
1899
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ZoomableDirective, decorators: [{
1884
1900
  type: Directive,
1885
1901
  args: [{
1886
1902
  selector: '[tetaZoomable]',
1887
1903
  }]
1888
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ZoomService }, { type: BroadcastService }]; }, propDecorators: { config: [{
1904
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ZoomService }, { type: BroadcastService }, { type: i0.NgZone }]; }, propDecorators: { config: [{
1889
1905
  type: Input
1890
1906
  }], axis: [{
1891
1907
  type: Input
@@ -1905,7 +1921,8 @@ class BrushableDirective {
1905
1921
  this.element = element;
1906
1922
  }
1907
1923
  ngOnInit() { }
1908
- ngAfterViewInit() { }
1924
+ ngAfterViewInit() {
1925
+ }
1909
1926
  ngOnChanges(changes) {
1910
1927
  if (changes.hasOwnProperty('config')) {
1911
1928
  this.brushService.clearPreviousSelection();
@@ -1955,7 +1972,10 @@ class ChartContainerComponent {
1955
1972
  return config.brush?.type === BrushType.x
1956
1973
  ? x.get(0)
1957
1974
  : y.get(0);
1958
- }), shareReplay(1));
1975
+ }), shareReplay({
1976
+ bufferSize: 1,
1977
+ refCount: true
1978
+ }));
1959
1979
  this.visibleRect = combineLatest([
1960
1980
  this.size,
1961
1981
  this.xAxisMap,
@@ -2002,7 +2022,8 @@ class ChartContainerComponent {
2002
2022
  });
2003
2023
  this._observer.observe(this._elementRef.nativeElement);
2004
2024
  }
2005
- ngAfterViewInit() {
2025
+ ngOnDestroy() {
2026
+ this._observer.disconnect();
2006
2027
  }
2007
2028
  getTranslate(axis, size) {
2008
2029
  return combineLatest([this.xAxisMap, this.yAxisMap]).pipe(map((data) => {
@@ -2074,10 +2095,10 @@ class ChartContainerComponent {
2074
2095
  }
2075
2096
  }
2076
2097
  ChartContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChartContainerComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ScaleService }, { token: ZoomService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2077
- ChartContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChartContainerComponent, selector: "teta-chart-container", ngImport: i0, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n xAxisMap: xAxisMap | async,\n yAxisMap: yAxisMap | async,\n xScaleMap: xScaleMap | async,\n yScaleMap: yScaleMap | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.yAxisMap | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [scale]=\"data.yScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.size.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.xAxisMap | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [scale]=\"data.xScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"0\"\n [attr.y]=\"0\"\n [attr.width]=\"data.size.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0\">\n <svg\n tetaBrushable\n tetaZoomable\n [size]=\"data.size\"\n [brushScale]=\"data.brushScale\"\n [config]=\"data.config\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.transform]=\"'translate('+ data.visibleRect.x +', '+ data.visibleRect.y +')'\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n (contextmenu)=\"contextMenu($event, data.xScaleMap, data.yScaleMap)\"\n (click)=\"click($event, data.xScaleMap, data.yScaleMap)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines !== false\"\n [size]=\"data.size\"\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"\n [annotations]=\"data.config.annotations\"></g>\n </g>\n <g class=\"series-container\">\n <g teta-series-host\n *ngFor=\"let series of data.config.series\"\n [config]=\"data.config\"\n [series]=\"series\"\n [size]=\"data.size\"></g>\n </g>\n\n </svg>\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}\n"], components: [{ type: TooltipComponent, selector: "teta-tooltip", inputs: ["size", "config"] }, { type: YAxisComponent, selector: "[teta-y-axis]", inputs: ["axis", "scale", "size"] }, { type: XAxisComponent, selector: "[teta-x-axis]", inputs: ["axis", "scale", "size"] }, { type: GridlinesComponent, selector: "[teta-gridlines]", inputs: ["size", "xScaleMap", "yScaleMap"] }, { type: PlotBandComponent, selector: "[teta-plot-band]", inputs: ["plotBand", "axis", "scale", "size"] }, { type: PlotlineComponent, selector: "[teta-plot-line]", inputs: ["plotLine", "size", "axis", "scale"] }, { type: AnnotationComponent, selector: "[teta-annotation]", inputs: ["annotations", "xScaleMap", "yScaleMap"] }, { type: SeriesHostComponent, selector: "[teta-series-host]", inputs: ["config", "series", "size", "rect"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: ZoomableDirective, selector: "[tetaZoomable]", inputs: ["config", "axis", "size", "brushScale"] }, { type: BrushableDirective, selector: "svg:svg[tetaBrushable]", inputs: ["config", "size", "brushScale"] }], pipes: { "async": i4.AsyncPipe, "keyvalue": i4.KeyValuePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2098
+ ChartContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChartContainerComponent, selector: "teta-chart-container", ngImport: i0, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n xAxisMap: xAxisMap | async,\n yAxisMap: yAxisMap | async,\n xScaleMap: xScaleMap | async,\n yScaleMap: yScaleMap | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\" xmlns:svg=\"http://www.w3.org/1999/html\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.yAxisMap | keyvalue;\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [scale]=\"data.yScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.size.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.xAxisMap | keyvalue;\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [scale]=\"data.xScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"0\"\n [attr.y]=\"0\"\n [attr.width]=\"data.size.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0\">\n <svg\n tetaBrushable\n tetaZoomable\n [size]=\"data.size\"\n [brushScale]=\"data.brushScale\"\n [config]=\"data.config\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.transform]=\"'translate('+ data.visibleRect.x +', '+ data.visibleRect.y +')'\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n (contextmenu)=\"contextMenu($event, data.xScaleMap, data.yScaleMap)\"\n (click)=\"click($event, data.xScaleMap, data.yScaleMap)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines?.enable !== false\"\n [size]=\"data.size\"\n [config]=\"data.config\"\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"series-container\">\n <g teta-series-host\n *ngFor=\"let series of data.config.series\"\n [config]=\"data.config\"\n [series]=\"series\"></g>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n *ngFor=\"let annotation of data.config.annotations\"\n [annotation]=\"annotation\"></g>\n </g>\n </svg>\n\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}\n"], components: [{ type: TooltipComponent, selector: "teta-tooltip", inputs: ["size", "config"] }, { type: YAxisComponent, selector: "[teta-y-axis]", inputs: ["axis", "scale", "size"] }, { type: XAxisComponent, selector: "[teta-x-axis]", inputs: ["axis", "scale", "size"] }, { type: GridlinesComponent, selector: "[teta-gridlines]", inputs: ["size", "xScaleMap", "yScaleMap", "config"] }, { type: PlotBandComponent, selector: "[teta-plot-band]", inputs: ["plotBand", "axis", "scale", "size"] }, { type: PlotlineComponent, selector: "[teta-plot-line]", inputs: ["plotLine", "size", "axis", "scale"] }, { type: SeriesHostComponent, selector: "[teta-series-host]", inputs: ["config", "series"] }, { type: AnnotationComponent, selector: "[teta-annotation]", inputs: ["annotation"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: ZoomableDirective, selector: "[tetaZoomable]", inputs: ["config", "axis", "size", "brushScale"] }, { type: BrushableDirective, selector: "svg:svg[tetaBrushable]", inputs: ["config", "size", "brushScale"] }], pipes: { "async": i4.AsyncPipe, "keyvalue": i4.KeyValuePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2078
2099
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChartContainerComponent, decorators: [{
2079
2100
  type: Component,
2080
- args: [{ selector: 'teta-chart-container', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n xAxisMap: xAxisMap | async,\n yAxisMap: yAxisMap | async,\n xScaleMap: xScaleMap | async,\n yScaleMap: yScaleMap | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.yAxisMap | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [scale]=\"data.yScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.size.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.xAxisMap | keyvalue; trackBy: identify\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [scale]=\"data.xScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"0\"\n [attr.y]=\"0\"\n [attr.width]=\"data.size.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0\">\n <svg\n tetaBrushable\n tetaZoomable\n [size]=\"data.size\"\n [brushScale]=\"data.brushScale\"\n [config]=\"data.config\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.transform]=\"'translate('+ data.visibleRect.x +', '+ data.visibleRect.y +')'\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n (contextmenu)=\"contextMenu($event, data.xScaleMap, data.yScaleMap)\"\n (click)=\"click($event, data.xScaleMap, data.yScaleMap)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines !== false\"\n [size]=\"data.size\"\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"\n [annotations]=\"data.config.annotations\"></g>\n </g>\n <g class=\"series-container\">\n <g teta-series-host\n *ngFor=\"let series of data.config.series\"\n [config]=\"data.config\"\n [series]=\"series\"\n [size]=\"data.size\"></g>\n </g>\n\n </svg>\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}\n"] }]
2101
+ args: [{ selector: 'teta-chart-container', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n size: size | async,\n config: config | async,\n xAxisMap: xAxisMap | async,\n yAxisMap: yAxisMap | async,\n xScaleMap: xScaleMap | async,\n yScaleMap: yScaleMap | async,\n visibleRect: visibleRect | async,\n brushScale: brushScale | async\n} as data\" xmlns:svg=\"http://www.w3.org/1999/html\">\n <teta-tooltip *ngIf=\"data.config?.tooltip?.enable\"\n [size]=\"data.size\"\n [config]=\"data.config\"></teta-tooltip>\n\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n <ng-container *ngFor=\"let item of data.yAxisMap | keyvalue;\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-y-axis\n [axis]=\"item.value\"\n [scale]=\"data.yScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.size.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n\n </ng-container>\n </g>\n <g class=\"x-axis-container\">\n <ng-container *ngFor=\"let item of data.xAxisMap | keyvalue;\">\n <ng-container *ngIf=\"item.value.options.visible\">\n <g\n teta-x-axis\n [axis]=\"item.value\"\n [scale]=\"data.xScaleMap.get(item.key)\"\n [size]=\"data.size\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect\n tetaZoomable\n fill-opacity=\"0\"\n [brushScale]=\"data.brushScale\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.size\"\n [attr.x]=\"0\"\n [attr.y]=\"0\"\n [attr.width]=\"data.size.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n </ng-container>\n </ng-container>\n </g>\n </svg>\n <ng-container *ngIf=\"data.visibleRect?.width > 0 && data.visibleRect?.height > 0\">\n <svg\n tetaBrushable\n tetaZoomable\n [size]=\"data.size\"\n [brushScale]=\"data.brushScale\"\n [config]=\"data.config\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.transform]=\"'translate('+ data.visibleRect.x +', '+ data.visibleRect.y +')'\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n (contextmenu)=\"contextMenu($event, data.xScaleMap, data.yScaleMap)\"\n (click)=\"click($event, data.xScaleMap, data.yScaleMap)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n <g class=\"gridlines\"\n teta-gridlines\n *ngIf=\"data.config.gridLines?.enable !== false\"\n [size]=\"data.size\"\n [config]=\"data.config\"\n [xScaleMap]=\"data.xScaleMap\"\n [yScaleMap]=\"data.yScaleMap\"></g>\n\n <g class=\"x-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotband-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-band *ngFor=\"let plotBand of axis.plotBands\"\n [plotBand]=\"plotBand\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"x-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.xAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.xScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.xAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"y-axis-plotline-container\">\n <ng-container *ngFor=\"let axis of data.config.yAxis; let i = index\">\n <g teta-plot-line *ngFor=\"let plotLine of axis.plotLines\"\n [plotLine]=\"plotLine\"\n [scale]=\"data.yScaleMap.get(i)\"\n [size]=\"data.size\"\n [axis]=\"data.yAxisMap.get(i)\"></g>\n </ng-container>\n </g>\n <g class=\"series-container\">\n <g teta-series-host\n *ngFor=\"let series of data.config.series\"\n [config]=\"data.config\"\n [series]=\"series\"></g>\n </g>\n <g class=\"annotations\">\n <g teta-annotation\n *ngFor=\"let annotation of data.config.annotations\"\n [annotation]=\"annotation\"></g>\n </g>\n </svg>\n\n </ng-container>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;flex-grow:1;min-width:0;min-height:0}:host .zoomable:hover{cursor:grab}:host .zoomable:active{cursor:grabbing}\n"] }]
2081
2102
  }], ctorParameters: function () { return [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ScaleService }, { type: ZoomService }, { type: i0.ElementRef }]; } });
2082
2103
 
2083
2104
  class LegendComponent {
@@ -2107,9 +2128,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
2107
2128
  }] } });
2108
2129
 
2109
2130
  class ChartComponent {
2110
- constructor(_svc, _zoomService) {
2111
- this._svc = _svc;
2131
+ constructor(chartService, _zoomService, _scaleService) {
2132
+ this.chartService = chartService;
2112
2133
  this._zoomService = _zoomService;
2134
+ this._scaleService = _scaleService;
2135
+ this.pointerMove = new EventEmitter();
2113
2136
  this.plotBandsMove = new EventEmitter();
2114
2137
  this.plotBandClick = new EventEmitter();
2115
2138
  this.plotBandContextMenu = new EventEmitter();
@@ -2117,45 +2140,89 @@ class ChartComponent {
2117
2140
  this.pointMove = new EventEmitter();
2118
2141
  this.chartClick = new EventEmitter();
2119
2142
  this.chartContextMenu = new EventEmitter();
2143
+ this.annotationContextMenu = new EventEmitter();
2144
+ this.annotationClick = new EventEmitter();
2145
+ this.annotationMove = new EventEmitter();
2120
2146
  this._alive = true;
2121
- this.svcConfig = this._svc.config;
2147
+ this.svcConfig = this.chartService.config;
2122
2148
  this.hasSeriesData = this.svcConfig.pipe(map((_) => _.series?.length > 0 && _.series?.some((_) => _.data?.length > 0)));
2123
2149
  }
2124
2150
  set config(config) {
2125
- this._svc.setConfig(config);
2151
+ this.chartService.setConfig(config);
2126
2152
  }
2127
2153
  ngOnChanges(changes) {
2128
2154
  }
2129
2155
  ngOnInit() {
2130
- this._svc.plotBandEvent
2156
+ this.chartService.pointerMove
2157
+ .pipe(takeWhile(() => this._alive), withLatestFrom(this._scaleService.xScaleMap, this._scaleService.yScaleMap, this.chartService.config))
2158
+ .subscribe((data) => {
2159
+ const [event, x, y, config] = data;
2160
+ const tooltipTracking = config?.tooltip?.tracking;
2161
+ if (tooltipTracking === TooltipTracking.y) {
2162
+ const result = new Map();
2163
+ y.forEach((value, key) => {
2164
+ result.set(key, value.invert(event.offsetY));
2165
+ });
2166
+ this.pointerMove.emit({
2167
+ event: event,
2168
+ target: result
2169
+ });
2170
+ }
2171
+ else {
2172
+ const result = new Map();
2173
+ x.forEach((value, key) => {
2174
+ result.set(key, value.invert(event.offsetX));
2175
+ });
2176
+ this.pointerMove.emit({
2177
+ event: event,
2178
+ target: result
2179
+ });
2180
+ }
2181
+ });
2182
+ this.chartService.plotBandEvent
2131
2183
  .pipe(takeWhile(() => this._alive))
2132
2184
  .subscribe((_) => {
2133
2185
  this.plotBandsMove.emit(_);
2134
2186
  });
2135
- this._svc.plotLineMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
2187
+ this.chartService.plotLineMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
2136
2188
  this.plotLinesMove.emit(_);
2137
2189
  });
2138
- this._svc.pointMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
2190
+ this.chartService.pointMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
2139
2191
  this.pointMove.emit(_);
2140
2192
  });
2141
- this._svc.chartClick
2193
+ this.chartService.chartClick
2142
2194
  .pipe(takeWhile(() => this._alive)).subscribe((_) => {
2143
2195
  this.chartClick.emit(_);
2144
2196
  });
2145
- this._svc.chartContextMenu
2197
+ this.chartService.chartContextMenu
2146
2198
  .pipe(takeWhile(() => this._alive)).subscribe((_) => {
2147
2199
  this.chartContextMenu.emit(_);
2148
2200
  });
2149
- this._svc.plotBandClick
2201
+ this.chartService.plotBandClick
2150
2202
  .pipe(takeWhile(() => this._alive))
2151
2203
  .subscribe((_) => {
2152
2204
  this.plotBandClick.emit(_);
2153
2205
  });
2154
- this._svc.plotBandContextMenu
2206
+ this.chartService.plotBandContextMenu
2155
2207
  .pipe(takeWhile(() => this._alive))
2156
2208
  .subscribe((_) => {
2157
2209
  this.plotBandContextMenu.emit(_);
2158
2210
  });
2211
+ this.chartService.annotationContextMenu
2212
+ .pipe(takeWhile(() => this._alive))
2213
+ .subscribe((_) => {
2214
+ this.annotationContextMenu.emit(_);
2215
+ });
2216
+ this.chartService.annotationClick
2217
+ .pipe(takeWhile(() => this._alive))
2218
+ .subscribe((_) => {
2219
+ this.annotationClick.emit(_);
2220
+ });
2221
+ this.chartService.annotationMove
2222
+ .pipe(takeWhile(() => this._alive))
2223
+ .subscribe((_) => {
2224
+ this.annotationMove.emit(_);
2225
+ });
2159
2226
  }
2160
2227
  ngAfterViewInit() {
2161
2228
  }
@@ -2166,12 +2233,14 @@ class ChartComponent {
2166
2233
  });
2167
2234
  }
2168
2235
  }
2169
- ChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChartComponent, deps: [{ token: ChartService }, { token: ZoomService }], target: i0.ɵɵFactoryTarget.Component });
2170
- ChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChartComponent, selector: "teta-svg-chart", inputs: { config: "config" }, outputs: { plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", chartClick: "chartClick", chartContextMenu: "chartContextMenu" }, providers: [ChartService, ZoomService, ScaleService, BrushService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], components: [{ type: ChartContainerComponent, selector: "teta-chart-container" }, { type: LegendComponent, selector: "teta-legend", inputs: ["series"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2236
+ ChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChartComponent, deps: [{ token: ChartService }, { token: ZoomService }, { token: ScaleService }], target: i0.ɵɵFactoryTarget.Component });
2237
+ ChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChartComponent, selector: "teta-svg-chart", inputs: { config: "config" }, outputs: { pointerMove: "pointerMove", plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", chartClick: "chartClick", chartContextMenu: "chartContextMenu", annotationContextMenu: "annotationContextMenu", annotationClick: "annotationClick", annotationMove: "annotationMove" }, providers: [ChartService, ZoomService, ScaleService, BrushService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], components: [{ type: ChartContainerComponent, selector: "teta-chart-container" }, { type: LegendComponent, selector: "teta-legend", inputs: ["series"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2171
2238
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChartComponent, decorators: [{
2172
2239
  type: Component,
2173
2240
  args: [{ selector: 'teta-svg-chart', providers: [ChartService, ZoomService, ScaleService, BrushService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"{\n hasSeriesData: hasSeriesData | async,\n svcConfig: svcConfig | async\n} as data\">\n <ng-container *ngIf=\"data.hasSeriesData === true else noData\">\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container\"></teta-chart-container>\n </div>\n <teta-legend *ngIf=\"data.svcConfig.legend?.enable === true\" [series]=\"data.svcConfig.series\"></teta-legend>\n </ng-container>\n</ng-container>\n<ng-template #noData>\n <div class=\"column column_auto align-center justify-content-center\">\n <span class=\"font-body-3 color-text-40\">\u0414\u0430\u043D\u043D\u044B\u0435 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442</span>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"] }]
2174
- }], ctorParameters: function () { return [{ type: ChartService }, { type: ZoomService }]; }, propDecorators: { plotBandsMove: [{
2241
+ }], ctorParameters: function () { return [{ type: ChartService }, { type: ZoomService }, { type: ScaleService }]; }, propDecorators: { pointerMove: [{
2242
+ type: Output
2243
+ }], plotBandsMove: [{
2175
2244
  type: Output
2176
2245
  }], plotBandClick: [{
2177
2246
  type: Output
@@ -2185,6 +2254,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
2185
2254
  type: Output
2186
2255
  }], chartContextMenu: [{
2187
2256
  type: Output
2257
+ }], annotationContextMenu: [{
2258
+ type: Output
2259
+ }], annotationClick: [{
2260
+ type: Output
2261
+ }], annotationMove: [{
2262
+ type: Output
2188
2263
  }], config: [{
2189
2264
  type: Input
2190
2265
  }] } });
@@ -2197,6 +2272,7 @@ ChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "1
2197
2272
  ChartContainerComponent,
2198
2273
  LegendComponent,
2199
2274
  SeriesBaseComponent,
2275
+ LinearSeriesBase,
2200
2276
  LineSeriesComponent,
2201
2277
  GridlinesComponent,
2202
2278
  XAxisComponent,
@@ -2230,6 +2306,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
2230
2306
  ChartContainerComponent,
2231
2307
  LegendComponent,
2232
2308
  SeriesBaseComponent,
2309
+ LinearSeriesBase,
2233
2310
  LineSeriesComponent,
2234
2311
  GridlinesComponent,
2235
2312
  XAxisComponent,
@@ -2291,18 +2368,6 @@ class PlotLine {
2291
2368
  }
2292
2369
  }
2293
2370
 
2294
- const annotationMap = [
2295
- annotationBadge,
2296
- annotationLabel,
2297
- annotationCallout,
2298
- annotationCalloutCircle,
2299
- annotationCalloutCurve,
2300
- annotationCalloutElbow,
2301
- annotationCalloutRect,
2302
- annotationCustomType,
2303
- annotationXYThreshold,
2304
- ];
2305
-
2306
2371
  /*
2307
2372
  * Public API Surface of chart
2308
2373
  */