simulate chart toolbar actions ...

This commit is contained in:
2026-08-24 09:15:11 +03:30
parent 78f1ae00aa
commit 398f098b8b
2 changed files with 501 additions and 214 deletions
@@ -2,8 +2,8 @@ import {
Component, Component,
ViewChild, ViewChild,
ElementRef, ElementRef,
ChangeDetectionStrategy,
HostListener, HostListener,
ChangeDetectionStrategy,
} from '@angular/core'; } from '@angular/core';
import { import {
nameof, nameof,
@@ -122,6 +122,40 @@ export class XChartComponent extends XChartContainerComponent {
this.registerActionProvider(); this.registerActionProvider();
} }
//
// Available Action Bar Items Changed ...
const isAvailableActionBarItemsChanged = changeKeys.includes(
nameof<XChartComponent>('availableActionBarItems')
);
if (isAvailableActionBarItemsChanged) {
//
if (isNullOrUndefined(this.availableActionBarItems)) {
this.availableActionBarItems = this.propertyProvider.availableActionBarItems;
}
//
await this.prepareActionBar();
}
//
// Zoom Step ...
const isZoomStepChanged = changeKeys.includes(
nameof<XChartComponent>('zoomStep')
);
if (isZoomStepChanged) {
//
let zoomStep = await this.getValueAsync(this.zoomStep);
if (isNullOrUndefined(zoomStep) ||
zoomStep < 0 ||
zoomStep > 1
) {
this.zoomStep = 0.125;
}
//
zoomStep = await this.getValueAsync(this.zoomStep);
}
// //
// Check Auto Update ... // Check Auto Update ...
var autoUpdate = await this.getValueAsync(this.autoUpdate); var autoUpdate = await this.getValueAsync(this.autoUpdate);
@@ -207,47 +241,82 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
switch ( switch (model.action) {
model.action
// //
// case this.ActionBarItems.ChangeMode: // Print ...
// this.handleActionModeFired(model.event); case XChartActionBarItem.Print:
// break; await this.handlePrint();
break;
// // //
// case this.ActionBarItems.ChangeTheme: // Export As CSV ...
// this.handleActionThemFired(model.event); case XChartActionBarItem.ExportAsCSV:
// break; await this.handleExportAsCSV();
break;
// // //
// case this.ActionBarItems.Close: // Export As PNG ...
// this.closeTab(this.currentTab); case XChartActionBarItem.ExportAsPNG:
// break; await this.handleExportAsPng();
break;
// // //
// case this.ActionBarItems.Undo: // Export As SVG ...
// this.undo(); case XChartActionBarItem.ExportAsSVG:
// break; await this.handleExportAsSVG();
break;
// // //
// case this.ActionBarItems.Redo: // Zoom In ...
// this.redo(); case XChartActionBarItem.ZoomIn:
// break; await this.handleZoomIn();
break;
// // //
// case this.ActionBarItems.Beautify: // Zoom Out ...
// await this.beautifyCode(); case XChartActionBarItem.ZoomOut:
// break; await this.handleZoomOut();
break;
// // //
// case this.ActionBarItems.Save: // Zoom Selection ...
// // case XChartActionBarItem.ZoomSelection:
// this.updateCurrentTabDescriptor({ break;
// canSave: false,
// }); //
// this.prepareActionBar(); // X Selection ...
// break; case XChartActionBarItem.XSelection:
) { break;
//
// Y Selection ...
case XChartActionBarItem.YSelection:
break;
//
// XY Selection ...
case XChartActionBarItem.XYSelection:
break;
//
// Pan ...
case XChartActionBarItem.Pan:
await this.handlePan();
break;
//
// ResetChart ...
case XChartActionBarItem.ResetChart:
await this.handleResetChart();
break;
//
// ToggleFullScreen ...
case XChartActionBarItem.ToggleFullScreen:
await this.handleToggleFullscreen();
break;
//
} }
// //
@@ -308,6 +377,222 @@ export class XChartComponent extends XChartContainerComponent {
} }
//#endregion //#endregion
//
//#region Toolbar Actions ...
async handleExportAsPng() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
await this.export('png');
}
async handleExportAsSVG() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
await this.export('svg');
}
async handleExportAsCSV() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
await this.export('csv');
}
async handleZoomIn() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
var zoomStep = await this.getValueAsync(this.zoomStep);
//
const state = this.chartInstance.getState();
const minX = state.minX;
const maxX = state.maxX;
const rangeIn = maxX - minX;
//
await this.chartInstance.zoomX(minX + rangeIn * zoomStep, maxX - rangeIn * zoomStep);
}
async handleZoomOut() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
var zoomStep = await this.getValueAsync(this.zoomStep);
//
const state = this.chartInstance.getState();
const minX = state.minX;
const maxX = state.maxX;
const rangeIn = maxX - minX;
//
await this.chartInstance.zoomX(minX - rangeIn * zoomStep, maxX + rangeIn * zoomStep);
}
async handlePan() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
await this.chartInstance.updateOptions({
chart: {
zoom: {
enabled: false
},
selection: {
type: 'x',
enabled: true,
},
}
});
}
async handleResetChart() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
this.chartInstance.resetSeries(true, true);
}
async handlePrint() {
//
if (isNullOrUndefined(this.chartInstance)) {
return;
}
//
try {
//
const result = await this.chartInstance.dataURI();
if ('imgURI' in result) {
//
const imgURI = result.imgURI;
const printWindow = window.open('', '_blank');
if (printWindow) {
//
// Write Data Uri on a Page for Printing ...
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>Print Chart</title>
<style>
body {
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
img {
max-width: 100%;
height: auto;
}
@media print {
body {
margin: 0;
}
img {
max-width: 100%;
page-break-inside: avoid;
}
}
</style>
</head>
<body>
<img src="${imgURI}" alt="Chart" />
<script>
window.onload = function() {
window.print();
window.onafterprint = function() {
window.close();
};
};
</script>
</body>
</html>
`);
//
printWindow.document.close();
}
}
} catch (error) {
}
}
async handleToggleFullscreen() {
//
if (isNullOrUndefined(this.chartInstance) ||
isNullOrUndefined(this.chartContainer) ||
isNullOrUndefined(this.chartContainer.nativeElement)
) {
return;
}
//
const chartWrapper = this.chartContainer.nativeElement;
const doc = document as any;
//
// Check if the chart wrapper is currently in fullscreen mode
const isFullscreen =
doc.fullscreenElement === chartWrapper ||
doc.msFullscreenElement === chartWrapper ||
doc.mozFullScreenElement === chartWrapper ||
doc.webkitFullscreenElement === chartWrapper;
if (!isFullscreen) {
//
// Enter Fullscreen
if (chartWrapper.requestFullscreen) {
await chartWrapper.requestFullscreen();
} else if (chartWrapper.webkitRequestFullscreen) {
await chartWrapper.webkitRequestFullscreen();
} else if (chartWrapper.mozRequestFullScreen) {
await chartWrapper.mozRequestFullScreen();
} else if (chartWrapper.msRequestFullscreen) {
await chartWrapper.msRequestFullscreen();
}
} else {
//
// Exit Fullscreen
if (doc.exitFullscreen) {
await doc.exitFullscreen();
} else if (doc.webkitExitFullscreen) {
await doc.webkitExitFullscreen();
} else if (doc.mozCancelFullScreen) {
await doc.mozCancelFullScreen();
} else if (doc.msExitFullscreen) {
await doc.msExitFullscreen();
}
}
}
//#endregion
// //
//#region Private ... //#region Private ...
private async initializeComponent() { private async initializeComponent() {
@@ -22,27 +22,26 @@ import {
XCardActionModel, XCardActionModel,
XComponentCardContainer, XComponentCardContainer,
IXComponentCardContainer, IXComponentCardContainer,
XComponentCardContainerComponent,
} from '../x-card/x-card.typings'; } from '../x-card/x-card.typings';
import { concatMap, map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import {
XBaseContainer,
XBaseContainerComponent,
} from '../classes/i-x-base.container';
import {
XActionBarItem,
XActionBarActionModel,
XActionBarActionFiredModel,
XComponentActionBarContainer,
IXComponentActionBarContainer,
} from '../x-action-bar/x-action-bar.typings';
import { forkJoin, Observable, Subject } from 'rxjs'; import { forkJoin, Observable, Subject } from 'rxjs';
import { ViewportRuler } from '@angular/cdk/overlay'; import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services'; import { XManagerService } from 'x-framework-services';
import { XBaseActionModel } from '../classes/x-base-action.model'; import { XBaseActionModel } from '../classes/x-base-action.model';
import { X_FRAMEWORK_COMPONENTS_CONFIG } from '../tokens/x-injectable-tokens'; import { X_FRAMEWORK_COMPONENTS_CONFIG } from '../tokens/x-injectable-tokens';
import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
import {
IXComponentActionBarContainer,
XActionBarActionFiredModel,
XActionBarActionModel,
XActionBarItem,
XComponentActionBarContainer,
} from '../x-action-bar/x-action-bar.typings';
import { XPopoverPresentOptions } from '../dialogs/x-popover/x-popover.typings'; import { XPopoverPresentOptions } from '../dialogs/x-popover/x-popover.typings';
import { import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
XBaseContainer,
XBaseContainerComponent,
} from '../classes/i-x-base.container';
// //
//#region Chart ... //#region Chart ...
@@ -371,71 +370,71 @@ export type XChartAxisChartSeries = {
zIndex?: number; zIndex?: number;
parsing?: XChartParsing; parsing?: XChartParsing;
data: data:
| (number | null)[] | (number | null)[]
| { | {
/** /**
* A category label, a timestamp, or a `Date`. On a `datetime` axis all * A category label, a timestamp, or a `Date`. On a `datetime` axis all
* three keep millisecond resolution. * three keep millisecond resolution.
*/ */
x: string | number | Date; x: string | number | Date;
/** /**
* A plain value for most charts. For `candlestick`/`boxPlot`, the * A plain value for most charts. For `candlestick`/`boxPlot`, the
* summary array (`[O,H,L,C]` / `[min,Q1,median,Q3,max]`). For `violin`, an * summary array (`[O,H,L,C]` / `[min,Q1,median,Q3,max]`). For `violin`, an
* object carrying the precomputed density profile (`[value, weight]` pairs) * object carrying the precomputed density profile (`[value, weight]` pairs)
* plus the raw observations rendered as jitter. For a `scatter` strip plot * plus the raw observations rendered as jitter. For a `scatter` strip plot
* (`plotOptions.scatter.jitter`), the array of observations in this category. * (`plotOptions.scatter.jitter`), the array of observations in this category.
*/ */
y: y:
| number | number
| null | null
| number[] | number[]
| { density: [number, number][]; points?: number[] }; | { density: [number, number][]; points?: number[] };
/** /**
* Optional raw observations for a `boxPlot` data point, rendered as jitter * Optional raw observations for a `boxPlot` data point, rendered as jitter
* dots when `plotOptions.boxPlot.points.show` is enabled. * dots when `plotOptions.boxPlot.points.show` is enabled.
*/ */
points?: number[]; points?: number[];
fill?: XChartFill; fill?: XChartFill;
fillColor?: string; fillColor?: string;
strokeColor?: string; strokeColor?: string;
meta?: unknown; meta?: unknown;
/** /**
* A second metric that drives this point's COLOUR, independent of `y` * A second metric that drives this point's COLOUR, independent of `y`
* which drives its size (`treemap`). See * which drives its size (`treemap`). See
* `plotOptions.treemap.colorScale.colorValue` to read a different key. * `plotOptions.treemap.colorScale.colorValue` to read a different key.
*/ */
colorValue?: number; colorValue?: number;
/** /**
* Nested hierarchy: this point is a branch containing these children, * Nested hierarchy: this point is a branch containing these children,
* to any depth (`treemap`, `sunburst`). A branch normally omits `y` and * to any depth (`treemap`, `sunburst`). A branch normally omits `y` and
* takes the sum of its children instead. * takes the sum of its children instead.
*/ */
children?: XChartHierarchyNode[]; children?: XChartHierarchyNode[];
/** /**
* Drilldown target: the `id` of a `drilldown.series` entry. Clicking this * Drilldown target: the `id` of a `drilldown.series` entry. Clicking this
* point drills into that level. Requires the Drilldown feature. * point drills into that level. Requires the Drilldown feature.
*/ */
drilldown?: string | number; drilldown?: string | number;
goals?: { goals?: {
name?: string; name?: string;
value: number; value: number;
strokeHeight?: number; strokeHeight?: number;
strokeWidth?: number; strokeWidth?: number;
strokeColor?: string; strokeColor?: string;
strokeDashArray?: number; strokeDashArray?: number;
strokeLineCap?: 'butt' | 'square' | 'round'; strokeLineCap?: 'butt' | 'square' | 'round';
}[]; }[];
barHeightOffset?: number; barHeightOffset?: number;
columnWidthOffset?: number; columnWidthOffset?: number;
}[] }[]
| [number, number | null][] | [number, number | null][]
| [number, (number | null)[]][] | [number, (number | null)[]][]
| number[][] | number[][]
// A `children` hierarchy for the partition charts, where a branch carries no // A `children` hierarchy for the partition charts, where a branch carries no
// value of its own. Listed before the catch-all so authors get completion on // value of its own. Listed before the catch-all so authors get completion on
// the node shape instead of falling through to `Record<string, any>`. // the node shape instead of falling through to `Record<string, any>`.
| XChartHierarchyNode[] | XChartHierarchyNode[]
| Record<string, any>[]; | Record<string, any>[];
}[]; }[];
export type XChartNonAxisChartSeries = number[] | XChartAxisChartSeries; export type XChartNonAxisChartSeries = number[] | XChartAxisChartSeries;
@@ -932,11 +931,11 @@ export type XChartPlotOptions = {
* property, or an accessor to compute one. * property, or an accessor to compute one.
*/ */
colorValue?: colorValue?:
| string | string
| (( | ((
datum: any, datum: any,
opts: { seriesIndex: number; dataPointIndex: number; w: any }, opts: { seriesIndex: number; dataPointIndex: number; w: any },
) => number); ) => number);
/** /**
* Continuous interpolation between colour stops, for the metric above. * Continuous interpolation between colour stops, for the metric above.
* Active as soon as any datum carries a colour metric; `enabled: false` * Active as soon as any datum carries a colour metric; `enabled: false`
@@ -1069,13 +1068,13 @@ export type XChartPlotOptions = {
* 'custom': positions come from `positions`. * 'custom': positions come from `positions`.
*/ */
layout?: layout?:
| 'grouped' | 'grouped'
| 'packed' | 'packed'
| 'columns' | 'columns'
| 'grid' | 'grid'
| 'scatter' | 'scatter'
| 'arc' | 'arc'
| 'custom'; | 'custom';
/** /**
* `layout: 'custom'` only. The layout provider: either a function returning * `layout: 'custom'` only. The layout provider: either a function returning
* plot-pixel positions, or the name of one registered with * plot-pixel positions, or the name of one registered with
@@ -2103,19 +2102,19 @@ export interface XChartDrilldown {
/** Inline child levels referenced by data-point `drilldown` ids. */ /** Inline child levels referenced by data-point `drilldown` ids. */
series?: XChartDrilldownSeries[]; series?: XChartDrilldownSeries[];
breadcrumb?: breadcrumb?:
| false | false
| { | {
show?: boolean; show?: boolean;
position?: 'top-left' | 'top-right'; position?: 'top-left' | 'top-right';
separator?: string; separator?: string;
rootLabel?: string; rootLabel?: string;
offsetX?: number; offsetX?: number;
offsetY?: number; offsetY?: number;
formatter?( formatter?(
label: string, label: string,
opts: { index: number; depth: number }, opts: { index: number; depth: number },
): string; ): string;
}; };
animation?: { animation?: {
enabled?: boolean; enabled?: boolean;
/** /**
@@ -2164,11 +2163,11 @@ export interface XChartDrilldown {
* name, so the default ships no user-visible English. * name, so the default ships no user-visible English.
*/ */
loading?: loading?:
| false | false
| { | {
show?: boolean; show?: boolean;
text?: string; text?: string;
}; };
/** /**
* Cache levels resolved by `onDrillDown`, keyed by id, so drilling back down * Cache levels resolved by `onDrillDown`, keyed by id, so drilling back down
* a branch does not re-fetch. Default true. Clear it with the drilldown * a branch does not re-fetch. Default true. Clear it with the drilldown
@@ -2274,12 +2273,12 @@ export type XChartStates = {
export type XChartStroke = { export type XChartStroke = {
show?: boolean; show?: boolean;
curve?: curve?:
| 'smooth' | 'smooth'
| 'straight' | 'straight'
| 'stepline' | 'stepline'
| 'linestep' | 'linestep'
| 'monotoneCubic' | 'monotoneCubic'
| ('smooth' | 'straight' | 'stepline' | 'linestep' | 'monotoneCubic')[]; | ('smooth' | 'straight' | 'stepline' | 'linestep' | 'monotoneCubic')[];
lineCap?: 'butt' | 'square' | 'round'; lineCap?: 'butt' | 'square' | 'round';
colors?: string[]; colors?: string[];
width?: number | number[]; width?: number | number[];
@@ -2330,11 +2329,11 @@ export type XChartTheme = {
}; };
accessibility?: { accessibility?: {
colorBlindMode?: colorBlindMode?:
| 'deuteranopia' | 'deuteranopia'
| 'protanopia' | 'protanopia'
| 'tritanopia' | 'tritanopia'
| 'highContrast' | 'highContrast'
| ''; | '';
}; };
}; };
@@ -2363,14 +2362,14 @@ export type XChartTooltip = {
inverseOrder?: boolean; inverseOrder?: boolean;
arrow?: boolean; arrow?: boolean;
custom?: custom?:
| (( | ((
opts: XChartTooltipCustomOpts, opts: XChartTooltipCustomOpts,
) => string | number | Element | { nodeName: string }) ) => string | number | Element | { nodeName: string })
| Array< | Array<
( (
opts: XChartTooltipCustomOpts, opts: XChartTooltipCustomOpts,
) => string | number | Element | { nodeName: string } ) => string | number | Element | { nodeName: string }
>; >;
fillSeriesColor?: boolean; fillSeriesColor?: boolean;
theme?: 'light' | 'dark'; theme?: 'light' | 'dark';
cssClass?: string; cssClass?: string;
@@ -2447,30 +2446,30 @@ export type XChart = {
width?: string | number; width?: string | number;
height?: string | number; height?: string | number;
type?: type?:
| 'line' | 'line'
| 'area' | 'area'
| 'bar' | 'bar'
| 'pie' | 'pie'
| 'donut' | 'donut'
| 'radialBar' | 'radialBar'
| 'scatter' | 'scatter'
| 'bubble' | 'bubble'
| 'heatmap' | 'heatmap'
| 'candlestick' | 'candlestick'
| 'boxPlot' | 'boxPlot'
| 'violin' | 'violin'
| 'histogram' | 'histogram'
| 'radar' | 'radar'
| 'polarArea' | 'polarArea'
| 'rangeBar' | 'rangeBar'
| 'rangeArea' | 'rangeArea'
| 'treemap' | 'treemap'
| 'unit' | 'unit'
| 'waffle' | 'waffle'
| 'sunburst' | 'sunburst'
| 'funnel' | 'funnel'
| 'pyramid' | 'pyramid'
| 'gauge'; | 'gauge';
/** /**
* Internal — populated when `type` is a first-class alias (`'funnel'`, * Internal — populated when `type` is a first-class alias (`'funnel'`,
* `'pyramid'`, `'gauge'`, `'waffle'`, `'histogram'`). The original requested * `'pyramid'`, `'gauge'`, `'waffle'`, `'histogram'`). The original requested
@@ -2753,9 +2752,9 @@ export type XChart = {
dimension?: (row: any) => any; dimension?: (row: any) => any;
/** FILTER mode: reduction over a bucket's rows. @default 'count' */ /** FILTER mode: reduction over a bucket's rows. @default 'count' */
reduce?: reduce?:
| 'count' | 'count'
| { sum?: string; avg?: string; min?: string; max?: string } | { sum?: string; avg?: string; min?: string; max?: string }
| ((rows: any[]) => number); | ((rows: any[]) => number);
/** /**
* FILTER mode: bucket kind. Else inferred: `bins` present => 'range', a * FILTER mode: bucket kind. Else inferred: `bins` present => 'range', a
* heatmap chart => 'matrix' (2D), otherwise 'category'. * heatmap chart => 'matrix' (2D), otherwise 'category'.
@@ -2873,21 +2872,21 @@ export type XChart = {
| 'yline' | 'yline'
| 'measure' | 'measure'
| { | {
id?: string; id?: string;
label?: string; label?: string;
icon?: string; icon?: string;
onClick?: ( onClick?: (
chart: ApexCharts, chart: ApexCharts,
context: { context: {
x: any; x: any;
y: any; y: any;
seriesIndex: number | null; seriesIndex: number | null;
dataPointIndex: number | null; dataPointIndex: number | null;
clientX: number; clientX: number;
clientY: number; clientY: number;
}, },
) => void; ) => void;
} }
>; >;
/** Override the built-in item labels. */ /** Override the built-in item labels. */
labels?: { labels?: {
@@ -3226,7 +3225,7 @@ export enum XChartAction {
export type XChartActionIdentifier = XChartAction | string; export type XChartActionIdentifier = XChartAction | string;
export interface XChartActionModel extends XBaseActionModel<XChartActionIdentifier> {} export interface XChartActionModel extends XBaseActionModel<XChartActionIdentifier> { }
export type XChartSeriesType = XChartAxisChartSeries | XChartNonAxisChartSeries; export type XChartSeriesType = XChartAxisChartSeries | XChartNonAxisChartSeries;
@@ -3300,8 +3299,7 @@ export interface IXChartContainer extends TXChartContainer {
autoUpdate: XStandardType<boolean>; autoUpdate: XStandardType<boolean>;
options: XStandardType<XChartOptions>; options: XStandardType<XChartOptions>;
series: XStandardType<XChartSeriesType>; series: XStandardType<XChartSeriesType>;
zoomStep: XStandardType<number>;
//
type: XStandardType<XChartTypeIdentifier>; type: XStandardType<XChartTypeIdentifier>;
// //
@@ -3324,14 +3322,16 @@ export interface IXChartContainer extends TXChartContainer {
}) })
export class XChartContainer export class XChartContainer
extends XBaseContainer extends XBaseContainer
implements Readonly<IXChartContainer> implements Readonly<IXChartContainer> {
{ //
readonly actionProvider = new Subject<XChartActionModel>();
readonly cssClass: XStandardType<XOneOrManyType<string>>;
// //
readonly options: XStandardType<XChartOptions>; readonly options: XStandardType<XChartOptions>;
readonly zoomStep: XStandardType<number> = 0.125;
readonly series: XStandardType<XChartSeriesType>; readonly series: XStandardType<XChartSeriesType>;
readonly autoUpdate: XStandardType<boolean> = true; readonly autoUpdate: XStandardType<boolean> = true;
readonly cssClass: XStandardType<XOneOrManyType<string>>;
readonly actionProvider = new Subject<XChartActionModel>();
readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line; readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line;
// //
@@ -3403,8 +3403,7 @@ export class XChartContainer
@Component({ template: `` }) @Component({ template: `` })
export abstract class XChartContainerComponent export abstract class XChartContainerComponent
extends XBaseContainerComponent extends XBaseContainerComponent
implements IXChartContainer implements IXChartContainer {
{
// //
//#region Props ... //#region Props ...
@Input() @Input()
@@ -3427,6 +3426,9 @@ export abstract class XChartContainerComponent
@Input() @Input()
series: XStandardType<XChartSeriesType> = this.propertyProvider.series; series: XStandardType<XChartSeriesType> = this.propertyProvider.series;
@Input()
zoomStep: XStandardType<number> = this.propertyProvider.zoomStep;
@Input() @Input()
autoUpdate: XStandardType<boolean> = this.propertyProvider.autoUpdate; autoUpdate: XStandardType<boolean> = this.propertyProvider.autoUpdate;