@tetacom/svg-charts 1.7.36 → 1.7.38

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,6 +1,6 @@
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 } from 'rxjs';
3
+ import { ReplaySubject, filter, BehaviorSubject, Subject, of, shareReplay, withLatestFrom, map, merge, lastValueFrom, take, combineLatest, tap, takeWhile, 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';
@@ -193,6 +193,9 @@ class ChartService {
193
193
  this.plotBandEvent$ = new Subject();
194
194
  this.plotLineMove$ = new Subject();
195
195
  this.pointMove$ = new Subject();
196
+ this.seriesMove$ = new Subject();
197
+ this.seriesPathOffsets$ = new BehaviorSubject(new Map());
198
+ this.selectedSeriesIds$ = new BehaviorSubject([]);
196
199
  this.chartClick$ = new Subject();
197
200
  this.chartContextMenu$ = new Subject();
198
201
  this.annotationEvent$ = new Subject();
@@ -216,6 +219,9 @@ class ChartService {
216
219
  this.plotBandEvent = this.plotBandEvent$.asObservable();
217
220
  this.plotLineMove = this.plotLineMove$.asObservable();
218
221
  this.pointMove = this.pointMove$.asObservable();
222
+ this.seriesMove = this.seriesMove$.asObservable();
223
+ this.seriesPathOffsets = this.seriesPathOffsets$.asObservable();
224
+ this.selectedSeriesIds = this.selectedSeriesIds$.asObservable();
219
225
  this.chartClick = this.chartClick$.asObservable();
220
226
  this.chartContextMenu = this.chartContextMenu$.asObservable();
221
227
  this.annotationClick = this.annotationEvent$.asObservable().pipe(filter((_) => _?.event?.type === 'click'));
@@ -231,6 +237,7 @@ class ChartService {
231
237
  }
232
238
  setConfig(config) {
233
239
  this.clearTooltips();
240
+ this.clearSeriesPathOffsets();
234
241
  this.config$.next(config);
235
242
  }
236
243
  setSize(size) {
@@ -293,6 +300,39 @@ class ChartService {
293
300
  emitPoint(event) {
294
301
  this.pointMove$.next(event);
295
302
  }
303
+ emitSeriesMove(event) {
304
+ this.seriesMove$.next(event);
305
+ }
306
+ getSeriesPathOffsets() {
307
+ return this.seriesPathOffsets$.value;
308
+ }
309
+ setSeriesPathOffsets(offsets) {
310
+ this.seriesPathOffsets$.next(new Map(offsets));
311
+ }
312
+ clearSeriesPathOffsets() {
313
+ this.seriesPathOffsets$.next(new Map());
314
+ }
315
+ getSelectedSeriesIds() {
316
+ return this.selectedSeriesIds$.value;
317
+ }
318
+ setSelectedSeriesIds(seriesIds) {
319
+ const nextSeriesIds = [...(seriesIds ?? [])];
320
+ if (this.areSeriesIdsEqual(this.selectedSeriesIds$.value, nextSeriesIds)) {
321
+ return;
322
+ }
323
+ this.selectedSeriesIds$.next(nextSeriesIds);
324
+ }
325
+ toggleSelectedSeriesId(seriesId) {
326
+ const selectedIds = this.selectedSeriesIds$.value;
327
+ if (selectedIds.includes(seriesId)) {
328
+ this.setSelectedSeriesIds(selectedIds.filter((id) => id !== seriesId));
329
+ return;
330
+ }
331
+ this.setSelectedSeriesIds([...selectedIds, seriesId]);
332
+ }
333
+ areSeriesIdsEqual(first, second) {
334
+ return first.length === second.length && first.every((id, index) => id === second[index]);
335
+ }
296
336
  emitChartClick(event) {
297
337
  this.chartClick$.next(event);
298
338
  }
@@ -1740,6 +1780,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1740
1780
  }] } });
1741
1781
 
