@tetacom/svg-charts 1.7.37 → 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,8 +193,9 @@ class ChartService {
|
|
|
193
193
|
this.plotBandEvent$ = new Subject();
|
|
194
194
|
this.plotLineMove$ = new Subject();
|
|
195
195
|
this.pointMove$ = new Subject();
|
|
196
|
-
this.
|
|
196
|
+
this.seriesMove$ = new Subject();
|
|
197
197
|
this.seriesPathOffsets$ = new BehaviorSubject(new Map());
|
|
198
|
+
this.selectedSeriesIds$ = new BehaviorSubject([]);
|
|
198
199
|
this.chartClick$ = new Subject();
|
|
199
200
|
this.chartContextMenu$ = new Subject();
|
|
200
201
|
this.annotationEvent$ = new Subject();
|
|
@@ -218,8 +219,9 @@ class ChartService {
|
|
|
218
219
|
this.plotBandEvent = this.plotBandEvent$.asObservable();
|
|
219
220
|
this.plotLineMove = this.plotLineMove$.asObservable();
|
|
220
221
|
this.pointMove = this.pointMove$.asObservable();
|
|
221
|
-
this.
|
|
222
|
+
this.seriesMove = this.seriesMove$.asObservable();
|
|
222
223
|
this.seriesPathOffsets = this.seriesPathOffsets$.asObservable();
|
|
224
|
+
this.selectedSeriesIds = this.selectedSeriesIds$.asObservable();
|
|
223
225
|
this.chartClick = this.chartClick$.asObservable();
|
|
224
226
|
this.chartContextMenu = this.chartContextMenu$.asObservable();
|
|
225
227
|
this.annotationClick = this.annotationEvent$.asObservable().pipe(filter((_) => _?.event?.type === 'click'));
|
|
@@ -235,6 +237,7 @@ class ChartService {
|
|
|
235
237
|
}
|
|
236
238
|
setConfig(config) {
|
|
237
239
|
this.clearTooltips();
|
|
240
|
+
this.clearSeriesPathOffsets();
|
|
238
241
|
this.config$.next(config);
|
|
239
242
|
}
|
|
240
243
|
setSize(size) {
|
|
@@ -297,8 +300,8 @@ class ChartService {
|
|
|
297
300
|
emitPoint(event) {
|
|
298
301
|
this.pointMove$.next(event);
|
|
299
302
|
}
|
|
300
|
-
|
|
301
|
-
this.
|
|
303
|
+
emitSeriesMove(event) {
|
|
304
|
+
this.seriesMove$.next(event);
|
|
302
305
|
}
|
|
303
306
|
getSeriesPathOffsets() {
|
|
304
307
|
return this.seriesPathOffsets$.value;
|
|
@@ -306,6 +309,30 @@ class ChartService {
|
|
|
306
309
|
setSeriesPathOffsets(offsets) {
|
|
307
310
|
this.seriesPathOffsets$.next(new Map(offsets));
|
|
308
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
|
+
}
|
|
309
336
|
emitChartClick(event) {
|
|
310
337
|
this.chartClick$.next(event);
|
|
311
338
|
}
|
|
@@ -1842,6 +1869,13 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
|
|
|
1842
1869
|
}
|
|
1843
1870
|
const mouse = [event?.offsetX, event?.offsetY];
|
|
1844
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
|
+
};
|
|
1845
1879
|
const lineIntersection = (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) => {
|
|
1846
1880
|
const rV = {};
|
|
1847
1881
|
const s1_x = p1_x - p0_x;
|
|
@@ -1864,9 +1898,10 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
|
|
|
1864
1898
|
if (x0 instanceof Date) {
|
|
1865
1899
|
x0 = x0.getTime();
|
|
1866
1900
|
}
|
|
1901
|
+
x0 = subtractOffset(x0, clipOffset.x);
|
|
1867
1902
|
const rightId = bisect([...this.series().data].sort((a, b) => a.x - b.x), x0);
|
|
1868
1903
|
const range = scaleY.range();
|
|
1869
|
-
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)));
|
|
1870
1905
|
const x = scaleX.invert(intersect.x);
|
|
1871
1906
|
const y = scaleY.invert(intersect.y);
|
|
1872
1907
|
if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
|
|
@@ -1896,9 +1931,10 @@ class LinearSeriesBaseComponent extends SeriesBaseComponent {
|
|
|
1896
1931
|
if (y0 instanceof Date) {
|
|
1897
1932
|
y0 = y0.getTime();
|
|
1898
1933
|
}
|
|
1934
|
+
y0 = subtractOffset(y0, clipOffset.y);
|
|
1899
1935
|
const rightId = bisect(sortedData, y0);
|
|
1900
1936
|
const range = scaleX.range();
|
|
1901
|
-
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)));
|
|
1902
1938
|
const x = scaleX.invert(intersect.x);
|
|
1903
1939
|
const y = scaleY.invert(intersect.y);
|
|
1904
1940
|
if (x !== null && x !== undefined && !isNaN(x) && y !== null && y !== undefined && !isNaN(y)) {
|
|
@@ -2191,12 +2227,16 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2191
2227
|
constructor() {
|
|
2192
2228
|
super(...arguments);
|
|
2193
2229
|
this.seriesPathOffsets = toSignal(this.svc.seriesPathOffsets, { initialValue: new Map() });
|
|
2230
|
+
this.selectedSeriesIds = toSignal(this.svc.selectedSeriesIds, { initialValue: [] });
|
|
2194
2231
|
this.seriesDragStartOffsets = new Map();
|
|
2195
2232
|
this.seriesDragGroup = [];
|
|
2196
2233
|
this.seriesDragMoved = false;
|
|
2197
2234
|
this.seriesOffsetValue = computed(() => {
|
|
2198
2235
|
return this.seriesPathOffsets().get(this.series().id) ?? { x: 0, y: 0 };
|
|
2199
2236
|
}, ...(ngDevMode ? [{ debugName: "seriesOffsetValue" }] : /* istanbul ignore next */ []));
|
|
2237
|
+
this.seriesSelectedForPathDrag = computed(() => {
|
|
2238
|
+
return this.isSeriesSelectedForPathDrag(this.series());
|
|
2239
|
+
}, ...(ngDevMode ? [{ debugName: "seriesSelectedForPathDrag" }] : /* istanbul ignore next */ []));
|
|
2200
2240
|
this.seriesPathTransform = computed(() => {
|
|
2201
2241
|
const offset = this.seriesOffsetValue();
|
|
2202
2242
|
const offsetX = this.getOffsetPixels(this.x(), offset.x);
|
|
@@ -2238,16 +2278,16 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2238
2278
|
this.seriesDragStartOffsets = new Map(this.seriesDragGroup.map((series) => {
|
|
2239
2279
|
return [series.id, this.svc.getSeriesPathOffsets().get(series.id) ?? { x: 0, y: 0 }];
|
|
2240
2280
|
}));
|
|
2241
|
-
this.
|
|
2281
|
+
this.emitSeriesMove('start', event);
|
|
2242
2282
|
}
|
|
2243
2283
|
seriesMoveProcess(event) {
|
|
2244
2284
|
this.seriesDragMoved = this.seriesDragMoved || Math.abs(event.deltaX) > 3 || Math.abs(event.deltaY) > 3;
|
|
2245
2285
|
this.updateSeriesOffset(event);
|
|
2246
|
-
this.
|
|
2286
|
+
this.emitSeriesMove('drag', event);
|
|
2247
2287
|
}
|
|
2248
2288
|
seriesMoveEnd(event) {
|
|
2249
2289
|
this.updateSeriesOffset(event);
|
|
2250
|
-
this.
|
|
2290
|
+
this.emitSeriesMove('end', event);
|
|
2251
2291
|
}
|
|
2252
2292
|
seriesPathClick(event) {
|
|
2253
2293
|
if (this.seriesDragMoved) {
|
|
@@ -2264,8 +2304,7 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2264
2304
|
}
|
|
2265
2305
|
event.stopPropagation();
|
|
2266
2306
|
event.preventDefault();
|
|
2267
|
-
this.
|
|
2268
|
-
this.cdr.markForCheck();
|
|
2307
|
+
this.svc.toggleSelectedSeriesId(this.series().id);
|
|
2269
2308
|
}
|
|
2270
2309
|
moveStart(event, point) {
|
|
2271
2310
|
this.start = { x: point.x, y: point.y };
|
|
@@ -2309,10 +2348,10 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2309
2348
|
label.dx = this.labelStart.dx + event.deltaX;
|
|
2310
2349
|
label.dy = this.labelStart.dy + event.deltaY;
|
|
2311
2350
|
}
|
|
2312
|
-
|
|
2351
|
+
emitSeriesMove(type, event) {
|
|
2313
2352
|
const offsetValue = this.seriesOffsetValue();
|
|
2314
2353
|
const seriesList = this.seriesDragGroup.length ? this.seriesDragGroup : [this.series()];
|
|
2315
|
-
this.svc.
|
|
2354
|
+
this.svc.emitSeriesMove({
|
|
2316
2355
|
event: {
|
|
2317
2356
|
type,
|
|
2318
2357
|
sourceEvent: event,
|
|
@@ -2375,19 +2414,24 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2375
2414
|
}
|
|
2376
2415
|
getPathDragSeriesGroup() {
|
|
2377
2416
|
const currentSeries = this.series();
|
|
2378
|
-
if (!currentSeries
|
|
2417
|
+
if (!this.isSeriesSelectedForPathDrag(currentSeries)) {
|
|
2379
2418
|
return [currentSeries];
|
|
2380
2419
|
}
|
|
2420
|
+
const selectedIds = this.svc.getSelectedSeriesIds();
|
|
2381
2421
|
const selectedSeries = this.config()?.series?.filter((series) => {
|
|
2382
|
-
return (series.
|
|
2422
|
+
return (selectedIds.includes(series.id) &&
|
|
2383
2423
|
series.draggablePath &&
|
|
2384
2424
|
series.visible !== false &&
|
|
2385
2425
|
series.enabled !== false &&
|
|
2386
|
-
series.
|
|
2387
|
-
series.
|
|
2426
|
+
series.pathDragType === currentSeries.pathDragType &&
|
|
2427
|
+
((currentSeries.pathDragType === DragPointType.x && series.xAxisIndex === currentSeries.xAxisIndex) ||
|
|
2428
|
+
(currentSeries.pathDragType === DragPointType.y && series.yAxisIndex === currentSeries.yAxisIndex)));
|
|
2388
2429
|
});
|
|
2389
2430
|
return selectedSeries?.length ? selectedSeries : [currentSeries];
|
|
2390
2431
|
}
|
|
2432
|
+
isSeriesSelectedForPathDrag(series) {
|
|
2433
|
+
return this.selectedSeriesIds().includes(series.id);
|
|
2434
|
+
}
|
|
2391
2435
|
getOffsetPixels(scale, offsetValue) {
|
|
2392
2436
|
if (!scale || !scale?.domain || offsetValue === null || offsetValue === undefined) {
|
|
2393
2437
|
return 0;
|
|
@@ -2398,11 +2442,11 @@ class LineSeriesComponent extends LinearSeriesBaseComponent {
|
|
|
2398
2442
|
return scale(nextValue) - scale(domainStart);
|
|
2399
2443
|
}
|
|
2400
2444
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2401
|
-
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]=\"
|
|
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 }); }
|
|
2402
2446
|
}
|
|
2403
2447
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LineSeriesComponent, decorators: [{
|
|
2404
2448
|
type: Component,
|
|
2405
|
-
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]=\"
|
|
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"] }]
|
|
2406
2450
|
}] });
|
|
2407
2451
|
|
|
2408
2452
|
class BarSeriesComponent extends SeriesBaseComponent {
|
|
@@ -3263,6 +3307,9 @@ class ChartComponent {
|
|
|
3263
3307
|
this.chartService.setConfig(config);
|
|
3264
3308
|
this.zoomService.setBroadcastChannel(config?.zoom?.syncChannel);
|
|
3265
3309
|
}
|
|
3310
|
+
set selectedSeriesIds(seriesIds) {
|
|
3311
|
+
this.chartService.setSelectedSeriesIds(seriesIds ?? []);
|
|
3312
|
+
}
|
|
3266
3313
|
constructor(chartService, zoomService, brushService, scaleService) {
|
|
3267
3314
|
this.chartService = chartService;
|
|
3268
3315
|
this.zoomService = zoomService;
|
|
@@ -3274,7 +3321,8 @@ class ChartComponent {
|
|
|
3274
3321
|
this.plotBandContextMenu = new EventEmitter();
|
|
3275
3322
|
this.plotLinesMove = new EventEmitter();
|
|
3276
3323
|
this.pointMove = new EventEmitter();
|
|
3277
|
-
this.
|
|
3324
|
+
this.seriesMove = new EventEmitter();
|
|
3325
|
+
this.selectedSeriesIdsChange = new EventEmitter();
|
|
3278
3326
|
this.chartClick = new EventEmitter();
|
|
3279
3327
|
this.chartContextMenu = new EventEmitter();
|
|
3280
3328
|
this.annotationContextMenu = new EventEmitter();
|
|
@@ -3334,8 +3382,13 @@ class ChartComponent {
|
|
|
3334
3382
|
this.chartService.pointMove.pipe(takeWhile(() => this._alive)).subscribe((_) => {
|
|
3335
3383
|
this.pointMove.emit(_);
|
|
3336
3384
|
});
|
|
3337
|
-
this.chartService.
|
|
3338
|
-
this.
|
|
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(_);
|
|
3339
3392
|
});
|
|
3340
3393
|
this.chartService.chartClick.pipe(takeWhile(() => this._alive)).subscribe((_) => {
|
|
3341
3394
|
this.chartClick.emit(_);
|
|
@@ -3365,8 +3418,11 @@ class ChartComponent {
|
|
|
3365
3418
|
ngOnDestroy() {
|
|
3366
3419
|
this._alive = false;
|
|
3367
3420
|
}
|
|
3421
|
+
areSeriesIdsEqual(first, second) {
|
|
3422
|
+
return first.length === second.length && first.every((id, index) => id === second[index]);
|
|
3423
|
+
}
|
|
3368
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 }); }
|
|
3369
|
-
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",
|
|
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 }); }
|
|
3370
3426
|
}
|
|
3371
3427
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ChartComponent, decorators: [{
|
|
3372
3428
|
type: Component,
|
|
@@ -3383,7 +3439,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3383
3439
|
type: Output
|
|
3384
3440
|
}], pointMove: [{
|
|
3385
3441
|
type: Output
|
|
3386
|
-
}],
|
|
3442
|
+
}], seriesMove: [{
|
|
3443
|
+
type: Output
|
|
3444
|
+
}], selectedSeriesIdsChange: [{
|
|
3387
3445
|
type: Output
|
|
3388
3446
|
}], chartClick: [{
|
|
3389
3447
|
type: Output
|
|
@@ -3403,6 +3461,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3403
3461
|
type: Output
|
|
3404
3462
|
}], config: [{
|
|
3405
3463
|
type: Input
|
|
3464
|
+
}], selectedSeriesIds: [{
|
|
3465
|
+
type: Input
|
|
3406
3466
|
}] } });
|
|
3407
3467
|
|
|
3408
3468
|
class PlotBand {
|