@tetacom/svg-charts 1.7.4 → 1.7.7

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, input, inject, ChangeDetectorRef, ElementRef, computed, Component, ChangeDetectionStrategy, Input, ViewChild, Directive, HostBinding, HostListener, signal, EventEmitter, Output, ViewContainerRef, effect } from '@angular/core';
2
+ import { Injectable, input, inject, ChangeDetectorRef, ElementRef, computed, Component, ChangeDetectionStrategy, Input, ViewChild, Directive, HostBinding, HostListener, signal, effect, EventEmitter, Output, ViewContainerRef } from '@angular/core';
3
3
  import { ReplaySubject, filter, BehaviorSubject, Subject, of, shareReplay, withLatestFrom, map, merge, lastValueFrom, take, combineLatest, tap, takeWhile, observeOn, animationFrameScheduler } from 'rxjs';
4
4
  import * as d3 from 'd3';
5
5
  import { zoomIdentity } from 'd3';
@@ -1195,45 +1195,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1195
1195
  }] } });
1196
1196
 
1197
1197
  class XAxisComponent {
1198
- constructor(scaleService, _svc) {
1199
- this.scaleService = scaleService;
1200
- this._svc = _svc;
1201
- this.update$ = new BehaviorSubject(null);
1202
- this._alive = true;
1203
- this.x = this.scaleService.scales.pipe(map((_) => {
1204
- return _.x.get(this.axis.index)?.scale;
1205
- }));
1206
- this.ticks = combineLatest([this.x, this.update$]).pipe(withLatestFrom(this._svc.size), map((_) => {
1207
- const [[x], size] = _;
1208
- const tickSize = x
1198
+ constructor() {
1199
+ this.scaleService = inject(ScaleService);
1200
+ this.xScales = toSignal(this.scaleService.scales.pipe(map((_) => _.x)));
1201
+ this.axis = input();
1202
+ this.size = input();
1203
+ this.x = computed(() => {
1204
+ return this.xScales().get(this.axis().index)?.scale;
1205
+ });
1206
+ this.ticks = computed(() => {
1207
+ const tickSize = this.x()
1209
1208
  .ticks()
1210
- .map((_) => getTextWidth(this.axis.options.tickFormat ? this.axis.options.tickFormat(_) : this.axis.defaultFormatter()(_), 0.45, 11));
1211
- return x.ticks(size.width / parseInt(d3.max(tickSize), 10) / 5);
1212
- }));
1213
- }
1214
- getLabelTransform() {
1215
- return `translate(${this.size.width / 2}, ${this.axis.options.opposite ? -32 : 32})`;
1216
- }
1217
- ngOnInit() { }
1218
- ngOnDestroy() {
1219
- this._alive = false;
1220
- }
1221
- ngOnChanges(changes) {
1222
- if (changes.hasOwnProperty('axis')) {
1223
- this.update$.next();
1224
- }
1209
+ .map((_) => getTextWidth(this.axis().options.tickFormat ? this.axis().options.tickFormat(_) : this.axis().defaultFormatter()(_), 0.45, 11));
1210
+ return this.x().ticks(this.size().width / parseInt(d3.max(tickSize), 10) / 5);
1211
+ });
1212
+ this.getLabelTransform = computed(() => {
1213
+ return `translate(${this.size().width / 2}, ${this.axis().options.opposite ? -32 : 32})`;
1214
+ });
1225
1215
  }
1226
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: XAxisComponent, deps: [{ token: ScaleService }, { token: ChartService }], target: i0.ɵɵFactoryTarget.Component }); }
1227
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: XAxisComponent, isStandalone: true, selector: "[teta-x-axis]", inputs: { axis: "axis", size: "size" }, usesOnChanges: true, ngImport: i0, template: "@if ({ x: x | async, ticks: ticks | async }; as data) {\n @for (tick of data.ticks; track $index) {\n <svg:g text-anchor=\"middle\" [attr.transform]=\"'translate(' + data.x(tick) + ', 0)'\">\n <text\n fill=\"var(--color-text-70)\"\n [attr.dy]=\"axis.options.opposite ? '-0.71em' : '0.71em'\"\n [attr.y]=\"axis.options.opposite ? 0 : 9\"\n >\n {{ this.axis.options.tickFormat ? this.axis.options.tickFormat(tick) : this.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.y2]=\"axis.options.opposite ? -6 : 6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text fill=\"var(--color-text-70)\" text-anchor=\"middle\" dominant-baseline=\"middle\">\n {{ axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host .tick{stroke:var(--color-text-20)}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1216
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: XAxisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1217
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: XAxisComponent, isStandalone: true, selector: "[teta-x-axis]", inputs: { axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if ({\n x: x(),\n ticks: ticks(),\n axis: axis()\n}; as data) {\n @for (tick of data.ticks; track $index) {\n <svg:g text-anchor=\"middle\" [attr.transform]=\"'translate(' + data.x(tick) + ', 0)'\">\n <text\n fill=\"var(--color-text-70)\"\n [attr.dy]=\"data.axis.options.opposite ? '-0.71em' : '0.71em'\"\n [attr.y]=\"data.axis.options.opposite ? 0 : 9\"\n >\n {{ data.axis.options.tickFormat ? data.axis.options.tickFormat(tick) : data.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.y2]=\"data.axis.options.opposite ? -6 : 6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text fill=\"var(--color-text-70)\" text-anchor=\"middle\" dominant-baseline=\"middle\">\n {{ data.axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host .tick{stroke:var(--color-text-20)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1228
1218
  }
1229
1219
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: XAxisComponent, decorators: [{
1230
1220
  type: Component,
1231
- args: [{ selector: '[teta-x-axis]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe], template: "@if ({ x: x | async, ticks: ticks | async }; as data) {\n @for (tick of data.ticks; track $index) {\n <svg:g text-anchor=\"middle\" [attr.transform]=\"'translate(' + data.x(tick) + ', 0)'\">\n <text\n fill=\"var(--color-text-70)\"\n [attr.dy]=\"axis.options.opposite ? '-0.71em' : '0.71em'\"\n [attr.y]=\"axis.options.opposite ? 0 : 9\"\n >\n {{ this.axis.options.tickFormat ? this.axis.options.tickFormat(tick) : this.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.y2]=\"axis.options.opposite ? -6 : 6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text fill=\"var(--color-text-70)\" text-anchor=\"middle\" dominant-baseline=\"middle\">\n {{ axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host .tick{stroke:var(--color-text-20)}\n"] }]
1232
- }], ctorParameters: () => [{ type: ScaleService }, { type: ChartService }], propDecorators: { axis: [{
1233
- type: Input
1234
- }], size: [{
1235
- type: Input
1236
- }] } });
1221
+ args: [{ selector: '[teta-x-axis]', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if ({\n x: x(),\n ticks: ticks(),\n axis: axis()\n}; as data) {\n @for (tick of data.ticks; track $index) {\n <svg:g text-anchor=\"middle\" [attr.transform]=\"'translate(' + data.x(tick) + ', 0)'\">\n <text\n fill=\"var(--color-text-70)\"\n [attr.dy]=\"data.axis.options.opposite ? '-0.71em' : '0.71em'\"\n [attr.y]=\"data.axis.options.opposite ? 0 : 9\"\n >\n {{ data.axis.options.tickFormat ? data.axis.options.tickFormat(tick) : data.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.y2]=\"data.axis.options.opposite ? -6 : 6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text fill=\"var(--color-text-70)\" text-anchor=\"middle\" dominant-baseline=\"middle\">\n {{ data.axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host .tick{stroke:var(--color-text-20)}\n"] }]
1222
+ }] });
1237
1223
 