1742
1782
  class LinearSeriesBaseComponent extends SeriesBaseComponent {
1783
+ getClipOffset() {
1784
+ return { x: 0, y: 0 };
1785
+ }
1743
1786
  constructor() {
1744
1787
  super();
1745
1788
  this.pointerMove = toSignal(this.svc.pointerMove);
@@ -1768,17 +1811,18 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1768
1811
  .x((point) => this.x()(point.x))
1769
1812
  .y((point) => this.y()(point.y));
1770
1813
  let filteredData = this.series().data;
1814
+ const clipOffset = this.getClipOffset();
1771
1815
  if (this.series().clipPointsDirection === ClipPointsDirection.x) {
1772
1816
  let [min, max] = this.x().domain();
1773
1817
  min = min instanceof Date ? min.getTime() : min;
1774
1818
  max = max instanceof Date ? max.getTime() : max;
1775
- filteredData = filteredData?.filter(filter(min, max));
1819
+ filteredData = filteredData?.filter(filter(min - clipOffset.x, max - clipOffset.x));
1776
1820
  }
1777
1821
  if (this.series().clipPointsDirection === ClipPointsDirection.y) {
1778
1822
  let [min, max] = this.y().domain();
1779
1823
  min = min instanceof Date ? min.getTime() : min;
1780
1824
  max = max instanceof Date ? max.getTime() : max;
1781
- filteredData = filteredData?.filter(filter(min, max));
1825
+ filteredData = filteredData?.filter(filter(min - clipOffset.y, max - clipOffset.y));
1782
1826
  }
1783
1827
  return line(filteredData);
1784
1828
  }, ...(ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []));
@@ -1825,6 +1869,13 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1825
1869
  }
1826
1870
  const mouse = [event?.offsetX, event?.offsetY];
1827
1871
  const tooltipTracking = this.config()?.tooltip?.tracking;
1872
+ const clipOffset = this.getClipOffset();
1873
+ const addOffset = (value, offset) => {
1874
+ return value instanceof Date ? new Date(value.getTime() + offset) : value + offset;
1875
+ };
1876
+ const subtractOffset = (value, offset) => {
1877
+ return value instanceof Date ? value.getTime() - offset : value - offset;
1878
+ };
1828
1879
  const lineIntersection = (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) => {
1829
1880
  const rV = {};
1830
1881
  const s1_x = p1_x - p0_x;
@@ -1847,9 +1898,10 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1847
1898
  if (x0 instanceof Date) {
1848
1899
  x0 = x0.getTime();
1849
1900
  }
1901
+ x0 = subtractOffset(x0, clipOffset.x);
1850
1902
  const rightId = bisect([...this.series().data].sort((a, b) => a.x - b.x), x0);
1851
1903
  const range = scaleY.range();
1852
- const intersect = lineIntersection(pointer, range[0], pointer, Number.MAX_SAFE_INTEGER, scaleX(sortedData[rightId - 1]?.x), scaleY(sortedData[rightId - 1]?.y), scaleX(sortedData[rightId]?.x), scaleY(sortedData[rightId]?.y));
1904
+ 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)));
1853
1905
  const x = scaleX.invert(intersect.x);
1854
1906
  const y = scaleY.invert(intersect.y);
1855
1907
  if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
@@ -1879,9 +1931,10 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
1879
1931
  if (y0 instanceof Date) {
1880
1932
  y0 = y0.getTime();
1881
1933
  }
1934
+ y0 = subtractOffset(y0, clipOffset.y);
1882
1935
  const rightId = bisect(sortedData, y0);
1883
1936
  const range = scaleX.range();
1884
- const intersect = lineIntersection(range[0], mouse[1], Number.MAX_SAFE_INTEGER, mouse[1], scaleX(sortedData[rightId - 1]?.x), scaleY(sortedData[rightId - 1]?.y), scaleX(sortedData[rightId]?.x), scaleY(sortedData[rightId]?.y));
1937
+ const intersect = lineIntersection(range[0], mouse[1], Number.MAX_SAFE_INTEGER, mouse[1], 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)));
1885
1938
  const x = scaleX.invert(intersect.x);
1886
1939
  const y = scaleY.invert(intersect.y);
1887
1940
  if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
@@ -2068,9 +2121,131 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2068
2121
  args: ['window:touchmove', ['$event']]
2069
2122
  }] } });
2070
2123
 
