@tetacom/svg-charts 1.7.38 → 1.7.40

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.
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, input, inject, ChangeDetectorRef, ElementRef, computed, Component, ViewChild, Input, ChangeDetectionStrategy, HostListener, HostBinding, Directive, signal, effect, EventEmitter, Output, ViewContainerRef } from '@angular/core';
3
- import { ReplaySubject, filter, BehaviorSubject, Subject, of, shareReplay, withLatestFrom, map, merge, lastValueFrom, take, combineLatest, tap, takeWhile, observeOn, animationFrameScheduler, distinctUntilChanged } from 'rxjs';
3
+ import { ReplaySubject, filter, BehaviorSubject, Subject, of, shareReplay, withLatestFrom, map, merge, lastValueFrom, take, combineLatest, takeWhile, tap, observeOn, animationFrameScheduler, distinctUntilChanged } from 'rxjs';
4
4
  import * as d3 from 'd3';
5
5
  import { zoomIdentity } from 'd3';
6
6
  import { maxIndex } from 'd3-array';
7
7
  import { toSignal } from '@angular/core/rxjs-interop';
8
- import * as i3 from '@angular/platform-browser';
8
+ import { DomSanitizer } from '@angular/platform-browser';
9
9
  import { NgTemplateOutlet, AsyncPipe, KeyValuePipe, NgStyle } from '@angular/common';
10
10
  import { DialogService, Align as Align$1, TetaSize, ButtonComponent, DropdownComponent, DropdownContentDirective, DropdownHeadDirective, IconComponent, AccordionComponent, AccordionHeadComponent, AccordionItemComponent, AccordionContentDirective, ColorInputComponent, SelectComponent, SelectOptionDirective, SelectValueDirective, ScrollableComponent, InputComponent } from '@tetacom/ng-components';
11
11
  import * as i1 from '@angular/forms';
@@ -1196,29 +1196,24 @@ class PositionUtil {
1196
1196
  }
1197
1197
 