1238
1224
  class ZoomableDirective {
1239
1225
  mouseenter() {
@@ -1467,93 +1453,86 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1467
1453
  }] } });
1468
1454
 
1469
1455
  class YAxisComponent {
1470
- constructor(scaleService) {
1471
- this.scaleService = scaleService;
1472
- this._alive = true;
1473
- this.y = this.scaleService.scales.pipe(map((_) => {
1474
- return _.y.get(this.axis.index)?.scale;
1475
- }));
1476
- }
1477
- ngOnInit() { }
1478
- ngOnDestroy() {
1479
- this._alive = false;
1480
- }
1481
- ngAfterViewInit() { }
1482
- getLabelTransform() {
1483
- return `translate(${this.axis.options.opposite ? this.axis.selfSize : -this.axis.selfSize}, ${this.size.height / 2}) rotate(-90)`;
1456
+ constructor() {
1457
+ this.scaleService = inject(ScaleService);
1458
+ this.yScales = toSignal(this.scaleService.scales.pipe(map((_) => _.y)));
1459
+ this.axis = input();
1460
+ this.size = input();
1461
+ this.y = computed(() => {
1462
+ return this.yScales().get(this.axis().index)?.scale;
1463
+ });
1464
+ this.getLabelTransform = computed(() => {
1465
+ return `translate(${this.axis().options.opposite ? this.axis().selfSize : -this.axis().selfSize}, ${this.size().height / 2}) rotate(-90)`;
1466
+ });
1484
1467
  }
1485
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: YAxisComponent, deps: [{ token: ScaleService }], target: i0.ɵɵFactoryTarget.Component }); }
1486
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: YAxisComponent, isStandalone: true, selector: "[teta-y-axis]", inputs: { axis: "axis", size: "size" }, ngImport: i0, template: "@if (y | async; as scale) {\n @for (tick of scale.ticks(); track $index) {\n <svg:g\n [attr.text-anchor]=\"axis.options.opposite ? 'start' : 'end'\"\n [attr.transform]=\"'translate(0, ' + scale(tick) + ')'\"\n >\n <text fill=\"var(--color-text-70)\" dy=\"0.32em\" [attr.x]=\"axis.options.opposite ? 10 : -9\">\n {{ this.axis.options.tickFormat ? this.axis.options.tickFormat(tick) : this.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.x2]=\"axis.options.opposite ? 6 : -6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text\n [attr.dy]=\"axis.options.opposite ? '-4px' : '4px'\"\n text-anchor=\"middle\"\n [attr.dominant-baseline]=\"axis.options.opposite ? 'auto' : 'hanging'\"\n >\n {{ axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host{shape-rendering:crispEdges}:host .label-axis{fill:var(--color-text-70)}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1468
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: YAxisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1469
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: YAxisComponent, isStandalone: true, selector: "[teta-y-axis]", inputs: { axis: { classPropertyName: "axis", publicName: "axis", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if ({\n y: y(),\n axis: axis()\n}; as data) {\n @for (tick of data.y.ticks(); track $index) {\n <svg:g\n [attr.text-anchor]=\"data.axis.options.opposite ? 'start' : 'end'\"\n [attr.transform]=\"'translate(0, ' + data.y(tick) + ')'\"\n >\n <text fill=\"var(--color-text-70)\" dy=\"0.32em\" [attr.x]=\"data.axis.options.opposite ? 10 : -9\">\n {{ data.axis.options.tickFormat ? data.axis.options.tickFormat(tick) : data.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.x2]=\"data.axis.options.opposite ? 6 : -6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text\n [attr.dy]=\"data.axis.options.opposite ? '-4px' : '4px'\"\n text-anchor=\"middle\"\n [attr.dominant-baseline]=\"data.axis.options.opposite ? 'auto' : 'hanging'\"\n >\n {{ data.axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host{shape-rendering:crispEdges}:host .label-axis{fill:var(--color-text-70)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1487
1470
  }
1488
1471
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: YAxisComponent, decorators: [{
1489
1472
  type: Component,
1490
- args: [{ selector: '[teta-y-axis]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe], template: "@if (y | async; as scale) {\n @for (tick of scale.ticks(); track $index) {\n <svg:g\n [attr.text-anchor]=\"axis.options.opposite ? 'start' : 'end'\"\n [attr.transform]=\"'translate(0, ' + scale(tick) + ')'\"\n >\n <text fill=\"var(--color-text-70)\" dy=\"0.32em\" [attr.x]=\"axis.options.opposite ? 10 : -9\">\n {{ this.axis.options.tickFormat ? this.axis.options.tickFormat(tick) : this.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.x2]=\"axis.options.opposite ? 6 : -6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text\n [attr.dy]=\"axis.options.opposite ? '-4px' : '4px'\"\n text-anchor=\"middle\"\n [attr.dominant-baseline]=\"axis.options.opposite ? 'auto' : 'hanging'\"\n >\n {{ axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host{shape-rendering:crispEdges}:host .label-axis{fill:var(--color-text-70)}\n"] }]
1491
- }], ctorParameters: () => [{ type: ScaleService }], propDecorators: { axis: [{
1492
- type: Input
1493
- }], size: [{
1494
- type: Input
1495
- }] } });
1496
-
1497
- class PlotBand {
1498
- constructor(options) {
1499
- this.order = 0;
1500
- this.id = options?.id;
1501
- this.name = options?.name;
1502
- this.from = options?.from;
1503
- this.to = options?.to;
1504
- this.label = options?.label;
1505
- this.showGrabbers = options?.showGrabbers != null ? options.showGrabbers : true;
1506
- this.draggable = options?.draggable != null ? options?.draggable : false;
1507
- this.resizable = options?.resizable != null ? options?.resizable : true;
1508
- this.min = options?.min;
1509
- this.max = options?.max;
1510
- this.order = options?.order ?? 0;
1511
- this.style = options?.style;
1512
- }
1513
- }
1473
+ args: [{ selector: '[teta-y-axis]', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if ({\n y: y(),\n axis: axis()\n}; as data) {\n @for (tick of data.y.ticks(); track $index) {\n <svg:g\n [attr.text-anchor]=\"data.axis.options.opposite ? 'start' : 'end'\"\n [attr.transform]=\"'translate(0, ' + data.y(tick) + ')'\"\n >\n <text fill=\"var(--color-text-70)\" dy=\"0.32em\" [attr.x]=\"data.axis.options.opposite ? 10 : -9\">\n {{ data.axis.options.tickFormat ? data.axis.options.tickFormat(tick) : data.axis.defaultFormatter()(tick) }}\n </text>\n <line stroke=\"var(--color-text-30)\" [attr.x2]=\"data.axis.options.opposite ? 6 : -6\"></line>\n </svg:g>\n }\n <svg:g class=\"label-axis font-caption\" [attr.transform]=\"getLabelTransform()\">\n <text\n [attr.dy]=\"data.axis.options.opposite ? '-4px' : '4px'\"\n text-anchor=\"middle\"\n [attr.dominant-baseline]=\"data.axis.options.opposite ? 'auto' : 'hanging'\"\n >\n {{ data.axis.options.title }}\n </text>\n </svg:g>\n}\n", styles: [":host{shape-rendering:crispEdges}:host .label-axis{fill:var(--color-text-70)}\n"] }]
1474
+ }] });
1514
1475
 
1515
1476
  class PlotBandComponent {
1516
1477
  click(event) {
1517
1478
  this.emit({
1518
- target: this.plotBand,
1479
+ target: this.plotBand(),
1519
1480
  event,
1520
1481
  });
1521
1482
  }
1522
1483
  contextMenu(event) {
1523
1484
  this.emit({
1524
- target: this.plotBand,
1485
+ target: this.plotBand(),
1525
1486
  event,
1526
1487
  });
1527
1488
  }
1528
- get height() {
1529
- return this.size.height;
1530
- }
1531
- get width() {
1532
- return this.size.width;
1533
- }
1534
- get from() {
1535
- return this.scale(this.plotBand.from);
1536
- }
1537
- get to() {
1538
- return this.scale(this.plotBand.to);
1539
- }
1540
- get bandSize() {
1541
- return Math.abs(this.scale(this.plotBand.to) - this.scale(this.plotBand.from));
1542
- }
1543
- constructor(chartService, cdr, element) {
1489
+ constructor(chartService, element) {
1544
1490
  this.chartService = chartService;
1545
- this.cdr = cdr;
1546
1491
  this.element = element;
1492
+ this.plotBand = input();
1493
+ this.axis = input();
1494
+ this.scale = input();
1495
+ this.size = input();
1496
+ this.fromTo = signal(null);
1547
1497
  this.orientation = AxisOrientation;
1548
- this.getTextPosition = () => {
1549
- let [min, max] = this.scale.domain();
1498
+ this.height = computed(() => {
1499
+ return this.size().height;
1500
+ });
1501
+ this.width = computed(() => {
1502
+ return this.size().width;
1503
+ });
1504
+ this.from = computed(() => {
1505
+ return this.scale()(this.fromTo().from);
1506
+ });
1507
+ this.to = computed(() => {
1508
+ return this.scale()(this.fromTo().to);
1509
+ });
1510
+ this.bandSize = computed(() => {
1511
+ return Math.abs(this.scale()(this.fromTo().to) - this.scale()(this.fromTo().from));
1512
+ });
1513
+ this.textPosition = computed(() => {
1514
+ let [min, max] = this.scale().domain();
1550
1515
  min = min instanceof Date ? min.getTime() : min;
1551
1516
  max = max instanceof Date ? max.getTime() : max;
1552
- const from = this.plotBand.from instanceof Date ? this.plotBand.from.getTime() : this.plotBand.from;
1553
- const to = this.plotBand.to instanceof Date ? this.plotBand.to.getTime() : this.plotBand.to;
1517
+ const from = this.fromTo().from instanceof Date ? this.fromTo().from.getTime() : this.fromTo().from;
1518
+ const to = this.fromTo().to instanceof Date ? this.fromTo().to.getTime() : this.fromTo().to;
1554
1519
  const position = ((from <= min ? min : from) + (to >= max ? max : to)) / 2;
1555
- return this.scale(position);
1556
- };
1520
+ return this.scale()(position);
1521
+ });
1522
+ this.fill = computed(() => {
1523
+ if (this.plotBand().style?.plotBand?.patternImage) {
1524
+ return `url(#${this.plotBand().style.plotBand?.patternImage})`;
1525
+ }
1526
+ return this.plotBand().style.plotBand?.fill;
1527
+ });
1528
+ effect(() => {
1529
+ if (this.plotBand()) {
1530
+ this.fromTo.set({
1531
+ from: this.plotBand().from,
1532
+ to: this.plotBand().to,
1533
+ });
1534
+ }
1535
+ });
1557
1536
  }
1558
1537
  emit(event) {
1559
1538
  this.chartService.emitPlotBand(event);
@@ -1562,23 +1541,42 @@ class PlotBandComponent {
1562
1541
  const plotbandElement = d3.select(this.element.nativeElement).select('.plotband');
1563
1542
  const grabElements = d3.select(this.element.nativeElement).selectAll('.grabber');
1564
1543
  this.dragElements = d3.drag().subject(() => {
1565
- if (this.axis.orientation === AxisOrientation.x) {
1544
+ if (this.axis().orientation === AxisOrientation.x) {
1566
1545
  return { x: plotbandElement.attr('x') };
1567
1546
  }
1568
- if (this.axis.orientation === AxisOrientation.y) {
1547
+ if (this.axis().orientation === AxisOrientation.y) {
1569
1548
  return { y: plotbandElement.attr('y') };
1570
1549
  }
1571
1550
  return null;
1572
1551
  });
1573
1552
  const drag = this.dragElements.on('start drag end', (event, d) => {
1574
- const bandSize = parseFloat(plotbandElement.attr(this.axis.orientation === AxisOrientation.x ? 'width' : 'height'));
1575
- d.from = this.scale.invert(event[AxisOrientation[this.axis.orientation]]);
1576
- d.to = this.scale.invert(event[AxisOrientation[this.axis.orientation]] + bandSize);
1553
+ const bandSize = parseFloat(plotbandElement.attr(this.axis().orientation === AxisOrientation.x ? 'width' : 'height'));
1554
+ const from = this.scale().invert(event[AxisOrientation[this.axis().orientation]]);
1555
+ const to = this.scale().invert(event[AxisOrientation[this.axis().orientation]] + bandSize);
1556
+ // const min = Math.min(...this.scale().domain());
1557
+ // const max = Math.max(...this.scale().domain());
1558
+ //
1559
+ // const minValue = d.min ?? min;
1560
+ // const maxValue = d.max ?? max;
1561
+ //
1562
+ // d.from = from;
1563
+ // d.to = to;
1564
+ // if (d.from < minValue) {
1565
+ // d.from = minValue;
1566
+ // }
1567
+ // if (d.to > maxValue) {
1568
+ // d.to = maxValue;
1569
+ // }
1570
+ d.from = from;
1571
+ d.to = to;
1572
+ this.fromTo.set({
1573
+ from: d.from,
1574
+ to: d.to,
1575
+ });
1577
1576
  this.emit({
1578
1577
  event,
1579
1578
  target: d,
1580
1579
  });
1581
- this.cdr.detectChanges();
1582
1580
  });
1583
1581
  let grabberKey;
1584
1582
  this.resizeElements = d3.drag();
@@ -1587,11 +1585,11 @@ class PlotBandComponent {
1587
1585
  const { grabber } = event?.sourceEvent?.target?.dataset;
1588
1586
  grabberKey = grabber;
1589
1587
  }
1590
- const min = Math.min(...this.scale.domain());
1591
- const max = Math.max(...this.scale.domain());
1588
+ const min = Math.min(...this.scale().domain());
1589
+ const max = Math.max(...this.scale().domain());
1592
1590
  const minValue = d.min ?? min;
1593
1591
  const maxValue = d.max ?? max;
1594
- d[grabberKey] = this.scale.invert(event[AxisOrientation[this.axis.orientation]]);
1592
+ d[grabberKey] = this.scale().invert(event[AxisOrientation[this.axis().orientation]]);
1595
1593
  if (grabberKey === 'from') {
1596
1594
  const borderMin = d.from <= minValue;
1597
1595
  if (d.from >= d.to) {
@@ -1610,18 +1608,21 @@ class PlotBandComponent {
1610
1608
  d.to = d.from;
1611
1609
  }
1612
1610
  }
1611
+ this.fromTo.set({
1612
+ from: d.from,
1613
+ to: d.to,
1614
+ });
1613
1615
  this.emit({
1614
1616
  event,
1615
1617
  target: d,
1616
1618
  });
1617
- this.cdr.detectChanges();
1618
1619
  });
1619
- plotbandElement.datum(this.plotBand);
1620
- grabElements.datum(this.plotBand);
1621
- if (this.plotBand.draggable) {
1620
+ plotbandElement.datum(this.plotBand());
1621
+ grabElements.datum(this.plotBand());
1622
+ if (this.plotBand().draggable) {
1622
1623
  plotbandElement.call(drag);
1623
1624
  }
1624
- if (this.plotBand.resizable) {
1625
+ if (this.plotBand().resizable) {
1625
1626
  grabElements.call(resize);
1626
1627
  }
1627
1628
  }
@@ -1629,27 +1630,13 @@ class PlotBandComponent {
1629
1630
  this.dragElements.on('start drag end', null);
1630
1631
  this.resizeElements.on('start drag end', null);
1631
1632
  }
1632
- getFill(d) {
1633
- if (d.style?.plotBand?.patternImage) {
1634
- return `url(#${d.style.plotBand?.patternImage})`;
1635
- }
1636
- return d.style.plotBand?.fill;
1637
- }
1638
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: PlotBandComponent, deps: [{ token: ChartService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1639
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: PlotBandComponent, isStandalone: true, selector: "[teta-plot-band]", inputs: { plotBand: "plotBand", axis: "axis", scale: "scale", size: "size" }, host: { listeners: { "click": "click($event)", "contextmenu": "contextMenu($event)" } }, ngImport: i0, template: "<svg:rect\n class=\"plotband\"\n xmlns:svg=\"http://www.w3.org/1999/html\"\n [class.draggable]=\"plotBand?.draggable === true\"\n [attr.fill]=\"getFill(plotBand)\"\n [attr.opacity]=\"plotBand.style?.plotBand?.opacity\"\n [attr.height]=\"axis.orientation === orientation.x ? height : bandSize\"\n [attr.width]=\"axis.orientation === orientation.x ? bandSize : width\"\n [attr.y]=\"axis.orientation === orientation.y ? (axis.options.inverted === true ? from : to) : null\"\n [attr.x]=\"axis.orientation === orientation.x ? (axis.options.inverted === true ? to : from) : null\"\n></svg:rect>\n@if (axis.orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n class=\"label font-caption fill-text-90\"\n [attr.x]=\"getTextPosition()\"\n [attr.transform]=\"'rotate(-90, ' + getTextPosition() + ',' + height / 2 + ')'\"\n [attr.y]=\"height / 2\"\n >\n {{ plotBand.label }}\n </svg:text>\n}\n@if (axis.orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-caption fill-text-90\"\n dominant-baseline=\"central\"\n [attr.x]=\"getTextPosition()\"\n [attr.y]=\"width / 2\"\n >\n {{ plotBand.label }}\n </svg:text>\n}\n@if (plotBand.resizable) {\n @if (plotBand.showGrabbers) {\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand.style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand.style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? from : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? from : width\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : from\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : from\"\n ></svg:line>\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand.style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand.style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? to : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? to : width\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : to\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : to\"\n ></svg:line>\n }\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [class.resizeable]=\"plotBand?.resizable\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis.orientation === orientation.x ? 'translateX(2px)' : 'translateY(2px)'\"\n [attr.x1]=\"axis.orientation === orientation.x ? from : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? from : width\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : from\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : from\"\n ></svg:line>\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [class.resizeable]=\"plotBand?.resizable\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis.orientation === orientation.x ? 'translateX(-2px)' : 'translateY(-2px)'\"\n [attr.x1]=\"axis.orientation === orientation.x ? to : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? to : width\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : to\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : to\"\n ></svg:line>\n}\n", styles: [":host .draggable rect:hover{cursor:grab}:host .draggable rect:active{cursor:grabbing}:host .x-grabber.resizeable{cursor:col-resize}:host .y-grabber.resizeable{cursor:row-resize}:host:hover .grabber{opacity:.1}.grabber{opacity:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1633
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: PlotBandComponent, deps: [{ token: ChartService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1634
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: PlotBandComponent, isStandalone: true, selector: "[teta-plot-band]", inputs: { plotBand: { classPropertyName: "plotBand", publicName: "plotBand", 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 }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "click($event)", "contextmenu": "contextMenu($event)" } }, ngImport: i0, template: "<svg:rect\n class=\"plotband\"\n xmlns:svg=\"http://www.w3.org/1999/html\"\n [class.draggable]=\"plotBand()?.draggable === true\"\n [attr.fill]=\"fill()\"\n [attr.opacity]=\"plotBand().style?.plotBand?.opacity\"\n [attr.height]=\"axis().orientation === orientation.x ? height() : bandSize()\"\n [attr.width]=\"axis().orientation === orientation.x ? bandSize() : width()\"\n [attr.y]=\"axis().orientation === orientation.y ? (axis().options.inverted === true ? from() : to()) : null\"\n [attr.x]=\"axis().orientation === orientation.x ? (axis().options.inverted === true ? to() : from()) : null\"\n></svg:rect>\n@if (axis().orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n class=\"label font-caption fill-text-90\"\n [attr.x]=\"textPosition()\"\n [attr.transform]=\"'rotate(-90, ' + textPosition() + ',' + height() / 2 + ')'\"\n [attr.y]=\"height() / 2\"\n >\n {{ plotBand().label }}\n </svg:text>\n}\n@if (axis().orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-caption fill-text-90\"\n dominant-baseline=\"central\"\n [attr.x]=\"textPosition()\"\n [attr.y]=\"width() / 2\"\n >\n {{ plotBand().label }}\n </svg:text>\n}\n@if (plotBand().resizable) {\n @if (plotBand().showGrabbers) {\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand().style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand().style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? from() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? from() : width()\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : from()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : from()\"\n ></svg:line>\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand().style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand().style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? to() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? to() : width()\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : to()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : to()\"\n ></svg:line>\n }\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [class.resizeable]=\"plotBand()?.resizable\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis().orientation === orientation.x ? 'translateX(2px)' : 'translateY(2px)'\"\n [attr.x1]=\"axis().orientation === orientation.x ? from() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? from() : width()\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : from()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : from()\"\n ></svg:line>\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [class.resizeable]=\"plotBand()?.resizable\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis().orientation === orientation.x ? 'translateX(-2px)' : 'translateY(-2px)'\"\n [attr.x1]=\"axis().orientation === orientation.x ? to() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? to() : width()\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : to()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : to()\"\n ></svg:line>\n}\n", styles: [":host .draggable rect:hover{cursor:grab}:host .draggable rect:active{cursor:grabbing}:host .x-grabber.resizeable{cursor:col-resize}:host .y-grabber.resizeable{cursor:row-resize}:host:hover .grabber{opacity:.1}.grabber{opacity:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1640
1635
  }
1641
1636
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: PlotBandComponent, decorators: [{
1642
1637
  type: Component,
1643
- args: [{ selector: '[teta-plot-band]', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:rect\n class=\"plotband\"\n xmlns:svg=\"http://www.w3.org/1999/html\"\n [class.draggable]=\"plotBand?.draggable === true\"\n [attr.fill]=\"getFill(plotBand)\"\n [attr.opacity]=\"plotBand.style?.plotBand?.opacity\"\n [attr.height]=\"axis.orientation === orientation.x ? height : bandSize\"\n [attr.width]=\"axis.orientation === orientation.x ? bandSize : width\"\n [attr.y]=\"axis.orientation === orientation.y ? (axis.options.inverted === true ? from : to) : null\"\n [attr.x]=\"axis.orientation === orientation.x ? (axis.options.inverted === true ? to : from) : null\"\n></svg:rect>\n@if (axis.orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n class=\"label font-caption fill-text-90\"\n [attr.x]=\"getTextPosition()\"\n [attr.transform]=\"'rotate(-90, ' + getTextPosition() + ',' + height / 2 + ')'\"\n [attr.y]=\"height / 2\"\n >\n {{ plotBand.label }}\n </svg:text>\n}\n@if (axis.orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-caption fill-text-90\"\n dominant-baseline=\"central\"\n [attr.x]=\"getTextPosition()\"\n [attr.y]=\"width / 2\"\n >\n {{ plotBand.label }}\n </svg:text>\n}\n@if (plotBand.resizable) {\n @if (plotBand.showGrabbers) {\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand.style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand.style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? from : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? from : width\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : from\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : from\"\n ></svg:line>\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand.style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand.style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis.orientation === orientation.x ? to : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? to : width\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : to\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : to\"\n ></svg:line>\n }\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [class.resizeable]=\"plotBand?.resizable\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis.orientation === orientation.x ? 'translateX(2px)' : 'translateY(2px)'\"\n [attr.x1]=\"axis.orientation === orientation.x ? from : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? from : width\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : from\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : from\"\n ></svg:line>\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis.orientation === orientation.x\"\n [class.y-grabber]=\"axis.orientation === orientation.y\"\n [class.resizeable]=\"plotBand?.resizable\"\n [attr.stroke]=\"plotBand.style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis.orientation === orientation.x ? 'translateX(-2px)' : 'translateY(-2px)'\"\n [attr.x1]=\"axis.orientation === orientation.x ? to : 0\"\n [attr.x2]=\"axis.orientation === orientation.x ? to : width\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis.orientation === orientation.x ? 0 : to\"\n [attr.y2]=\"axis.orientation === orientation.x ? height : to\"\n ></svg:line>\n}\n", styles: [":host .draggable rect:hover{cursor:grab}:host .draggable rect:active{cursor:grabbing}:host .x-grabber.resizeable{cursor:col-resize}:host .y-grabber.resizeable{cursor:row-resize}:host:hover .grabber{opacity:.1}.grabber{opacity:0}\n"] }]
1644
- }], ctorParameters: () => [{ type: ChartService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { plotBand: [{
1645
- type: Input
1646
- }], axis: [{
1647
- type: Input
1648
- }], scale: [{
1649
- type: Input
1650
- }], size: [{
1651
- type: Input
1652
- }], click: [{
1638
+ args: [{ selector: '[teta-plot-band]', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:rect\n class=\"plotband\"\n xmlns:svg=\"http://www.w3.org/1999/html\"\n [class.draggable]=\"plotBand()?.draggable === true\"\n [attr.fill]=\"fill()\"\n [attr.opacity]=\"plotBand().style?.plotBand?.opacity\"\n [attr.height]=\"axis().orientation === orientation.x ? height() : bandSize()\"\n [attr.width]=\"axis().orientation === orientation.x ? bandSize() : width()\"\n [attr.y]=\"axis().orientation === orientation.y ? (axis().options.inverted === true ? from() : to()) : null\"\n [attr.x]=\"axis().orientation === orientation.x ? (axis().options.inverted === true ? to() : from()) : null\"\n></svg:rect>\n@if (axis().orientation === orientation.x) {\n <svg:text\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n class=\"label font-caption fill-text-90\"\n [attr.x]=\"textPosition()\"\n [attr.transform]=\"'rotate(-90, ' + textPosition() + ',' + height() / 2 + ')'\"\n [attr.y]=\"height() / 2\"\n >\n {{ plotBand().label }}\n </svg:text>\n}\n@if (axis().orientation === orientation.y) {\n <svg:text\n text-anchor=\"middle\"\n class=\"label font-caption fill-text-90\"\n dominant-baseline=\"central\"\n [attr.x]=\"textPosition()\"\n [attr.y]=\"width() / 2\"\n >\n {{ plotBand().label }}\n </svg:text>\n}\n@if (plotBand().resizable) {\n @if (plotBand().showGrabbers) {\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand().style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand().style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? from() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? from() : width()\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : from()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : from()\"\n ></svg:line>\n <svg:line\n class=\"display-grabber\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"plotBand().style?.grabbers?.strokeWidth || 4\"\n [attr.stroke-dasharray]=\"plotBand().style?.grabbers?.strokeDasharray\"\n [attr.x1]=\"axis().orientation === orientation.x ? to() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? to() : width()\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : to()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : to()\"\n ></svg:line>\n }\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [class.resizeable]=\"plotBand()?.resizable\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis().orientation === orientation.x ? 'translateX(2px)' : 'translateY(2px)'\"\n [attr.x1]=\"axis().orientation === orientation.x ? from() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? from() : width()\"\n [attr.data-grabber]=\"'from'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : from()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : from()\"\n ></svg:line>\n <svg:line\n class=\"grabber\"\n [class.x-grabber]=\"axis().orientation === orientation.x\"\n [class.y-grabber]=\"axis().orientation === orientation.y\"\n [class.resizeable]=\"plotBand()?.resizable\"\n [attr.stroke]=\"plotBand().style?.grabbers?.stroke || 'var(--color-text-50)'\"\n [attr.stroke-width]=\"8\"\n [style.transform]=\"axis().orientation === orientation.x ? 'translateX(-2px)' : 'translateY(-2px)'\"\n [attr.x1]=\"axis().orientation === orientation.x ? to() : 0\"\n [attr.x2]=\"axis().orientation === orientation.x ? to() : width()\"\n [attr.data-grabber]=\"'to'\"\n [attr.y1]=\"axis().orientation === orientation.x ? 0 : to()\"\n [attr.y2]=\"axis().orientation === orientation.x ? height() : to()\"\n ></svg:line>\n}\n", styles: [":host .draggable rect:hover{cursor:grab}:host .draggable rect:active{cursor:grabbing}:host .x-grabber.resizeable{cursor:col-resize}:host .y-grabber.resizeable{cursor:row-resize}:host:hover .grabber{opacity:.1}.grabber{opacity:0}\n"] }]
1639
+ }], ctorParameters: () => [{ type: ChartService }, { type: i0.ElementRef }], propDecorators: { click: [{
1653
1640
  type: HostListener,
1654
1641
  args: ['click', ['$event']]
1655
1642
  }], contextMenu: [{
@@ -2236,12 +2223,15 @@ class SeriesHostComponent {
2236
2223
  this.count = 0;
2237
2224
  effect(() => {
2238
2225
  if (this.series()) {
2239
- this.viewContainerRef.clear();
2240
- this._componentRef?.destroy();
2241
2226
  if (!Object.prototype.isPrototypeOf.call(SeriesBaseComponent, this.series().component)) {
2242
2227
  this.series().component = defaultSeriesTypeMapping.get(this.series().type) || LineSeriesComponent;
2243
2228
  }
2244
- this._componentRef = this.viewContainerRef.createComponent(this.series().component);
2229
+ if (this.series().component !== this.seriesComponent) {
2230
+ this.viewContainerRef.clear();
2231
+ this._componentRef?.destroy();
2232
+ this._componentRef = this.viewContainerRef.createComponent(this.series().component);
2233
+ this.seriesComponent = this.series().component;
2234
+ }
2245
2235
  this._componentRef?.setInput('config', this.config());
2246
2236
  this._componentRef?.setInput('series', this.series());
2247
2237
  }
@@ -2821,7 +2811,7 @@ class ChartContainerComponent {
2821
2811
  this._svc.setPointerMove(event);
2822
2812
  }
2823
2813
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ChartContainerComponent, deps: [{ token: ChartService }, { token: ScaleService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
2824
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: ChartContainerComponent, isStandalone: true, selector: "teta-chart-container", ngImport: i0, template: "@if ({\n size: size | async,\n config: config | async,\n scales: scales | async,\n plotBands: plotBands | async,\n visibleRect: visibleRect | async,\n};\n as data) {\n @if (data.config?.tooltip?.enable) {\n <teta-tooltip [size]=\"data.size\" [config]=\"data.config\"></teta-tooltip>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n @for (item of data.scales.y | keyvalue; track item.value.index) {\n @if (item.value.selfSize > 0 && item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n <g class=\"x-axis-container\">\n @for (item of data.scales.x | keyvalue; track item.value.index) {\n @if (item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n </svg>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg\n tetaZoomable\n tetaBrushable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate(' + data.visibleRect.x + 'px, ' + data.visibleRect.y + 'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n @if (data.config.gridLines?.enable !== false) {\n <g class=\"gridlines\" teta-gridlines [size]=\"data.size\"></g>\n }\n <g class=\"x-axis-plotband-container\">\n @for (plotBand of data.plotBands; track $index) {\n <g teta-plot-band\n [plotBand]=\"plotBand.plotBand\"\n [scale]=\"plotBand.axis.scale\"\n [size]=\"data.visibleRect\"\n [axis]=\"plotBand.axis\"></g>\n }\n </g>\n <g class=\"series-container\">\n @for (series of data.config.series; track series) {\n @if (series.visible && series.enabled) {\n <g teta-series-host [config]=\"data.config\" [series]=\"series\"></g>\n }\n }\n </g>\n <g class=\"x-axis-plotline-container\">\n @for (axis of data.config.xAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n }\n }\n </g>\n <g class=\"y-axis-plotline-container\">\n @for (axis of data.config.yAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n }\n }\n </g>\n <g class=\"annotations\">\n @for (annotation of data.config.annotations; track annotation) {\n <g teta-annotation [visibleRect]=\"data.visibleRect\" [annotation]=\"annotation\"></g>\n }\n </g>\n @if (data.config.tooltip?.showCrosshair) {\n <g class=\"crosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n }\n </svg>\n @if (data.config.controls?.enable) {\n <teta-series-controls [series]=\"data.config.series\"\n class=\"position-absolute\"\n style=\"transform: translateX(-100%)\"\n [style.top.px]=\"data.visibleRect.y + 12\"\n [style.left.px]=\"data.visibleRect.width + data.visibleRect.x -12\">\n </teta-series-controls>\n }\n }\n}\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}:host .crosshair{cursor:crosshair}\n"], dependencies: [{ kind: "component", type: TooltipComponent, selector: "teta-tooltip", inputs: ["size", "config"] }, { kind: "directive", type: ZoomableDirective, selector: "[tetaZoomable]", inputs: ["config", "axis", "size"] }, { kind: "component", type: XAxisComponent, selector: "[teta-x-axis]", inputs: ["axis", "size"] }, { kind: "component", type: YAxisComponent, selector: "[teta-y-axis]", inputs: ["axis", "size"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "component", type: PlotBandComponent, selector: "[teta-plot-band]", inputs: ["plotBand", "axis", "scale", "size"] }, { kind: "component", type: GridlinesComponent, selector: "[teta-gridlines]", inputs: ["size"] }, { kind: "component", type: SeriesHostComponent, selector: "[teta-series-host]", inputs: ["config", "series"] }, { kind: "component", type: PlotlineComponent, selector: "[teta-plot-line]", inputs: ["plotLine", "size", "axis", "scale"] }, { kind: "component", type: AnnotationComponent, selector: "[teta-annotation]", inputs: ["visibleRect", "annotation"] }, { kind: "component", type: CrosshairComponent, selector: "[teta-crosshair]", inputs: ["size"] }, { kind: "directive", type: BrushableDirective, selector: "[tetaBrushable]", inputs: ["config", "axis"] }, { kind: "component", type: SeriesControlsComponent, selector: "teta-series-controls", inputs: ["series"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2814
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: ChartContainerComponent, isStandalone: true, selector: "teta-chart-container", ngImport: i0, template: "@if ({\n size: size | async,\n config: config | async,\n scales: scales | async,\n plotBands: plotBands | async,\n visibleRect: visibleRect | async,\n};\n as data) {\n @if (data.config?.tooltip?.enable) {\n <teta-tooltip [size]=\"data.size\" [config]=\"data.config\"></teta-tooltip>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n @for (item of data.scales.y | keyvalue; track item.value.index) {\n @if (item.value.selfSize > 0 && item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n <g class=\"x-axis-container\">\n @for (item of data.scales.x | keyvalue; track item.value.index) {\n @if (item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n </svg>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg\n tetaZoomable\n tetaBrushable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate(' + data.visibleRect.x + 'px, ' + data.visibleRect.y + 'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n @if (data.config.gridLines?.enable !== false) {\n <g class=\"gridlines\" teta-gridlines [size]=\"data.size\"></g>\n }\n <g class=\"x-axis-plotband-container\">\n @for (plotBand of data.plotBands; track $index) {\n <g teta-plot-band\n [plotBand]=\"plotBand.plotBand\"\n [scale]=\"plotBand.axis.scale\"\n [size]=\"data.visibleRect\"\n [axis]=\"plotBand.axis\"></g>\n }\n </g>\n <g class=\"series-container\">\n @for (series of data.config.series; track $index) {\n @if (series.visible && series.enabled) {\n <g teta-series-host [config]=\"data.config\" [series]=\"series\"></g>\n }\n }\n </g>\n <g class=\"x-axis-plotline-container\">\n @for (axis of data.config.xAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n }\n }\n </g>\n <g class=\"y-axis-plotline-container\">\n @for (axis of data.config.yAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n }\n }\n </g>\n <g class=\"annotations\">\n @for (annotation of data.config.annotations; track annotation) {\n <g teta-annotation [visibleRect]=\"data.visibleRect\" [annotation]=\"annotation\"></g>\n }\n </g>\n @if (data.config.tooltip?.showCrosshair) {\n <g class=\"crosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n }\n </svg>\n @if (data.config.controls?.enable) {\n <teta-series-controls [series]=\"data.config.series\"\n class=\"position-absolute\"\n style=\"transform: translateX(-100%)\"\n [style.top.px]=\"data.visibleRect.y + 12\"\n [style.left.px]=\"data.visibleRect.width + data.visibleRect.x -12\">\n </teta-series-controls>\n }\n }\n}\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}:host .crosshair{cursor:crosshair}\n"], dependencies: [{ kind: "component", type: TooltipComponent, selector: "teta-tooltip", inputs: ["size", "config"] }, { kind: "directive", type: ZoomableDirective, selector: "[tetaZoomable]", inputs: ["config", "axis", "size"] }, { kind: "component", type: XAxisComponent, selector: "[teta-x-axis]", inputs: ["axis", "size"] }, { kind: "component", type: YAxisComponent, selector: "[teta-y-axis]", inputs: ["axis", "size"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "component", type: PlotBandComponent, selector: "[teta-plot-band]", inputs: ["plotBand", "axis", "scale", "size"] }, { kind: "component", type: GridlinesComponent, selector: "[teta-gridlines]", inputs: ["size"] }, { kind: "component", type: SeriesHostComponent, selector: "[teta-series-host]", inputs: ["config", "series"] }, { kind: "component", type: PlotlineComponent, selector: "[teta-plot-line]", inputs: ["plotLine", "size", "axis", "scale"] }, { kind: "component", type: AnnotationComponent, selector: "[teta-annotation]", inputs: ["visibleRect", "annotation"] }, { kind: "component", type: CrosshairComponent, selector: "[teta-crosshair]", inputs: ["size"] }, { kind: "directive", type: BrushableDirective, selector: "[tetaBrushable]", inputs: ["config", "axis"] }, { kind: "component", type: SeriesControlsComponent, selector: "teta-series-controls", inputs: ["series"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2825
2815
  }
2826
2816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ChartContainerComponent, decorators: [{
2827
2817
  type: Component,
@@ -2840,7 +2830,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
2840
2830
  CrosshairComponent,
2841
2831
  BrushableDirective,
2842
2832
  SeriesControlsComponent,
2843
- ], template: "@if ({\n size: size | async,\n config: config | async,\n scales: scales | async,\n plotBands: plotBands | async,\n visibleRect: visibleRect | async,\n};\n as data) {\n @if (data.config?.tooltip?.enable) {\n <teta-tooltip [size]=\"data.size\" [config]=\"data.config\"></teta-tooltip>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n @for (item of data.scales.y | keyvalue; track item.value.index) {\n @if (item.value.selfSize > 0 && item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n <g class=\"x-axis-container\">\n @for (item of data.scales.x | keyvalue; track item.value.index) {\n @if (item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n </svg>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg\n tetaZoomable\n tetaBrushable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate(' + data.visibleRect.x + 'px, ' + data.visibleRect.y + 'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n @if (data.config.gridLines?.enable !== false) {\n <g class=\"gridlines\" teta-gridlines [size]=\"data.size\"></g>\n }\n <g class=\"x-axis-plotband-container\">\n @for (plotBand of data.plotBands; track $index) {\n <g teta-plot-band\n [plotBand]=\"plotBand.plotBand\"\n [scale]=\"plotBand.axis.scale\"\n [size]=\"data.visibleRect\"\n [axis]=\"plotBand.axis\"></g>\n }\n </g>\n <g class=\"series-container\">\n @for (series of data.config.series; track series) {\n @if (series.visible && series.enabled) {\n <g teta-series-host [config]=\"data.config\" [series]=\"series\"></g>\n }\n }\n </g>\n <g class=\"x-axis-plotline-container\">\n @for (axis of data.config.xAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n }\n }\n </g>\n <g class=\"y-axis-plotline-container\">\n @for (axis of data.config.yAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n }\n }\n </g>\n <g class=\"annotations\">\n @for (annotation of data.config.annotations; track annotation) {\n <g teta-annotation [visibleRect]=\"data.visibleRect\" [annotation]=\"annotation\"></g>\n }\n </g>\n @if (data.config.tooltip?.showCrosshair) {\n <g class=\"crosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n }\n </svg>\n @if (data.config.controls?.enable) {\n <teta-series-controls [series]=\"data.config.series\"\n class=\"position-absolute\"\n style=\"transform: translateX(-100%)\"\n [style.top.px]=\"data.visibleRect.y + 12\"\n [style.left.px]=\"data.visibleRect.width + data.visibleRect.x -12\">\n </teta-series-controls>\n }\n }\n}\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}:host .crosshair{cursor:crosshair}\n"] }]
2833
+ ], template: "@if ({\n size: size | async,\n config: config | async,\n scales: scales | async,\n plotBands: plotBands | async,\n visibleRect: visibleRect | async,\n};\n as data) {\n @if (data.config?.tooltip?.enable) {\n <teta-tooltip [size]=\"data.size\" [config]=\"data.config\"></teta-tooltip>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg height=\"100%\" width=\"100%\" class=\"position-absolute\">\n <g class=\"y-axis-container\">\n @for (item of data.scales.y | keyvalue; track item.value.index) {\n @if (item.value.selfSize > 0 && item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-y-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"item.value.options.opposite ? 0 : -item.value.selfSize\"\n [attr.y]=\"0\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.width]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n <g class=\"x-axis-container\">\n @for (item of data.scales.x | keyvalue; track item.value.index) {\n @if (item.value.options.visible && data.scales.x.size > 0 && data.scales.y.size > 0) {\n <g teta-x-axis\n [axis]=\"item.value\"\n [size]=\"data.visibleRect\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></g>\n <rect tetaZoomable\n fill-opacity=\"0\"\n [axis]=\"item.value\"\n [config]=\"data.config\"\n [size]=\"data.visibleRect\"\n [attr.x]=\"0\"\n [attr.y]=\"item.value.options.opposite ? -item.value.selfSize : 0\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"item.value.selfSize\"\n [attr.transform]=\"getTranslate(item.value, data.size) | async\"></rect>\n }\n }\n </g>\n </svg>\n }\n @if (data.size?.height > 0 &&\n data.size?.width > 0 &&\n data.visibleRect?.height > 0 &&\n data.visibleRect?.width > 0 &&\n data.scales?.x.size === data.config.xAxis.length &&\n data.scales?.y.size === data.config.yAxis.length) {\n <svg\n tetaZoomable\n tetaBrushable\n class=\"position-absolute\"\n [size]=\"data.visibleRect\"\n [config]=\"data.config\"\n [axis]=\"data.config?.zoom?.type === zoomType.x ? data.scales.x.get(0) : data.scales.y.get(0)\"\n [attr.width]=\"data.visibleRect.width\"\n [attr.height]=\"data.visibleRect.height\"\n [attr.viewBox]=\"'0 0 ' + data.visibleRect.width + ' ' + data.visibleRect.height\"\n [style.transform]=\"'translate(' + data.visibleRect.x + 'px, ' + data.visibleRect.y + 'px)'\"\n (contextmenu)=\"contextMenu($event, data.scales.x, data.scales.y)\"\n (click)=\"click($event, data.scales.x, data.scales.y)\"\n (mouseleave)=\"mouseLeave($event)\"\n (mousemove)=\"mouseMove($event)\">\n @if (data.config.gridLines?.enable !== false) {\n <g class=\"gridlines\" teta-gridlines [size]=\"data.size\"></g>\n }\n <g class=\"x-axis-plotband-container\">\n @for (plotBand of data.plotBands; track $index) {\n <g teta-plot-band\n [plotBand]=\"plotBand.plotBand\"\n [scale]=\"plotBand.axis.scale\"\n [size]=\"data.visibleRect\"\n [axis]=\"plotBand.axis\"></g>\n }\n </g>\n <g class=\"series-container\">\n @for (series of data.config.series; track $index) {\n @if (series.visible && series.enabled) {\n <g teta-series-host [config]=\"data.config\" [series]=\"series\"></g>\n }\n }\n </g>\n <g class=\"x-axis-plotline-container\">\n @for (axis of data.config.xAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.x.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.x.get(i)\"></g>\n }\n }\n </g>\n <g class=\"y-axis-plotline-container\">\n @for (axis of data.config.yAxis; let i = $index; track axis) {\n @for (plotLine of axis.plotLines; track $index) {\n <g teta-plot-line\n [plotLine]=\"plotLine\"\n [scale]=\"data.scales.y.get(i).scale\"\n [size]=\"data.size\"\n [axis]=\"data.scales.y.get(i)\"></g>\n }\n }\n </g>\n <g class=\"annotations\">\n @for (annotation of data.config.annotations; track annotation) {\n <g teta-annotation [visibleRect]=\"data.visibleRect\" [annotation]=\"annotation\"></g>\n }\n </g>\n @if (data.config.tooltip?.showCrosshair) {\n <g class=\"crosshair\">\n <g teta-crosshair [size]=\"data.visibleRect\"></g>\n </g>\n }\n </svg>\n @if (data.config.controls?.enable) {\n <teta-series-controls [series]=\"data.config.series\"\n class=\"position-absolute\"\n style=\"transform: translateX(-100%)\"\n [style.top.px]=\"data.visibleRect.y + 12\"\n [style.left.px]=\"data.visibleRect.width + data.visibleRect.x -12\">\n </teta-series-controls>\n }\n }\n}\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}:host .crosshair{cursor:crosshair}\n"] }]
2844
2834
  }], ctorParameters: () => [{ type: ChartService }, { type: ScaleService }, { type: i0.ElementRef }] });
2845
2835
 
2846
2836
  class LegendComponent {
@@ -3009,6 +2999,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
3009
2999
  type: Input
3010
3000
  }] } });
3011
3001
 
3002
+ class PlotBand {
3003
+ constructor(options) {
3004
+ this.order = 0;
3005
+ this.id = options?.id;
3006
+ this.name = options?.name;
3007
+ this.from = options?.from;
3008
+ this.to = options?.to;
3009
+ this.label = options?.label;
3010
+ this.showGrabbers = options?.showGrabbers != null ? options.showGrabbers : true;
3011
+ this.draggable = options?.draggable != null ? options?.draggable : false;
3012
+ this.resizable = options?.resizable != null ? options?.resizable : true;
3013
+ this.min = options?.min;
3014
+ this.max = options?.max;
3015
+ this.order = options?.order ?? 0;
3016
+ this.style = options?.style;
3017
+ }
3018
+ }
3019
+
3012
3020
  class BlockHorizontalSeriesComponent extends SeriesBaseComponent {
3013
3021
  constructor() {
3014
3022
  super(...arguments);