2124
+ class DraggableSeriesDirective {
2125
+ constructor() {
2126
+ this.dragDirection = DragPointType.xy;
2127
+ this.moveStart = new EventEmitter();
2128
+ this.moveProcess = new EventEmitter();
2129
+ this.moveEnd = new EventEmitter();
2130
+ }
2131
+ pointerDown(event) {
2132
+ if (!this.tetaDraggableSeries) {
2133
+ return;
2134
+ }
2135
+ event.stopPropagation();
2136
+ event.preventDefault();
2137
+ this.startPosition = {
2138
+ x: event.clientX,
2139
+ y: event.clientY,
2140
+ };
2141
+ this.moveStart.emit({
2142
+ x: event.clientX,
2143
+ y: event.clientY,
2144
+ deltaX: 0,
2145
+ deltaY: 0,
2146
+ });
2147
+ }
2148
+ pointerMove(event) {
2149
+ if (!this.startPosition) {
2150
+ return;
2151
+ }
2152
+ const nextOffset = this.getNextOffset(event);
2153
+ event.stopPropagation();
2154
+ event.preventDefault();
2155
+ this.moveProcess.emit({
2156
+ x: event.clientX,
2157
+ y: event.clientY,
2158
+ deltaX: nextOffset.x,
2159
+ deltaY: nextOffset.y,
2160
+ });
2161
+ }
2162
+ pointerUp(event) {
2163
+ if (!this.startPosition) {
2164
+ return;
2165
+ }
2166
+ const nextOffset = this.getNextOffset(event);
2167
+ this.moveEnd.emit({
2168
+ x: event.clientX,
2169
+ y: event.clientY,
2170
+ deltaX: nextOffset.x,
2171
+ deltaY: nextOffset.y,
2172
+ });
2173
+ this.startPosition = null;
2174
+ }
2175
+ resetTransform() {
2176
+ this.startPosition = null;
2177
+ }
2178
+ getNextOffset(event) {
2179
+ let deltaX = event.clientX - this.startPosition.x;
2180
+ let deltaY = event.clientY - this.startPosition.y;
2181
+ if (this.dragDirection === DragPointType.x) {
2182
+ deltaY = 0;
2183
+ }
2184
+ if (this.dragDirection === DragPointType.y) {
2185
+ deltaX = 0;
2186
+ }
2187
+ return {
2188
+ x: deltaX,
2189
+ y: deltaY,
2190
+ };
2191
+ }
2192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DraggableSeriesDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2193
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: DraggableSeriesDirective, isStandalone: true, selector: "[tetaDraggableSeries]", inputs: { tetaDraggableSeries: "tetaDraggableSeries", dragDirection: "dragDirection" }, outputs: { moveStart: "moveStart", moveProcess: "moveProcess", moveEnd: "moveEnd" }, host: { listeners: { "pointerdown": "pointerDown($event)", "window:pointermove": "pointerMove($event)", "window:pointerup": "pointerUp($event)", "window:pointercancel": "pointerUp($event)" } }, exportAs: ["tetaDraggableSeries"], ngImport: i0 }); }
2194
+ }
2195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DraggableSeriesDirective, decorators: [{
2196
+ type: Directive,
2197
+ args: [{
2198
+ selector: '[tetaDraggableSeries]',
2199
+ exportAs: 'tetaDraggableSeries',
2200
+ standalone: true,
2201
+ }]
2202
+ }], propDecorators: { tetaDraggableSeries: [{
2203
+ type: Input
2204
+ }], dragDirection: [{
2205
+ type: Input
2206
+ }], moveStart: [{
2207
+ type: Output
2208
+ }], moveProcess: [{
2209
+ type: Output
2210
+ }], moveEnd: [{
2211
+ type: Output
2212
+ }], pointerDown: [{
2213
+ type: HostListener,
2214
+ args: ['pointerdown', ['$event']]
2215
+ }], pointerMove: [{
2216
+ type: HostListener,
2217
+ args: ['window:pointermove', ['$event']]
2218
+ }], pointerUp: [{
2219
+ type: HostListener,
2220
+ args: ['window:pointerup', ['$event']]
2221
+ }, {
2222
+ type: HostListener,
2223
+ args: ['window:pointercancel', ['$event']]
2224
+ }] } });
2225
+
2071
2226
  class LineSeriesComponent extends LinearSeriesBaseComponent {
2072
2227
  constructor() {
2073
2228
  super(...arguments);
2229
+ this.seriesPathOffsets = toSignal(this.svc.seriesPathOffsets, { initialValue: new Map() });
2230
+ this.selectedSeriesIds = toSignal(this.svc.selectedSeriesIds, { initialValue: [] });
2231
+ this.seriesDragStartOffsets = new Map();
2232
+ this.seriesDragGroup = [];
2233
+ this.seriesDragMoved = false;
2234
+ this.seriesOffsetValue = computed(() => {
2235
+ return this.seriesPathOffsets().get(this.series().id) ?? { x: 0, y: 0 };
2236
+ }, ...(ngDevMode ? [{ debugName: "seriesOffsetValue" }] : /* istanbul ignore next */ []));
2237
+ this.seriesSelectedForPathDrag = computed(() => {
2238
+ return this.isSeriesSelectedForPathDrag(this.series());
2239
+ }, ...(ngDevMode ? [{ debugName: "seriesSelectedForPathDrag" }] : /* istanbul ignore next */ []));
2240
+ this.seriesPathTransform = computed(() => {
2241
+ const offset = this.seriesOffsetValue();
2242
+ const offsetX = this.getOffsetPixels(this.x(), offset.x);
2243
+ const offsetY = this.getOffsetPixels(this.y(), offset.y);
2244
+ if (!offsetX && !offsetY) {
2245
+ return null;
2246
+ }
2247
+ return `translate(${offsetX}, ${offsetY})`;
2248
+ }, ...(ngDevMode ? [{ debugName: "seriesPathTransform" }] : /* istanbul ignore next */ []));
2074
2249
  this.allowDrag = (point) => {
2075
2250
  return (newPoint) => {
2076
2251
  if (point.marker.minX !== null && point.marker.minX !== undefined) {
@@ -2097,6 +2272,40 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
2097
2272
  };
2098
2273
  };
2099
2274
  }
2275
+ seriesMoveStart(event) {
2276
+ this.seriesDragMoved = false;
2277
+ this.seriesDragGroup = this.getPathDragSeriesGroup();
2278
+ this.seriesDragStartOffsets = new Map(this.seriesDragGroup.map((series) => {
2279
+ return [series.id, this.svc.getSeriesPathOffsets().get(series.id) ?? { x: 0, y: 0 }];
2280
+ }));
2281
+ this.emitSeriesMove('start', event);
2282
+ }
2283
+ seriesMoveProcess(event) {
2284
+ this.seriesDragMoved = this.seriesDragMoved || Math.abs(event.deltaX) > 3 || Math.abs(event.deltaY) > 3;
2285
+ this.updateSeriesOffset(event);
2286
+ this.emitSeriesMove('drag', event);
2287
+ }
2288
+ seriesMoveEnd(event) {
2289
+ this.updateSeriesOffset(event);
2290
+ this.emitSeriesMove('end', event);
2291
+ }
2292
+ seriesPathClick(event) {
2293
+ if (this.seriesDragMoved) {
2294
+ event.stopPropagation();
2295
+ event.preventDefault();
2296
+ this.seriesDragMoved = false;
2297
+ return;
2298
+ }
2299
+ if (!event.ctrlKey && !event.metaKey) {
2300
+ return;
2301
+ }
2302
+ if (!this.series().draggablePath) {
2303
+ return;
2304
+ }
2305
+ event.stopPropagation();
2306
+ event.preventDefault();
2307
+ this.svc.toggleSelectedSeriesId(this.series().id);
2308
+ }
2100
2309
  moveStart(event, point) {
2101
2310
  this.start = { x: point.x, y: point.y };
2102
2311
  }
@@ -2139,12 +2348,105 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
2139
2348
  label.dx = this.labelStart.dx + event.deltaX;
2140
2349
  label.dy = this.labelStart.dy + event.deltaY;
2141
2350
  }
2351
+ emitSeriesMove(type, event) {
2352
+ const offsetValue = this.seriesOffsetValue();
2353
+ const seriesList = this.seriesDragGroup.length ? this.seriesDragGroup : [this.series()];
2354
+ this.svc.emitSeriesMove({
2355
+ event: {
2356
+ type,
2357
+ sourceEvent: event,
2358
+ },
2359
+ target: {
2360
+ series: this.series(),
2361
+ seriesList,
2362
+ seriesIds: seriesList.map((series) => series.id),
2363
+ offsets: seriesList.map((series) => {
2364
+ const seriesOffsetValue = this.svc.getSeriesPathOffsets().get(series.id) ?? { x: 0, y: 0 };
2365
+ return {
2366
+ series,
2367
+ seriesId: series.id,
2368
+ offsetPx: {
2369
+ x: this.getOffsetPixels(this.x(), seriesOffsetValue.x),
2370
+ y: this.getOffsetPixels(this.y(), seriesOffsetValue.y),
2371
+ },
2372
+ offsetValue: seriesOffsetValue,
2373
+ };
2374
+ }),
2375
+ offsetPx: {
2376
+ x: this.getOffsetPixels(this.x(), offsetValue.x),
2377
+ y: this.getOffsetPixels(this.y(), offsetValue.y),
2378
+ },
2379
+ offsetValue: {
2380
+ x: offsetValue.x,
2381
+ y: offsetValue.y,
2382
+ },
2383
+ },
2384
+ });
2385
+ }
2386
+ updateSeriesOffset(event) {
2387
+ const dragOffset = {
2388
+ x: this.getScaleOffset(this.x(), event.deltaX),
2389
+ y: this.getScaleOffset(this.y(), event.deltaY),
2390
+ };
2391
+ const offsets = new Map(this.svc.getSeriesPathOffsets());
2392
+ const seriesList = this.seriesDragGroup.length ? this.seriesDragGroup : [this.series()];
2393
+ seriesList.forEach((series) => {
2394
+ const startOffset = this.seriesDragStartOffsets.get(series.id) ?? { x: 0, y: 0 };
2395
+ offsets.set(series.id, {
2396
+ x: startOffset.x + dragOffset.x,
2397
+ y: startOffset.y + dragOffset.y,
2398
+ });
2399
+ });
2400
+ this.svc.setSeriesPathOffsets(offsets);
2401
+ }
2402
+ getScaleOffset(scale, offsetPx) {
2403
+ if (!scale?.invert || !scale?.domain) {
2404
+ return 0;
2405
+ }
2406
+ const [domainStart] = scale.domain();
2407
+ const startValue = domainStart instanceof Date ? domainStart.getTime() : domainStart;
2408
+ const nextValue = scale.invert(scale(domainStart) + offsetPx);
2409
+ const normalizedNextValue = nextValue instanceof Date ? nextValue.getTime() : nextValue;
2410
+ return normalizedNextValue - startValue;
2411
+ }
2412
+ getClipOffset() {
2413
+ return this.seriesOffsetValue();
2414
+ }
2415
+ getPathDragSeriesGroup() {
2416
+ const currentSeries = this.series();
2417
+ if (!this.isSeriesSelectedForPathDrag(currentSeries)) {
2418
+ return [currentSeries];
2419
+ }
2420
+ const selectedIds = this.svc.getSelectedSeriesIds();
2421
+ const selectedSeries = this.config()?.series?.filter((series) => {
2422
+ return (selectedIds.includes(series.id) &&
2423
+ series.draggablePath &&
2424
+ series.visible !== false &&
2425
+ series.enabled !== false &&
2426
+ series.pathDragType === currentSeries.pathDragType &&
2427
+ ((currentSeries.pathDragType === DragPointType.x && series.xAxisIndex === currentSeries.xAxisIndex) ||
2428
+ (currentSeries.pathDragType === DragPointType.y && series.yAxisIndex === currentSeries.yAxisIndex)));
2429
+ });
2430
+ return selectedSeries?.length ? selectedSeries : [currentSeries];
2431
+ }
2432
+ isSeriesSelectedForPathDrag(series) {
2433
+ return this.selectedSeriesIds().includes(series.id);
2434
+ }
2435
+ getOffsetPixels(scale, offsetValue) {
2436
+ if (!scale || !scale?.domain || offsetValue === null || offsetValue === undefined) {
2437
+ return 0;
2438
+ }
2439
+ const [domainStart] = scale.domain();
2440
+ const startValue = domainStart instanceof Date ? domainStart.getTime() : domainStart;
2441
+ const nextValue = domainStart instanceof Date ? new Date(startValue + offsetValue) : startValue + offsetValue;
2442
+ return scale(nextValue) - scale(domainStart);
2443
+ }
2142
2444
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2143
- 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:path\n class=\"line\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n fill=\"none\"\n ></svg:path>\n @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 @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 [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 <svg:circle 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\"></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line [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\"></svg:line>\n <svg:foreignObject [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 <div #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 {{ 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}.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
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 }); }
2144
2446
  }