1198
1198
  class TooltipComponent {
1199
- constructor(svc, cdr, zoomService, sanitizer, _zone, _elementRef) {
1200
- this.svc = svc;
1201
- this.cdr = cdr;
1202
- this.zoomService = zoomService;
1203
- this.sanitizer = sanitizer;
1204
- this._zone = _zone;
1205
- this._elementRef = _elementRef;
1199
+ constructor() {
1200
+ this.svc = inject(ChartService);
1201
+ this.sanitizer = inject(DomSanitizer);
1202
+ this.pointerMove = toSignal(this.svc.pointerMove);
1203
+ this.display = computed(() => (this.pointerMove()?.type === 'mousemove' ? 1 : 0), ...(ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []));
1204
+ this.position = computed(() => {
1205
+ const event = this.pointerMove();
1206
+ if (!this.display() || !event) {
1207
+ return null;
1208
+ }
1209
+ return this.getPosition(event);
1210
+ }, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
1206
1211
  this.tooltips = this.svc.tooltips.pipe(map((_) => [..._.values()]));
1207
1212
  }
1208
1213
  getImplicit(t) {
1209
1214
  return { $implicit: t };
1210
1215
  }
1211
1216
  ngOnInit() {
1212
- this.display = this.svc.pointerMove.pipe(map((event) => {
1213
- return event.type === 'mousemove' ? 1 : 0;
1214
- }), tap(() => {
1215
- setTimeout(() => {
1216
- this.cdr.detectChanges();
1217
- });
1218
- }));
1219
- this.position = this.svc.pointerMove.pipe(filter((event) => !!event), map((_) => {
1220
- return this.getPosition(_);
1221
- }), tap(() => this.cdr.detectChanges()));
1222
1217
  const transformHtml = (html) => {
1223
1218
  return this.sanitizer.bypassSecurityTrustHtml(html);
1224
1219
  };
@@ -1243,8 +1238,7 @@ class TooltipComponent {
1243
1238
  if (tooltipList?.length < 1) {
1244
1239
  return '';
1245
1240
  }
1246
- const formatted = formatter ? transformHtml(formatter(tooltipList)) : defaultFormatter(tooltipList);
1247
- return formatted;
1241
+ return formatter ? transformHtml(formatter(tooltipList)) : defaultFormatter(tooltipList);
1248
1242
  }));
1249
1243
  }
1250
1244
  getPosition(event) {
@@ -1266,13 +1260,13 @@ class TooltipComponent {
1266
1260
  const format = d3.format(',.5~r');
1267
1261
  return format(input);
1268
1262
  }
1269
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TooltipComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: ZoomService }, { token: i3.DomSanitizer }, { token: i0.NgZone }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1270
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TooltipComponent, isStandalone: true, selector: "teta-tooltip", inputs: { size: "size", config: "config" }, viewQueries: [{ propertyName: "tooltip", first: true, predicate: ["tooltip"], descendants: true, read: ElementRef }], ngImport: i0, template: "@if ({ p: position | async }; as data) {\n @if (tooltips | async; as t) {\n @if (t.length > 0) {\n <div\n class=\"chart-tooltip color-text-90 bg-global-bgcard shadow-2\"\n #tooltip\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n [hidden]=\"!data.p\"\n style=\"pointer-events: none; min-width: 200px\"\n [style.left.px]=\"data.p?.left\"\n [style.top.px]=\"data.p?.top\"\n [style.bottom.px]=\"data.p?.bottom\"\n [style.right.px]=\"data.p?.right\"\n >\n @if (config.tooltip?.template) {\n <ng-container *ngTemplateOutlet=\"config.tooltip.template; context: getImplicit(t)\"></ng-container>\n }\n @if (config.tooltip?.format) {\n <div [innerHTML]=\"displayTooltips | async\"></div>\n } @else {\n @if (!config.tooltip?.template) {\n <div class=\"padding-2 border-radius-1\">\n @for (tooltip of t; track $index) {\n <div class=\"display-flex align-center\">\n <span\n class=\"display-block margin-right-1\"\n [style.width.px]=\"10\"\n [style.height.px]=\"2\"\n [style.background-color]=\"tooltip.series?.color\"\n >\n </span>\n <span class=\"font-title-3\">\n {{ tooltip.series?.name }}\n <span class=\"font-body-3\">\n x: {{ format(tooltip.point?.x) }} y: {{ format(tooltip.point?.y) }}\n </span>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n }\n }\n}\n", styles: [":host{position:absolute;z-index:2}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1263
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1264
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TooltipComponent, isStandalone: true, selector: "teta-tooltip", inputs: { size: "size", config: "config" }, viewQueries: [{ propertyName: "tooltip", first: true, predicate: ["tooltip"], descendants: true, read: ElementRef }], ngImport: i0, template: "@if ({ p: position() }; as data) {\n @if (tooltips | async; as t) {\n @if (t.length > 0) {\n <div\n class=\"chart-tooltip color-text-90 bg-global-bgcard shadow-2\"\n #tooltip\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display()\"\n [hidden]=\"!data.p\"\n style=\"pointer-events: none; min-width: 200px\"\n [style.left.px]=\"data.p?.left\"\n [style.top.px]=\"data.p?.top\"\n [style.bottom.px]=\"data.p?.bottom\"\n [style.right.px]=\"data.p?.right\"\n >\n @if (config.tooltip?.template) {\n <ng-container *ngTemplateOutlet=\"config.tooltip.template; context: getImplicit(t)\"></ng-container>\n }\n @if (config.tooltip?.format) {\n <div [innerHTML]=\"displayTooltips | async\"></div>\n } @else {\n @if (!config.tooltip?.template) {\n <div class=\"padding-2 border-radius-1\">\n @for (tooltip of t; track $index) {\n <div class=\"display-flex align-center\">\n <span\n class=\"display-block margin-right-1\"\n [style.width.px]=\"10\"\n [style.height.px]=\"2\"\n [style.background-color]=\"tooltip.series?.color\"\n >\n </span>\n <span class=\"font-title-3\">\n {{ tooltip.series?.name }}\n <span class=\"font-body-3\">\n x: {{ format(tooltip.point?.x) }} y: {{ format(tooltip.point?.y) }}\n </span>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n }\n }\n}\n", styles: [":host{position:absolute;z-index:2}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1271
1265
  }
1272
1266
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TooltipComponent, decorators: [{
1273
1267
  type: Component,
1274
- args: [{ selector: 'teta-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, NgTemplateOutlet], template: "@if ({ p: position | async }; as data) {\n @if (tooltips | async; as t) {\n @if (t.length > 0) {\n <div\n class=\"chart-tooltip color-text-90 bg-global-bgcard shadow-2\"\n #tooltip\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display | async\"\n [hidden]=\"!data.p\"\n style=\"pointer-events: none; min-width: 200px\"\n [style.left.px]=\"data.p?.left\"\n [style.top.px]=\"data.p?.top\"\n [style.bottom.px]=\"data.p?.bottom\"\n [style.right.px]=\"data.p?.right\"\n >\n @if (config.tooltip?.template) {\n <ng-container *ngTemplateOutlet=\"config.tooltip.template; context: getImplicit(t)\"></ng-container>\n }\n @if (config.tooltip?.format) {\n <div [innerHTML]=\"displayTooltips | async\"></div>\n } @else {\n @if (!config.tooltip?.template) {\n <div class=\"padding-2 border-radius-1\">\n @for (tooltip of t; track $index) {\n <div class=\"display-flex align-center\">\n <span\n class=\"display-block margin-right-1\"\n [style.width.px]=\"10\"\n [style.height.px]=\"2\"\n [style.background-color]=\"tooltip.series?.color\"\n >\n </span>\n <span class=\"font-title-3\">\n {{ tooltip.series?.name }}\n <span class=\"font-body-3\">\n x: {{ format(tooltip.point?.x) }} y: {{ format(tooltip.point?.y) }}\n </span>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n }\n }\n}\n", styles: [":host{position:absolute;z-index:2}\n"] }]
1275
- }], ctorParameters: () => [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: ZoomService }, { type: i3.DomSanitizer }, { type: i0.NgZone }, { type: i0.ElementRef }], propDecorators: { size: [{
1268
+ args: [{ selector: 'teta-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, NgTemplateOutlet], template: "@if ({ p: position() }; as data) {\n @if (tooltips | async; as t) {\n @if (t.length > 0) {\n <div\n class=\"chart-tooltip color-text-90 bg-global-bgcard shadow-2\"\n #tooltip\n [style.position]=\"'fixed'\"\n [style.opacity]=\"display()\"\n [hidden]=\"!data.p\"\n style=\"pointer-events: none; min-width: 200px\"\n [style.left.px]=\"data.p?.left\"\n [style.top.px]=\"data.p?.top\"\n [style.bottom.px]=\"data.p?.bottom\"\n [style.right.px]=\"data.p?.right\"\n >\n @if (config.tooltip?.template) {\n <ng-container *ngTemplateOutlet=\"config.tooltip.template; context: getImplicit(t)\"></ng-container>\n }\n @if (config.tooltip?.format) {\n <div [innerHTML]=\"displayTooltips | async\"></div>\n } @else {\n @if (!config.tooltip?.template) {\n <div class=\"padding-2 border-radius-1\">\n @for (tooltip of t; track $index) {\n <div class=\"display-flex align-center\">\n <span\n class=\"display-block margin-right-1\"\n [style.width.px]=\"10\"\n [style.height.px]=\"2\"\n [style.background-color]=\"tooltip.series?.color\"\n >\n </span>\n <span class=\"font-title-3\">\n {{ tooltip.series?.name }}\n <span class=\"font-body-3\">\n x: {{ format(tooltip.point?.x) }} y: {{ format(tooltip.point?.y) }}\n </span>\n </span>\n </div>\n }\n </div>\n }\n }\n </div>\n }\n }\n}\n", styles: [":host{position:absolute;z-index:2}\n"] }]
1269
+ }], ctorParameters: () => [], propDecorators: { size: [{
1276
1270
  type: Input
1277
1271
  }], config: [{
1278
1272
  type: Input
@@ -1794,9 +1788,17 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1794
1788
  this.markers = computed(() => {
1795
1789
  return this.series().data?.filter((_) => _?.marker && _?.x !== undefined && _?.y !== undefined && _?.x !== null && _?.y !== null);
1796
1790
  }, ...(ngDevMode ? [{ debugName: "markers" }] : /* istanbul ignore next */ []));
1791
+ this.sortedTooltipData = computed(() => {
1792
+ this.update();
1793
+ const data = [...this.series().data];
1794
+ const tooltipTracking = this.config()?.tooltip?.tracking;
1795
+ return data.sort(tooltipTracking === TooltipTracking.y ? (a, b) => a.y - b.y : (a, b) => a.x - b.x);
1796
+ }, ...(ngDevMode ? [{ debugName: "sortedTooltipData" }] : /* istanbul ignore next */ []));
1797
1797
  this.path = computed(() => {
1798
1798
  this.update();
1799
- if (!this.x() || !this.y()) {
1799
+ const x = this.x();
1800
+ const y = this.y();
1801
+ if (!x || !y) {
1800
1802
  return '';
1801
1803
  }
1802
1804
  const filter = this.defaultClipPointsMapping.get(this.series().clipPointsDirection);
@@ -1808,18 +1810,18 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1808
1810
  point.y !== undefined &&
1809
1811
  !isNaN(point.x) &&
1810
1812
  !isNaN(point.y))
1811
- .x((point) => this.x()(point.x))
1812
- .y((point) => this.y()(point.y));
1813
+ .x((point) => x(point.x))
1814
+ .y((point) => y(point.y));
1813
1815
  let filteredData = this.series().data;
1814
1816
  const clipOffset = this.getClipOffset();
1815
1817
  if (this.series().clipPointsDirection === ClipPointsDirection.x) {
1816
- let [min, max] = this.x().domain();
1818
+ let [min, max] = x.domain();
1817
1819
  min = min instanceof Date ? min.getTime() : min;
1818
1820
  max = max instanceof Date ? max.getTime() : max;
1819
1821
  filteredData = filteredData?.filter(filter(min - clipOffset.x, max - clipOffset.x));
1820
1822
  }
1821
1823
  if (this.series().clipPointsDirection === ClipPointsDirection.y) {
1822
- let [min, max] = this.y().domain();
1824
+ let [min, max] = y.domain();
1823
1825
  min = min instanceof Date ? min.getTime() : min;
1824
1826
  max = max instanceof Date ? max.getTime() : max;
1825
1827
  filteredData = filteredData?.filter(filter(min - clipOffset.y, max - clipOffset.y));
@@ -1891,7 +1893,7 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1891
1893
  return rV;
1892
1894
  };
1893
1895
  if (tooltipTracking === TooltipTracking.x) {
1894
- const sortedData = [...this.series().data].sort((a, b) => a.x - b.x);
1896
+ const sortedData = this.sortedTooltipData();
1895
1897
  const bisect = d3.bisector((_) => _.x).right;
1896
1898
  const pointer = mouse[0];
1897
1899
  let x0 = scaleX.invert(pointer);
@@ -1899,7 +1901,7 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1899
1901
  x0 = x0.getTime();
1900
1902
  }
1901
1903
  x0 = subtractOffset(x0, clipOffset.x);
1902
- const rightId = bisect([...this.series().data].sort((a, b) => a.x - b.x), x0);
1904
+ const rightId = bisect(sortedData, x0);
1903
1905
  const range = scaleY.range();
1904
1906
  const intersect = lineIntersection(pointer, range[0], pointer, Number.MAX_SAFE_INTEGER, scaleX(addOffset(sortedData[rightId - 1]?.x, clipOffset.x)), scaleY(addOffset(sortedData[rightId - 1]?.y, clipOffset.y)), scaleX(addOffset(sortedData[rightId]?.x, clipOffset.x)), scaleY(addOffset(sortedData[rightId]?.y, clipOffset.y)));
1905
1907
  const x = scaleX.invert(intersect.x);
@@ -1925,7 +1927,7 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1925
1927
  };
1926
1928
  }
1927
1929
  if (tooltipTracking === TooltipTracking.y) {
1928
- const sortedData = [...this.series().data].sort((a, b) => a.y - b.y);
1930
+ const sortedData = this.sortedTooltipData();
1929
1931
  const bisect = d3.bisector((_) => _.y).right;
1930
1932
  let y0 = scaleY.invert(mouse[1]);
1931
1933
  if (y0 instanceof Date) {
@@ -2442,24 +2444,27 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
2442
2444
  return scale(nextValue) - scale(domainStart);
2443
2445
  }
2444
2446
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2445
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: LineSeriesComponent, isStandalone: true, selector: "svg:svg[teta-line-series]", usesInheritance: true, ngImport: i0, template: "@if (series(); as series) {\n <svg:g\n [tetaDraggableSeries]=\"series.draggablePath\"\n [dragDirection]=\"series.pathDragType\"\n [attr.transform]=\"seriesPathTransform()\"\n [class.draggable-path]=\"series.draggablePath\"\n [class.selected-path]=\"seriesSelectedForPathDrag()\"\n (click)=\"seriesPathClick($event)\"\n (moveStart)=\"seriesMoveStart($event)\"\n (moveProcess)=\"seriesMoveProcess($event)\"\n (moveEnd)=\"seriesMoveEnd($event)\"\n >\n <svg:path\n class=\"line\"\n [class.line-selected]=\"seriesSelectedForPathDrag()\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [style.--series-color]=\"series.color\"\n fill=\"none\"\n ></svg:path>\n @if (series.draggablePath) {\n <svg:path\n class=\"line-hitbox\"\n [attr.d]=\"path()\"\n fill=\"none\"\n stroke=\"transparent\"\n stroke-width=\"14\"\n pointer-events=\"stroke\"\n ></svg:path>\n }\n </svg:g>\n @if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"\n ></svg:circle>\n }\n }\n @if (markers(); as draggablePoints) {\n @if (x() && y()) {\n @for (point of draggablePoints; track point) {\n <svg:g [attr.transform]=\"'translate(' + x()(point.x) + ',' + y()(point.y) + ')'\">\n <svg:g\n [tetaDraggablePoint]=\"point.marker.draggable\"\n [dragDirection]=\"point.marker.dragType\"\n [allowDrag]=\"allowDrag(point)\"\n #dragPoint=\"tetaDraggablePoint\"\n (moveStart)=\"moveStart($event, point)\"\n (moveEnd)=\"moveEnd($event, point); dragPoint.resetTransform()\"\n (moveProcess)=\"moveProcess($event, point); dragPoint.resetTransform()\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n >\n <svg:circle\n class=\"marker\"\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]=\"0\"\n [attr.cy]=\"0\"\n ></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line\n [attr.x1]=\"0\"\n [attr.y1]=\"0\"\n [attr.x2]=\"point.marker.label?.dx\"\n [attr.y2]=\"point.marker.label?.dy\"\n [attr.stroke]=\"point.marker.label?.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"point.marker.label?.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"point.marker.label?.style?.strokeDasharray ?? null\"\n ></svg:line>\n <svg:foreignObject\n [tetaDraggablePoint]=\"point.marker.label?.draggable\"\n [dragDirection]=\"point.marker.label.dragType\"\n #labelPoint=\"tetaDraggablePoint\"\n (moveStart)=\"startLabel($event, point.marker.label)\"\n (moveProcess)=\"moveLabel($event, point.marker.label); labelPoint.resetTransform()\"\n (moveEnd)=\"labelPoint.resetTransform()\"\n [attr.width]=\"annotationNode?.offsetWidth ?? 0\"\n [attr.height]=\"annotationNode?.offsetHeight ?? 0\"\n [attr.x]=\"point.marker.label?.dx\"\n [attr.y]=\"point.marker.label?.dy\"\n class=\"position-absolute\"\n >\n <div\n #annotationNode\n class=\"shadow-2 padding-2\"\n [style.color]=\"'var(--color-text-90)'\"\n [style.background-color]=\"'var(--color-global-bgcard)'\"\n [style.cursor]=\"'move'\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n {{ point.marker.label?.text }}\n </div>\n </svg:foreignObject>\n }\n </svg:g>\n </svg:g>\n }\n }\n }\n}\n", styles: [".draggable-marker{cursor:move}.draggable-path,.selected-path,.selected-path:active{cursor:ew-resize}.line-selected{filter:drop-shadow(0 0 3px var(--series-color))}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"], dependencies: [{ kind: "directive", type: DraggablePointDirective, selector: "[tetaDraggablePoint]", inputs: ["tetaDraggablePoint", "dragDirection", "allowDrag"], outputs: ["moveStart", "moveProcess", "moveEnd"], exportAs: ["tetaDraggablePoint"] }, { kind: "directive", type: DraggableSeriesDirective, selector: "[tetaDraggableSeries]", inputs: ["tetaDraggableSeries", "dragDirection"], outputs: ["moveStart", "moveProcess", "moveEnd"], exportAs: ["tetaDraggableSeries"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2447
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: LineSeriesComponent, isStandalone: true, selector: "svg:svg[teta-line-series]", usesInheritance: true, ngImport: i0, template: "@if (series(); as series) {\n <svg:g\n [tetaDraggableSeries]=\"series.draggablePath\"\n [dragDirection]=\"series.pathDragType\"\n [attr.transform]=\"seriesPathTransform()\"\n [class.draggable-path]=\"series.draggablePath\"\n [class.selected-path]=\"seriesSelectedForPathDrag()\"\n (click)=\"seriesPathClick($event)\"\n (moveStart)=\"seriesMoveStart($event)\"\n (moveProcess)=\"seriesMoveProcess($event)\"\n (moveEnd)=\"seriesMoveEnd($event)\"\n >\n <svg:path\n class=\"line\"\n [class.line-selected]=\"seriesSelectedForPathDrag()\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [style.--series-color]=\"series.color\"\n fill=\"none\"\n ></svg:path>\n @if (series.draggablePath) {\n <svg:path\n class=\"line-hitbox\"\n [attr.d]=\"path()\"\n fill=\"none\"\n stroke=\"transparent\"\n stroke-width=\"14\"\n pointer-events=\"stroke\"\n ></svg:path>\n }\n </svg:g>\n @if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"\n ></svg:circle>\n }\n }\n @if (markers(); as draggablePoints) {\n @if ({ x: x(), y: y() }; as scales) {\n @if (scales.x && scales.y) {\n @for (point of draggablePoints; track point) {\n <svg:g [attr.transform]=\"'translate(' + scales.x(point.x) + ',' + scales.y(point.y) + ')'\">\n <svg:g\n [tetaDraggablePoint]=\"point.marker.draggable\"\n [dragDirection]=\"point.marker.dragType\"\n [allowDrag]=\"allowDrag(point)\"\n #dragPoint=\"tetaDraggablePoint\"\n (moveStart)=\"moveStart($event, point)\"\n (moveEnd)=\"moveEnd($event, point); dragPoint.resetTransform()\"\n (moveProcess)=\"moveProcess($event, point); dragPoint.resetTransform()\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n >\n <svg:circle\n class=\"marker\"\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]=\"0\"\n [attr.cy]=\"0\"\n ></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line\n [attr.x1]=\"0\"\n [attr.y1]=\"0\"\n [attr.x2]=\"point.marker.label?.dx\"\n [attr.y2]=\"point.marker.label?.dy\"\n [attr.stroke]=\"point.marker.label?.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"point.marker.label?.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"point.marker.label?.style?.strokeDasharray ?? null\"\n ></svg:line>\n <svg:foreignObject\n [tetaDraggablePoint]=\"point.marker.label?.draggable\"\n [dragDirection]=\"point.marker.label.dragType\"\n #labelPoint=\"tetaDraggablePoint\"\n (moveStart)=\"startLabel($event, point.marker.label)\"\n (moveProcess)=\"moveLabel($event, point.marker.label); labelPoint.resetTransform()\"\n (moveEnd)=\"labelPoint.resetTransform()\"\n [attr.width]=\"annotationNode?.offsetWidth ?? 0\"\n [attr.height]=\"annotationNode?.offsetHeight ?? 0\"\n [attr.x]=\"point.marker.label?.dx\"\n [attr.y]=\"point.marker.label?.dy\"\n class=\"position-absolute\"\n >\n <div\n #annotationNode\n class=\"shadow-2 padding-2\"\n [style.color]=\"'var(--color-text-90)'\"\n [style.background-color]=\"'var(--color-global-bgcard)'\"\n [style.cursor]=\"'move'\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n {{ point.marker.label?.text }}\n </div>\n </svg:foreignObject>\n }\n </svg:g>\n </svg:g>\n }\n }\n }\n }\n}\n", styles: [".draggable-marker{cursor:move}.draggable-path,.selected-path,.selected-path:active{cursor:ew-resize}.line-selected{filter:drop-shadow(0 0 3px var(--series-color))}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"], dependencies: [{ kind: "directive", type: DraggablePointDirective, selector: "[tetaDraggablePoint]", inputs: ["tetaDraggablePoint", "dragDirection", "allowDrag"], outputs: ["moveStart", "moveProcess", "moveEnd"], exportAs: ["tetaDraggablePoint"] }, { kind: "directive", type: DraggableSeriesDirective, selector: "[tetaDraggableSeries]", inputs: ["tetaDraggableSeries", "dragDirection"], outputs: ["moveStart", "moveProcess", "moveEnd"], exportAs: ["tetaDraggableSeries"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2446
2448
  }
2447
2449
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, decorators: [{
2448
2450
  type: Component,
2449
- args: [{ selector: 'svg:svg[teta-line-series]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, DraggablePointDirective, DraggableSeriesDirective], template: "@if (series(); as series) {\n <svg:g\n [tetaDraggableSeries]=\"series.draggablePath\"\n [dragDirection]=\"series.pathDragType\"\n [attr.transform]=\"seriesPathTransform()\"\n [class.draggable-path]=\"series.draggablePath\"\n [class.selected-path]=\"seriesSelectedForPathDrag()\"\n (click)=\"seriesPathClick($event)\"\n (moveStart)=\"seriesMoveStart($event)\"\n (moveProcess)=\"seriesMoveProcess($event)\"\n (moveEnd)=\"seriesMoveEnd($event)\"\n >\n <svg:path\n class=\"line\"\n [class.line-selected]=\"seriesSelectedForPathDrag()\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [style.--series-color]=\"series.color\"\n fill=\"none\"\n ></svg:path>\n @if (series.draggablePath) {\n <svg:path\n class=\"line-hitbox\"\n [attr.d]=\"path()\"\n fill=\"none\"\n stroke=\"transparent\"\n stroke-width=\"14\"\n pointer-events=\"stroke\"\n ></svg:path>\n }\n </svg:g>\n @if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"\n ></svg:circle>\n }\n }\n @if (markers(); as draggablePoints) {\n @if (x() && y()) {\n @for (point of draggablePoints; track point) {\n <svg:g [attr.transform]=\"'translate(' + x()(point.x) + ',' + y()(point.y) + ')'\">\n <svg:g\n [tetaDraggablePoint]=\"point.marker.draggable\"\n [dragDirection]=\"point.marker.dragType\"\n [allowDrag]=\"allowDrag(point)\"\n #dragPoint=\"tetaDraggablePoint\"\n (moveStart)=\"moveStart($event, point)\"\n (moveEnd)=\"moveEnd($event, point); dragPoint.resetTransform()\"\n (moveProcess)=\"moveProcess($event, point); dragPoint.resetTransform()\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n >\n <svg:circle\n class=\"marker\"\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]=\"0\"\n [attr.cy]=\"0\"\n ></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line\n [attr.x1]=\"0\"\n [attr.y1]=\"0\"\n [attr.x2]=\"point.marker.label?.dx\"\n [attr.y2]=\"point.marker.label?.dy\"\n [attr.stroke]=\"point.marker.label?.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"point.marker.label?.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"point.marker.label?.style?.strokeDasharray ?? null\"\n ></svg:line>\n <svg:foreignObject\n [tetaDraggablePoint]=\"point.marker.label?.draggable\"\n [dragDirection]=\"point.marker.label.dragType\"\n #labelPoint=\"tetaDraggablePoint\"\n (moveStart)=\"startLabel($event, point.marker.label)\"\n (moveProcess)=\"moveLabel($event, point.marker.label); labelPoint.resetTransform()\"\n (moveEnd)=\"labelPoint.resetTransform()\"\n [attr.width]=\"annotationNode?.offsetWidth ?? 0\"\n [attr.height]=\"annotationNode?.offsetHeight ?? 0\"\n [attr.x]=\"point.marker.label?.dx\"\n [attr.y]=\"point.marker.label?.dy\"\n class=\"position-absolute\"\n >\n <div\n #annotationNode\n class=\"shadow-2 padding-2\"\n [style.color]=\"'var(--color-text-90)'\"\n [style.background-color]=\"'var(--color-global-bgcard)'\"\n [style.cursor]=\"'move'\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n {{ point.marker.label?.text }}\n </div>\n </svg:foreignObject>\n }\n </svg:g>\n </svg:g>\n }\n }\n }\n}\n", styles: [".draggable-marker{cursor:move}.draggable-path,.selected-path,.selected-path:active{cursor:ew-resize}.line-selected{filter:drop-shadow(0 0 3px var(--series-color))}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"] }]
2451
+ args: [{ selector: 'svg:svg[teta-line-series]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, DraggablePointDirective, DraggableSeriesDirective], template: "@if (series(); as series) {\n <svg:g\n [tetaDraggableSeries]=\"series.draggablePath\"\n [dragDirection]=\"series.pathDragType\"\n [attr.transform]=\"seriesPathTransform()\"\n [class.draggable-path]=\"series.draggablePath\"\n [class.selected-path]=\"seriesSelectedForPathDrag()\"\n (click)=\"seriesPathClick($event)\"\n (moveStart)=\"seriesMoveStart($event)\"\n (moveProcess)=\"seriesMoveProcess($event)\"\n (moveEnd)=\"seriesMoveEnd($event)\"\n >\n <svg:path\n class=\"line\"\n [class.line-selected]=\"seriesSelectedForPathDrag()\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n [style.--series-color]=\"series.color\"\n fill=\"none\"\n ></svg:path>\n @if (series.draggablePath) {\n <svg:path\n class=\"line-hitbox\"\n [attr.d]=\"path()\"\n fill=\"none\"\n stroke=\"transparent\"\n stroke-width=\"14\"\n pointer-events=\"stroke\"\n ></svg:path>\n }\n </svg:g>\n @if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle\n r=\"3\"\n [attr.fill]=\"series.color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"\n ></svg:circle>\n }\n }\n @if (markers(); as draggablePoints) {\n @if ({ x: x(), y: y() }; as scales) {\n @if (scales.x && scales.y) {\n @for (point of draggablePoints; track point) {\n <svg:g [attr.transform]=\"'translate(' + scales.x(point.x) + ',' + scales.y(point.y) + ')'\">\n <svg:g\n [tetaDraggablePoint]=\"point.marker.draggable\"\n [dragDirection]=\"point.marker.dragType\"\n [allowDrag]=\"allowDrag(point)\"\n #dragPoint=\"tetaDraggablePoint\"\n (moveStart)=\"moveStart($event, point)\"\n (moveEnd)=\"moveEnd($event, point); dragPoint.resetTransform()\"\n (moveProcess)=\"moveProcess($event, point); dragPoint.resetTransform()\"\n [class.draggable-marker]=\"point?.marker?.draggable\"\n >\n <svg:circle\n class=\"marker\"\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]=\"0\"\n [attr.cy]=\"0\"\n ></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line\n [attr.x1]=\"0\"\n [attr.y1]=\"0\"\n [attr.x2]=\"point.marker.label?.dx\"\n [attr.y2]=\"point.marker.label?.dy\"\n [attr.stroke]=\"point.marker.label?.style?.stroke ?? 'var(--color-text-90)'\"\n [attr.stroke-width]=\"point.marker.label?.style?.strokeWidth ?? 1\"\n [attr.stroke-dasharray]=\"point.marker.label?.style?.strokeDasharray ?? null\"\n ></svg:line>\n <svg:foreignObject\n [tetaDraggablePoint]=\"point.marker.label?.draggable\"\n [dragDirection]=\"point.marker.label.dragType\"\n #labelPoint=\"tetaDraggablePoint\"\n (moveStart)=\"startLabel($event, point.marker.label)\"\n (moveProcess)=\"moveLabel($event, point.marker.label); labelPoint.resetTransform()\"\n (moveEnd)=\"labelPoint.resetTransform()\"\n [attr.width]=\"annotationNode?.offsetWidth ?? 0\"\n [attr.height]=\"annotationNode?.offsetHeight ?? 0\"\n [attr.x]=\"point.marker.label?.dx\"\n [attr.y]=\"point.marker.label?.dy\"\n class=\"position-absolute\"\n >\n <div\n #annotationNode\n class=\"shadow-2 padding-2\"\n [style.color]=\"'var(--color-text-90)'\"\n [style.background-color]=\"'var(--color-global-bgcard)'\"\n [style.cursor]=\"'move'\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n {{ point.marker.label?.text }}\n </div>\n </svg:foreignObject>\n }\n </svg:g>\n </svg:g>\n }\n }\n }\n }\n}\n", styles: [".draggable-marker{cursor:move}.draggable-path,.selected-path,.selected-path:active{cursor:ew-resize}.line-selected{filter:drop-shadow(0 0 3px var(--series-color))}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"] }]
2450
2452
  }] });
2451
2453
 
2452
2454
  class BarSeriesComponent extends SeriesBaseComponent {
2453
2455
  constructor() {
2454
2456
  super(...arguments);
2455
2457
  this.x1 = computed(() => {
2456
- const x = this.xScales().get(this.series().xAxisIndex)?.scale;
2458
+ const series = this.series();
2459
+ const x = this.xScales().get(series.xAxisIndex)?.scale;
2457
2460
  const range = x.range();
2458
- const domain = this.series().data.map((_) => _.x);
2461
+ const domain = series.data.map((_) => _.x);
2459
2462
  return d3.scaleBand().range([0, range[1]]).domain(domain).padding(0.1);
2460
2463
  }, ...(ngDevMode ? [{ debugName: "x1" }] : /* istanbul ignore next */ []));
2461
2464
  this.barSeriesCount = computed(() => {
2462
- const count = this.config().series.filter((_) => _.type === SeriesType.bar && _.xAxisIndex === this.series().xAxisIndex);
2465
+ const config = this.config();
2466
+ const series = this.series();
2467
+ const count = config.series.filter((_) => _.type === SeriesType.bar && _.xAxisIndex === series.xAxisIndex);
2463
2468
  return count.length;
2464
2469
  }, ...(ngDevMode ? [{ debugName: "barSeriesCount" }] : /* istanbul ignore next */ []));
2465
2470
  this.Math = Math;
@@ -2489,12 +2494,14 @@ class BlockSeriesComponent extends SeriesBaseComponent {
2489
2494
  constructor() {
2490
2495
  super(...arguments);
2491
2496
  this.displayPoints = computed(() => {
2492
- const domain = this.config().inverted ? this.y().domain() : this.x().domain();
2497
+ const config = this.config();
2498
+ const series = this.series();
2499
+ const domain = config.inverted ? this.y().domain() : this.x().domain();
2493
2500
  const [min, max] = domain;
2494
- return this.series().data.filter((point, index, arr) => {
2501
+ return series.data.filter((point, index, arr) => {
2495
2502
  const next = arr[index + 1];
2496
2503
  const secondNext = arr[index + 2];
2497
- if (this.config().inverted) {
2504
+ if (config.inverted) {
2498
2505
  if (point.y1 === null || point.y1 === undefined) {
2499
2506
  point.y1 = next?.y ?? point.y;
2500
2507
  }
@@ -2531,12 +2538,14 @@ class BlockAreaSeriesComponent extends SeriesBaseComponent {
2531
2538
  constructor() {
2532
2539
  super(...arguments);
2533
2540
  this.displayPoints = computed(() => {
2534
- const domain = this.config().inverted ? this.y().domain() : this.x().domain();
2541
+ const config = this.config();
2542
+ const series = this.series();
2543
+ const domain = config.inverted ? this.y().domain() : this.x().domain();
2535
2544
  const [min, max] = domain;
2536
- return this.series().data.filter((point, index, arr) => {
2545
+ return series.data.filter((point, index, arr) => {
2537
2546
  const next = arr[index + 1];
2538
2547
  const secondNext = arr[index + 2];
2539
- if (this.config().inverted) {
2548
+ if (config.inverted) {
2540
2549
  if (point.y1 === null || point.y1 === undefined) {
2541
2550
  point.y1 = next?.y ?? point.y;
2542
2551
  }
@@ -2573,34 +2582,38 @@ class AreaSeriesComponent extends LinearSeriesBaseComponent {
2573
2582
  constructor() {
2574
2583
  super(...arguments);
2575
2584
  this.areaPath = computed(() => {
2576
- if (!this.x() || !this.y()) {
2585
+ const x = this.x();
2586
+ const y = this.y();
2587
+ const config = this.config();
2588
+ const series = this.series();
2589
+ if (!x || !y) {
2577
2590
  return '';
2578
2591
  }
2579
2592
  const area = d3
2580
2593
  .area()
2581
2594
  .defined((point) => point.x !== null && point.y !== null && !isNaN(point.x) && !isNaN(point.y));
2582
- if (this.config().inverted) {
2595
+ if (config.inverted) {
2583
2596
  area
2584
- .x1((_) => (_.x1 !== null && _.x1 !== undefined ? this.x()(_.x1) : this.x()(0)))
2585
- .x0((_) => this.x()(_.x))
2586
- .y((_) => this.y()(_.y));
2597
+ .x1((_) => (_.x1 !== null && _.x1 !== undefined ? x(_.x1) : x(0)))
2598
+ .x0((_) => x(_.x))
2599
+ .y((_) => y(_.y));
2587
2600
  }
2588
2601
  else {
2589
2602
  area
2590
- .y1((_) => (_.y1 !== null && _.y1 !== undefined ? this.y()(_.y1) : this.y()(0)))
2591
- .y0((_) => this.y()(_.y))
2592
- .x((_) => this.x()(_.x));
2593
- }
2594
- const filter = this.defaultClipPointsMapping.get(this.series().clipPointsDirection);
2595
- let filteredData = this.series().data;
2596
- if (this.series().clipPointsDirection === ClipPointsDirection.x) {
2597
- let [min, max] = this.x().domain();
2603
+ .y1((_) => (_.y1 !== null && _.y1 !== undefined ? y(_.y1) : y(0)))
2604
+ .y0((_) => y(_.y))
2605
+ .x((_) => x(_.x));
2606
+ }
2607
+ const filter = this.defaultClipPointsMapping.get(series.clipPointsDirection);
2608
+ let filteredData = series.data;
2609
+ if (series.clipPointsDirection === ClipPointsDirection.x) {
2610
+ let [min, max] = x.domain();
2598
2611
  min = min instanceof Date ? min.getTime() : min;
2599
2612
  max = max instanceof Date ? max.getTime() : max;
2600
2613
  filteredData = filteredData?.filter(filter(min, max));
2601
2614
  }
2602
- if (this.series().clipPointsDirection === ClipPointsDirection.y) {
2603
- let [min, max] = this.y().domain();
2615
+ if (series.clipPointsDirection === ClipPointsDirection.y) {
2616
+ let [min, max] = y.domain();
2604
2617
  min = min instanceof Date ? min.getTime() : min;
2605
2618
  max = max instanceof Date ? max.getTime() : max;
2606
2619
  filteredData = filteredData?.filter(filter(min, max));
@@ -2611,11 +2624,11 @@ class AreaSeriesComponent extends LinearSeriesBaseComponent {
2611
2624
  this.FillDirection = FillDirection;
2612
2625
  }
2613
2626
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AreaSeriesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2614
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AreaSeriesComponent, isStandalone: true, selector: "svg:svg[teta-area-series]", usesInheritance: true, ngImport: i0, template: "@if (series()?.fillType === FillType.gradient) {\n <svg:defs>\n <svg:linearGradient [id]=\"'gradient-fill-' + id\"\n 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}\n<svg:path class=\"area\"\n [attr.d]=\"areaPath()\"\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)\"></svg:path>\n<svg:path class=\"area\"\n fill=\"none\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series().color\"\n [attr.stroke-dasharray]=\"series().style?.strokeDasharray\"\n [attr.stroke-width]=\"series().style?.strokeWidth\"></svg:path>\n@if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle r=\"3\"\n [attr.fill]=\"series().color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"></svg:circle>\n }\n}\n@if (markers(); as draggablePoints) {\n @for (point of draggablePoints; track point) {\n <svg:circle class=\"marker\"\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 ></svg:circle>\n }\n}\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2627
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AreaSeriesComponent, isStandalone: true, selector: "svg:svg[teta-area-series]", usesInheritance: true, ngImport: i0, template: "@if (series()?.fillType === FillType.gradient) {\n <svg:defs>\n <svg:linearGradient [id]=\"'gradient-fill-' + id\"\n 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}\n<svg:path class=\"area\"\n [attr.d]=\"areaPath()\"\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)\"></svg:path>\n<svg:path class=\"area\"\n fill=\"none\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series().color\"\n [attr.stroke-dasharray]=\"series().style?.strokeDasharray\"\n [attr.stroke-width]=\"series().style?.strokeWidth\"></svg:path>\n@if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle r=\"3\"\n [attr.fill]=\"series().color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"></svg:circle>\n }\n}\n@if ({ points: markers(), x: x(), y: y() }; as data) {\n @if (data.x && data.y) {\n @for (point of data.points; track point) {\n <svg:circle class=\"marker\"\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]=\"data.x(point.x)\"\n [attr.cy]=\"data.y(point.y)\"\n ></svg:circle>\n }\n }\n}\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2615
2628
  }
2616
2629
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AreaSeriesComponent, decorators: [{
2617
2630
  type: Component,
2618
- args: [{ selector: 'svg:svg[teta-area-series]', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (series()?.fillType === FillType.gradient) {\n <svg:defs>\n <svg:linearGradient [id]=\"'gradient-fill-' + id\"\n 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}\n<svg:path class=\"area\"\n [attr.d]=\"areaPath()\"\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)\"></svg:path>\n<svg:path class=\"area\"\n fill=\"none\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series().color\"\n [attr.stroke-dasharray]=\"series().style?.strokeDasharray\"\n [attr.stroke-width]=\"series().style?.strokeWidth\"></svg:path>\n@if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle r=\"3\"\n [attr.fill]=\"series().color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"></svg:circle>\n }\n}\n@if (markers(); as draggablePoints) {\n @for (point of draggablePoints; track point) {\n <svg:circle class=\"marker\"\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 ></svg:circle>\n }\n}\n" }]
2631
+ args: [{ selector: 'svg:svg[teta-area-series]', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (series()?.fillType === FillType.gradient) {\n <svg:defs>\n <svg:linearGradient [id]=\"'gradient-fill-' + id\"\n 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}\n<svg:path class=\"area\"\n [attr.d]=\"areaPath()\"\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)\"></svg:path>\n<svg:path class=\"area\"\n fill=\"none\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series().color\"\n [attr.stroke-dasharray]=\"series().style?.strokeDasharray\"\n [attr.stroke-width]=\"series().style?.strokeWidth\"></svg:path>\n@if (transform(); as t) {\n @if (t?.x !== null && t?.x !== undefined && t?.y !== null && t?.y !== undefined) {\n <svg:circle r=\"3\"\n [attr.fill]=\"series().color\"\n [attr.transform]=\"'translate(' + t.x + ', ' + t.y + ')'\"></svg:circle>\n }\n}\n@if ({ points: markers(), x: x(), y: y() }; as data) {\n @if (data.x && data.y) {\n @for (point of data.points; track point) {\n <svg:circle class=\"marker\"\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]=\"data.x(point.x)\"\n [attr.cy]=\"data.y(point.y)\"\n ></svg:circle>\n }\n }\n}\n" }]
2619
2632
  }] });
2620
2633
 
2621
2634
  const defaultSeriesTypeMapping = new Map()
@@ -2664,58 +2677,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2664
2677
  }]
2665
2678
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }] } });
2666
2679
 
2667
- class PlotLine {
2668
- constructor(options) {
2669
- this.id = options?.id;
2670
- this.name = options?.name;
2671
- this.value = options?.value;
2672
- this.label = options?.label;
2673
- this.min = options?.min;
2674
- this.max = options?.max;
2675
- this.draggable = options?.draggable;
2676
- this.style = options?.style;
2677
- }
2678
- }
2679
-
2680
2680
  class PlotlineComponent {
2681
- constructor(cdr, zoomService, scaleService, chartService, element) {
2682
- this.cdr = cdr;
2683
- this.zoomService = zoomService;
2684
- this.scaleService = scaleService;
2685
- this.chartService = chartService;
2686
- this.element = element;
2681
+ constructor() {
2682
+ this.chartService = inject(ChartService);
2683
+ this.element = inject(ElementRef);
2684
+ this.plotLine = input(...(ngDevMode ? [undefined, { debugName: "plotLine" }] : /* istanbul ignore next */ []));
2685
+ this.size = input(...(ngDevMode ? [undefined, { debugName: "size" }] : /* istanbul ignore next */ []));
2686
+ this.axis = input(...(ngDevMode ? [undefined, { debugName: "axis" }] : /* istanbul ignore next */ []));
2687
+ this.scale = input(...(ngDevMode ? [undefined, { debugName: "scale" }] : /* istanbul ignore next */ []));
2687
2688
  this.orientation = AxisOrientation;
2689
+ this.currentValue = signal(0, ...(ngDevMode ? [{ debugName: "currentValue" }] : /* istanbul ignore next */ []));
2690
+ this.value = computed(() => {
2691
+ const scale = this.scale();
2692
+ if (!scale) {
2693
+ return 0;
2694
+ }
2695
+ return scale(this.currentValue());
2696
+ }, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2697
+ this.height = computed(() => {
2698
+ return this.size()?.height ?? 0;
2699
+ }, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2700
+ this.width = computed(() => {
2701
+ return this.size()?.width ?? 0;
2702
+ }, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2703
+ effect(() => {
2704
+ if (this.plotLine()) {
2705
+ this.currentValue.set(this.plotLine().value);
2706
+ }
2707
+ });
2688
2708
  }
2689
- ngOnInit() {
2690
- this._domain = this.scale.domain();
2709
+ ngAfterViewInit() {
2691
2710
  const plotlineElement = d3.select(this.element.nativeElement).select('.plotline');
2692
2711
  const grabElement = d3.select(this.element.nativeElement).selectAll('.grabber');
2693
2712
  this.dragElements = d3.drag().subject(() => {
2694
- if (this.axis.orientation === AxisOrientation.y) {
2713
+ if (this.axis().orientation === AxisOrientation.y) {
2695
2714
  return { y: plotlineElement.attr('y1') };
2696
2715
  }
2697
- if (this.axis.orientation === AxisOrientation.x) {
2716
+ if (this.axis().orientation === AxisOrientation.x) {
2698
2717
  return { x: plotlineElement.attr('x1') };
2699
2718
  }
2700
2719
  return null;
2701
2720
  });
2702
2721
  const drag = this.dragElements.on('start drag end', (event, d) => {
2703
- d.value = this.scale.invert(event[AxisOrientation[this.axis.orientation]]);
2722
+ d.value = this.scale().invert(event[AxisOrientation[this.axis().orientation]]);
2704
2723
  if (d.max !== null && d.max !== undefined && d.value >= d.max) {
2705
2724
  d.value = d.max;
2706
2725
  }
2707
2726
  if (d.min !== null && d.min !== undefined && d.value <= d.min) {
2708
2727
  d.value = d.min;
2709
2728
  }
2729
+ this.currentValue.set(d.value);
2710
2730
  this.emit({
2711
2731
  event,
2712
2732
  target: d,
2713
2733
  });
2714
- this.cdr.detectChanges();
2715
2734
  });
2716
- plotlineElement.datum(this.plotLine);
2717
- grabElement.datum(this.plotLine);
2718
- if (this.plotLine.draggable) {
2735
+ plotlineElement.datum(this.plotLine());
2736
+ grabElement.datum(this.plotLine());
2737
+ if (this.plotLine().draggable) {
2719
2738
  grabElement.call(drag);
2720
2739
  }
2721
2740
  }
@@ -2725,30 +2744,13 @@ class PlotlineComponent {
2725
2744
  emit(event) {
2726
2745
  this.chartService.emitPlotLine(event);
2727
2746
  }
2728
- get value() {
2729
- return this.scale(this.plotLine.value);
2730
- }
2731
- get height() {
2732
- return this.size.height;
2733
- }
2734
- get width() {
2735
- return this.size.width;
2736
- }
2737
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PlotlineComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: ZoomService }, { token: ScaleService }, { token: ChartService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
2738
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PlotlineComponent, isStandalone: true, selector: "[teta-plot-line]", inputs: { plotLine: "plotLine", size: "size", axis: "axis", scale: "scale" }, ngImport: i0, template: "<svg:line\n class=\"plotline\"\n [attr.stroke]=\"plotLine.style?.stroke || 'red'\"\n [attr.stroke-width]=\"plotLine.style?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotLine.style?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? value : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? value : width\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : value\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : value\"\n></svg:line>\n\n@if (axis.orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"label font-title-2 fill-text-70\"\n [attr.x]=\"value\"\n dy=\"-2em\"\n [attr.transform]=\"'rotate(-90, ' + value + ',' + height / 2 + ')'\"\n [attr.y]=\"height / 2\"\n >\n {{ plotLine.label }}\n </svg:text>\n}\n@if (axis.orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-title-2 fill-text-70\"\n dominant-baseline=\"central\"\n [attr.x]=\"value\"\n [attr.y]=\"width / 2\"\n >\n {{ plotLine.label }}\n </svg:text>\n}\n<svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [attr.stroke]=\"'red'\"\n [attr.stroke-width]=\"8\"\n opacity=\"0\"\n [attr.x1]=\"axis.orientation === orientation.x ? value : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? value : width\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : value\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : value\"\n></svg:line>\n", styles: [":host .x-grabber{cursor:col-resize}:host .y-grabber{cursor:row-resize}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2747
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PlotlineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2748
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PlotlineComponent, isStandalone: true, selector: "[teta-plot-line]", inputs: { plotLine: { classPropertyName: "plotLine", publicName: "plotLine", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<svg:line\n class=\"plotline\"\n [attr.stroke]=\"plotLine().style?.stroke || 'red'\"\n [attr.stroke-width]=\"plotLine().style?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotLine().style?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? value() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? value() : width()\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : value()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : value()\"\n></svg:line>\n\n@if (axis().orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"label font-title-2 fill-text-70\"\n [attr.x]=\"value()\"\n dy=\"-2em\"\n [attr.transform]=\"'rotate(-90, ' + value() + ',' + height() / 2 + ')'\"\n [attr.y]=\"height() / 2\"\n >\n {{ plotLine().label }}\n </svg:text>\n}\n@if (axis().orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-title-2 fill-text-70\"\n dominant-baseline=\"central\"\n [attr.x]=\"value()\"\n [attr.y]=\"width() / 2\"\n >\n {{ plotLine().label }}\n </svg:text>\n}\n<svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [attr.stroke]=\"'red'\"\n [attr.stroke-width]=\"8\"\n opacity=\"0\"\n [attr.x1]=\"axis().orientation === orientation.x ? value() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? value() : width()\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : value()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : value()\"\n></svg:line>\n", styles: [":host .x-grabber{cursor:col-resize}:host .y-grabber{cursor:row-resize}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2739
2749
  }
2740
2750
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PlotlineComponent, decorators: [{
2741
2751
  type: Component,
2742
- args: [{ selector: '[teta-plot-line]', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:line\n class=\"plotline\"\n [attr.stroke]=\"plotLine.style?.stroke || 'red'\"\n [attr.stroke-width]=\"plotLine.style?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotLine.style?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? value : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? value : width\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : value\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : value\"\n></svg:line>\n\n@if (axis.orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"label font-title-2 fill-text-70\"\n [attr.x]=\"value\"\n dy=\"-2em\"\n [attr.transform]=\"'rotate(-90, ' + value + ',' + height / 2 + ')'\"\n [attr.y]=\"height / 2\"\n >\n {{ plotLine.label }}\n </svg:text>\n}\n@if (axis.orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-title-2 fill-text-70\"\n dominant-baseline=\"central\"\n [attr.x]=\"value\"\n [attr.y]=\"width / 2\"\n >\n {{ plotLine.label }}\n </svg:text>\n}\n<svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [attr.stroke]=\"'red'\"\n [attr.stroke-width]=\"8\"\n opacity=\"0\"\n [attr.x1]=\"axis.orientation === orientation.x ? value : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? value : width\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : value\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : value\"\n></svg:line>\n", styles: [":host .x-grabber{cursor:col-resize}:host .y-grabber{cursor:row-resize}\n"] }]
2743
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: ZoomService }, { type: ScaleService }, { type: ChartService }, { type: i0.ElementRef }], propDecorators: { plotLine: [{
2744
- type: Input
2745
- }], size: [{
2746
- type: Input
2747
- }], axis: [{
2748
- type: Input
2749
- }], scale: [{
2750
- type: Input
2751
- }] } });
2752
+ args: [{ selector: '[teta-plot-line]', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:line\n class=\"plotline\"\n [attr.stroke]=\"plotLine().style?.stroke || 'red'\"\n [attr.stroke-width]=\"plotLine().style?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotLine().style?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? value() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? value() : width()\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : value()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : value()\"\n></svg:line>\n\n@if (axis().orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"label font-title-2 fill-text-70\"\n [attr.x]=\"value()\"\n dy=\"-2em\"\n [attr.transform]=\"'rotate(-90, ' + value() + ',' + height() / 2 + ')'\"\n [attr.y]=\"height() / 2\"\n >\n {{ plotLine().label }}\n </svg:text>\n}\n@if (axis().orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-title-2 fill-text-70\"\n dominant-baseline=\"central\"\n [attr.x]=\"value()\"\n [attr.y]=\"width() / 2\"\n >\n {{ plotLine().label }}\n </svg:text>\n}\n<svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [attr.stroke]=\"'red'\"\n [attr.stroke-width]=\"8\"\n opacity=\"0\"\n [attr.x1]=\"axis().orientation === orientation.x ? value() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? value() : width()\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : value()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : value()\"\n></svg:line>\n", styles: [":host .x-grabber{cursor:col-resize}:host .y-grabber{cursor:row-resize}\n"] }]
2753
+ }], ctorParameters: () => [], propDecorators: { plotLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "plotLine", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], axis: [{ type: i0.Input, args: [{ isSignal: true, alias: "axis", required: false }] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }] } });
2752
2754
 
2753
2755
  class AnnotationComponent {
2754
2756
  set annotation(annotation) {
@@ -2765,10 +2767,10 @@ class AnnotationComponent {
2765
2767
  get node() {
2766
2768
  return this._node;
2767
2769
  }
2768
- constructor(scaleService, cdr, chartService) {
2769
- this.scaleService = scaleService;
2770
- this.cdr = cdr;
2771
- this.chartService = chartService;
2770
+ constructor() {
2771
+ this.scaleService = inject(ScaleService);
2772
+ this.cdr = inject(ChangeDetectorRef);
2773
+ this.chartService = inject(ChartService);
2772
2774
  this.x = this.scaleService.scales.pipe(map((_) => _.x.get(this.annotation.xAxisIndex ?? 0)?.scale));
2773
2775
  this.y = this.scaleService.scales.pipe(map((_) => _.y.get(this.annotation.yAxisIndex ?? 0)?.scale));
2774
2776
  this.drag = d3.drag();
@@ -2789,6 +2791,9 @@ class AnnotationComponent {
2789
2791
  this.drag.on('drag end', null);
2790
2792
  }
2791
2793
  init() {
2794
+ if (!this.node) {
2795
+ return;
2796
+ }
2792
2797
  d3.select(this.node.nativeElement).datum(this.annotation);
2793
2798
  const offsetPx = 10;
2794
2799
  const nodeRect = this.node.nativeElement.getBoundingClientRect();
@@ -2821,13 +2826,13 @@ class AnnotationComponent {
2821
2826
  d3.select(this.node.nativeElement).call(this.drag);
2822
2827
  }
2823
2828
  }
2824
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AnnotationComponent, deps: [{ token: ScaleService }, { token: i0.ChangeDetectorRef }, { token: ChartService }], target: i0.ɵɵFactoryTarget.Component }); }
2825
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AnnotationComponent, isStandalone: true, selector: "[teta-annotation]", inputs: { visibleRect: "visibleRect", annotation: "annotation" }, host: { listeners: { "click": "click($event)", "contextmenu": "contextMenu($event)" } }, viewQueries: [{ propertyName: "node", first: true, predicate: ["annotationNode"], descendants: true }], ngImport: i0, template: "@if ({ x: x | async, y: y | async }; as data) {\n @if (data.x && data.y) {\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 ></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 >\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-global-bgmain)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n [className]=\"'padding-h-2 ' + (annotation.className ?? '')\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n @if (annotation.template) {\n <ng-container *ngTemplateOutlet=\"annotation.template; context: { $implicit: annotation }\"></ng-container>\n } @else {\n {{ annotation.note?.label }}\n }\n </div>\n </svg:foreignObject>\n }\n}\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2829
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AnnotationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2830
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AnnotationComponent, isStandalone: true, selector: "[teta-annotation]", inputs: { visibleRect: "visibleRect", annotation: "annotation" }, host: { listeners: { "click": "click($event)", "contextmenu": "contextMenu($event)" } }, viewQueries: [{ propertyName: "node", first: true, predicate: ["annotationNode"], descendants: true }], ngImport: i0, template: "@if ({ x: x | async, y: y | async }; as data) {\n @if (data.x && data.y && annotation.point.x !== null && annotation.point.x !== undefined && annotation.point.y !== null && annotation.point.y !== undefined) {\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 ></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 >\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-global-bgmain)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n [className]=\"'padding-h-2 ' + (annotation.className ?? '')\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n @if (annotation.template) {\n <ng-container *ngTemplateOutlet=\"annotation.template; context: { $implicit: annotation }\"></ng-container>\n } @else {\n {{ annotation.note?.label }}\n }\n </div>\n </svg:foreignObject>\n }\n}\n", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2826
2831
  }
2827
2832
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AnnotationComponent, decorators: [{
2828
2833
  type: Component,
2829
- args: [{ selector: '[teta-annotation]', imports: [NgTemplateOutlet, AsyncPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if ({ x: x | async, y: y | async }; as data) {\n @if (data.x && data.y) {\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 ></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 >\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-global-bgmain)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n [className]=\"'padding-h-2 ' + (annotation.className ?? '')\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n @if (annotation.template) {\n <ng-container *ngTemplateOutlet=\"annotation.template; context: { $implicit: annotation }\"></ng-container>\n } @else {\n {{ annotation.note?.label }}\n }\n </div>\n </svg:foreignObject>\n }\n}\n" }]
2830
- }], ctorParameters: () => [{ type: ScaleService }, { type: i0.ChangeDetectorRef }, { type: ChartService }], propDecorators: { visibleRect: [{
2834
+ args: [{ selector: '[teta-annotation]', imports: [NgTemplateOutlet, AsyncPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if ({ x: x | async, y: y | async }; as data) {\n @if (data.x && data.y && annotation.point.x !== null && annotation.point.x !== undefined && annotation.point.y !== null && annotation.point.y !== undefined) {\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 ></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 >\n <div\n #annotationNode\n [style.background-color]=\"annotation.style?.fill ?? 'var(--color-global-bgmain)'\"\n [style.cursor]=\"annotation?.draggable ? 'move' : 'default'\"\n [className]=\"'padding-h-2 ' + (annotation.className ?? '')\"\n style=\"border-radius: 2px; display: inline-block\"\n >\n @if (annotation.template) {\n <ng-container *ngTemplateOutlet=\"annotation.template; context: { $implicit: annotation }\"></ng-container>\n } @else {\n {{ annotation.note?.label }}\n }\n </div>\n </svg:foreignObject>\n }\n}\n" }]
2835
+ }], ctorParameters: () => [], propDecorators: { visibleRect: [{
2831
2836
  type: Input
2832
2837
  }], annotation: [{
2833
2838
  type: Input
@@ -3483,12 +3488,26 @@ class PlotBand {
3483
3488
  }
3484
3489
  }
3485
3490
 
3491
+ class PlotLine {
3492
+ constructor(options) {
3493
+ this.id = options?.id;
3494
+ this.name = options?.name;
3495
+ this.value = options?.value;
3496
+ this.label = options?.label;
3497
+ this.min = options?.min;
3498
+ this.max = options?.max;
3499
+ this.draggable = options?.draggable;
3500
+ this.style = options?.style;
3501
+ }
3502
+ }
3503
+
3486
3504
  class BlockHorizontalSeriesComponent extends SeriesBaseComponent {
3487
3505
  constructor() {
3488
3506
  super(...arguments);
3489
3507
  this.displayPoints = computed(() => {
3508
+ const x = this.x();
3509
+ const [min, max] = x.domain();
3490
3510
  return this.series().data.filter((point, index, arr) => {
3491
- const [min, max] = this.x().domain();
3492
3511
  return ((point.x >= min || point.x1 >= min || arr[index + 1]?.x >= min || arr[index + 1]?.x1 >= min) &&
3493
3512
  (point.x <= max || point.x1 <= max || arr[index - 1]?.x <= max || arr[index - 1]?.x1 <= max));
3494
3513
  });