2145
2447
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, decorators: [{
2146
2448
  type: Component,
2147
- args: [{ selector: 'svg:svg[teta-line-series]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AsyncPipe, DraggablePointDirective], template: "@if (series(); as series) {\n <svg:path\n class=\"line\"\n [attr.d]=\"path()\"\n [attr.stroke]=\"series.color\"\n [attr.stroke-dasharray]=\"series.style?.strokeDasharray\"\n [attr.stroke-width]=\"series.style?.strokeWidth\"\n fill=\"none\"\n ></svg:path>\n @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 @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 [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 <svg:circle 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\"></svg:circle>\n @if (point.marker.label?.text) {\n <svg:line [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\"></svg:line>\n <svg:foreignObject [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 <div #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 {{ 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}.active{stroke-opacity:.5}.marker-grab{opacity:0}\n"] }]
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"] }]
2148
2450
  }] });
2149
2451
 
2150
2452
  class BarSeriesComponent extends SeriesBaseComponent {
@@ -3005,6 +3307,9 @@ class ChartComponent {
3005
3307
  this.chartService.setConfig(config);
3006
3308
  this.zoomService.setBroadcastChannel(config?.zoom?.syncChannel);
3007
3309
  }
3310
+ set selectedSeriesIds(seriesIds) {
3311
+ this.chartService.setSelectedSeriesIds(seriesIds ?? []);
3312
+ }
3008
3313
  constructor(chartService, zoomService, brushService, scaleService) {
3009
3314
  this.chartService = chartService;
3010
3315
  this.zoomService = zoomService;
@@ -3016,6 +3321,8 @@ class ChartComponent {
3016
3321
  this.plotBandContextMenu = new EventEmitter();
3017
3322
  this.plotLinesMove = new EventEmitter();
3018
3323
  this.pointMove = new EventEmitter();
3324
+ this.seriesMove = new EventEmitter();
3325
+ this.selectedSeriesIdsChange = new EventEmitter();
3019
3326
  this.chartClick = new EventEmitter();
3020
3327
  this.chartContextMenu = new EventEmitter();
3021
3328
  this.annotationContextMenu = new EventEmitter();
@@ -3075,6 +3382,14 @@ class ChartComponent {
3075
3382
  this.chartService.pointMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
3076
3383
  this.pointMove.emit(_);
3077
3384
  });
3385
+ this.chartService.seriesMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
3386
+ this.seriesMove.emit(_);
3387
+ });
3388
+ this.chartService.selectedSeriesIds
3389
+ .pipe(takeWhile(() => this._alive), distinctUntilChanged((prev, next) => this.areSeriesIdsEqual(prev, next)))
3390
+ .subscribe((_) => {
3391
+ this.selectedSeriesIdsChange.emit(_);
3392
+ });
3078
3393
  this.chartService.chartClick.pipe(takeWhile(() => this._alive)).subscribe((_) => {
3079
3394
  this.chartClick.emit(_);
3080
3395
  });
@@ -3103,8 +3418,11 @@ class ChartComponent {
3103
3418
  ngOnDestroy() {
3104
3419
  this._alive = false;
3105
3420
  }
3421
+ areSeriesIdsEqual(first, second) {
3422
+ return first.length === second.length && first.every((id, index) => id === second[index]);
3423
+ }
3106
3424
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ChartComponent, deps: [{ token: ChartService }, { token: ZoomService }, { token: BrushService }, { token: ScaleService }], target: i0.ɵɵFactoryTarget.Component }); }
3107
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ChartComponent, isStandalone: true, selector: "teta-svg-chart", inputs: { config: "config" }, outputs: { pointerMove: "pointerMove", plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", chartClick: "chartClick", chartContextMenu: "chartContextMenu", annotationContextMenu: "annotationContextMenu", annotationClick: "annotationClick", annotationMove: "annotationMove", zoomServiceInstance: "zoomServiceInstance", brushServiceInstance: "brushServiceInstance", configUpdated: "configUpdated" }, providers: [ChartService, ZoomService, ScaleService, BrushService], ngImport: i0, template: "@if ({ hasSeriesData: hasSeriesData | async, svcConfig: svcConfig | async }; as data) {\n @if (data.hasSeriesData === true) {\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container position-relative\"></teta-chart-container>\n </div>\n @if (data.svcConfig.legend?.enable === true) {\n <teta-legend [series]=\"data.svcConfig.series\"></teta-legend>\n }\n } @else {\n <div class=\"column column_auto justify-content-center\">\n <span class=\"font-body-3 color-text-40 overflow-hidden text-overflow-ellipsis nowrap text-align-center\">\n <div #ref><ng-content></ng-content></div>\n @if (!ref.hasChildNodes()) {\n <span> No data </span>\n }\n </span>\n </div>\n }\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "component", type: ChartContainerComponent, selector: "teta-chart-container" }, { kind: "component", type: LegendComponent, selector: "teta-legend", inputs: ["series"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3425
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ChartComponent, isStandalone: true, selector: "teta-svg-chart", inputs: { config: "config", selectedSeriesIds: "selectedSeriesIds" }, outputs: { pointerMove: "pointerMove", plotBandsMove: "plotBandsMove", plotBandClick: "plotBandClick", plotBandContextMenu: "plotBandContextMenu", plotLinesMove: "plotLinesMove", pointMove: "pointMove", seriesMove: "seriesMove", selectedSeriesIdsChange: "selectedSeriesIdsChange", chartClick: "chartClick", chartContextMenu: "chartContextMenu", annotationContextMenu: "annotationContextMenu", annotationClick: "annotationClick", annotationMove: "annotationMove", zoomServiceInstance: "zoomServiceInstance", brushServiceInstance: "brushServiceInstance", configUpdated: "configUpdated" }, providers: [ChartService, ZoomService, ScaleService, BrushService], ngImport: i0, template: "@if ({ hasSeriesData: hasSeriesData | async, svcConfig: svcConfig | async }; as data) {\n @if (data.hasSeriesData === true) {\n <div class=\"column column_auto\">\n <teta-chart-container class=\"chart-container position-relative\"></teta-chart-container>\n </div>\n @if (data.svcConfig.legend?.enable === true) {\n <teta-legend [series]=\"data.svcConfig.series\"></teta-legend>\n }\n } @else {\n <div class=\"column column_auto justify-content-center\">\n <span class=\"font-body-3 color-text-40 overflow-hidden text-overflow-ellipsis nowrap text-align-center\">\n <div #ref><ng-content></ng-content></div>\n @if (!ref.hasChildNodes()) {\n <span> No data </span>\n }\n </span>\n </div>\n }\n}\n", styles: [":host{position:relative;display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "component", type: ChartContainerComponent, selector: "teta-chart-container" }, { kind: "component", type: LegendComponent, selector: "teta-legend", inputs: ["series"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3108
3426
  }
3109
3427
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ChartComponent, decorators: [{
3110
3428
  type: Component,
@@ -3121,6 +3439,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3121
3439
  type: Output
3122
3440
  }], pointMove: [{
3123
3441
  type: Output
3442
+ }], seriesMove: [{
3443
+ type: Output
3444
+ }], selectedSeriesIdsChange: [{
3445
+ type: Output
3124
3446
  }], chartClick: [{
3125
3447
  type: Output
3126
3448
  }], chartContextMenu: [{
@@ -3139,6 +3461,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3139
3461
  type: Output
3140
3462
  }], config: [{
3141
3463
  type: Input
3464
+ }], selectedSeriesIds: [{
3465
+ type: Input
3142
3466
  }] } });
3143
3467
 
3144
3468
  class PlotBand {