@eclipse-scout/chart 24.1.3 → 24.1.10

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.
package/dist/file-list CHANGED
@@ -1,13 +1,13 @@
1
- eclipse-scout-chart-1a81682e3fb823b0ca01.min.js
2
- eclipse-scout-chart-1a81682e3fb823b0ca01.min.js.map
1
+ eclipse-scout-chart-3ba6b8f30d5806cac8ae.min.js
2
+ eclipse-scout-chart-3ba6b8f30d5806cac8ae.min.js.map
3
3
  eclipse-scout-chart-theme-56ba6667e592ef147869.min.css
4
4
  eclipse-scout-chart-theme-dark-593955eea95984c5aa62.min.css
5
5
  eclipse-scout-chart-theme-dark.css
6
6
  eclipse-scout-chart-theme-dark.css.map
7
7
  eclipse-scout-chart-theme.css
8
8
  eclipse-scout-chart-theme.css.map
9
- eclipse-scout-chart.esm-063bb266266e01e3ccd0.min.js
10
- eclipse-scout-chart.esm-063bb266266e01e3ccd0.min.js.map
9
+ eclipse-scout-chart.esm-8d9db200429e545abcae.min.js
10
+ eclipse-scout-chart.esm-8d9db200429e545abcae.min.js.map
11
11
  eclipse-scout-chart.esm.js
12
12
  eclipse-scout-chart.esm.js.map
13
13
  eclipse-scout-chart.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-scout/chart",
3
- "version": "24.1.3",
3
+ "version": "24.1.10",
4
4
  "description": "Eclipse Scout chart",
5
5
  "author": "BSI Business Systems Integration AG",
6
6
  "homepage": "https://www.eclipse.org/scout",
@@ -26,7 +26,7 @@
26
26
  "src"
27
27
  ],
28
28
  "devDependencies": {
29
- "@eclipse-scout/cli": "24.1.3",
29
+ "@eclipse-scout/cli": "24.1.10",
30
30
  "@eclipse-scout/releng": "^24.1.0",
31
31
  "jasmine-core": "5.1.1",
32
32
  "jasmine-jquery": "2.1.1",
@@ -36,7 +36,7 @@
36
36
  "@types/jasmine-jquery": "1.5.37"
37
37
  },
38
38
  "dependencies": {
39
- "@eclipse-scout/core": "24.1.3",
39
+ "@eclipse-scout/core": "24.1.10",
40
40
  "jquery": "3.7.1",
41
41
  "chart.js": "4.4.0",
42
42
  "chartjs-plugin-datalabels": "2.2.0"
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010, 2023 BSI Business Systems Integration AG
2
+ * Copyright (c) 2010, 2024 BSI Business Systems Integration AG
3
3
  *
4
4
  * This program and the accompanying materials are made
5
5
  * available under the terms of the Eclipse Public License 2.0
@@ -9,10 +9,12 @@
9
9
  */
10
10
 
11
11
  import {Chart} from '../index';
12
- import {arrays, Session} from '@eclipse-scout/core';
12
+ import {arrays, PropertyChangeEvent, PropertyEventEmitter, PropertyEventMap, Session} from '@eclipse-scout/core';
13
13
  import {UpdateChartOptions} from './Chart';
14
14
 
15
- export class AbstractChartRenderer {
15
+ export class AbstractChartRenderer extends PropertyEventEmitter {
16
+ declare eventMap: AbstractChartRendererEventMap;
17
+
16
18
  chart: Chart;
17
19
  session: Session;
18
20
 
@@ -25,6 +27,7 @@ export class AbstractChartRenderer {
25
27
  firstOpaqueBackgroundColor: string;
26
28
 
27
29
  constructor(chart: Chart) {
30
+ super();
28
31
  this.chart = chart;
29
32
  this.session = chart.session;
30
33
  this.rendering = false;
@@ -87,14 +90,16 @@ export class AbstractChartRenderer {
87
90
  * property is ignored when chart.config.options.animation.duration is <code>0</code>!
88
91
  */
89
92
  render(requestAnimation: boolean) {
90
- this.animationDuration = requestAnimation ? this.chart.config.options.animation.duration : 0;
91
93
  if (!this.validate() || !this.chart.rendered) {
92
94
  return;
93
95
  }
96
+ const configAnimationDuration = this.chart.config.options.animation.duration;
97
+ this.setAnimationDuration(requestAnimation ? configAnimationDuration : 0);
94
98
  this.rendering = true;
95
99
  this._render();
96
100
  this.rendering = false;
97
101
  this.rendered = true;
102
+ this.setAnimationDuration(configAnimationDuration);
98
103
  }
99
104
 
100
105
  protected _render() {
@@ -121,11 +126,13 @@ export class AbstractChartRenderer {
121
126
  this.render(requestAnimation);
122
127
  return;
123
128
  }
124
- this.animationDuration = requestAnimation ? this.chart.config.options.animation.duration : 0;
125
129
  if (!this.validate() || !this.isDataUpdatable()) {
126
130
  return;
127
131
  }
132
+ const configAnimationDuration = this.chart.config.options.animation.duration;
133
+ this.setAnimationDuration(requestAnimation ? configAnimationDuration : 0);
128
134
  this._updateData();
135
+ this.setAnimationDuration(configAnimationDuration);
129
136
  }
130
137
 
131
138
  protected _updateData() {
@@ -136,6 +143,10 @@ export class AbstractChartRenderer {
136
143
  return false;
137
144
  }
138
145
 
146
+ isDetachSupported(): boolean {
147
+ return true;
148
+ }
149
+
139
150
  refresh() {
140
151
  if (this.rendered) {
141
152
  this.remove(false);
@@ -143,18 +154,37 @@ export class AbstractChartRenderer {
143
154
  this.render(false);
144
155
  }
145
156
 
157
+ setAnimationDuration(animationDuration: number) {
158
+ if (!this.setProperty('animationDuration', animationDuration)) {
159
+ return;
160
+ }
161
+ if (this.rendered) {
162
+ this._renderAnimationDuration();
163
+ }
164
+ }
165
+
166
+ protected _setAnimationDuration(animationDuration: number) {
167
+ this._setProperty('animationDuration', animationDuration);
168
+ }
169
+
170
+ protected _renderAnimationDuration() {
171
+ // nop
172
+ }
173
+
146
174
  /**
147
175
  * @param requestAnimation
148
176
  * Whether animations should be used while removing the chart. Note that his
149
177
  * property is ignored when chart.config.options.animation.duration is <code>0</code>!
150
178
  */
151
179
  remove(requestAnimation = false, afterRemoveFunc?: (chartAnimationStopping?: boolean) => void) {
152
- this.animationDuration = requestAnimation && this.chart.config.options.animation.duration;
180
+ const configAnimationDuration = this.chart.config.options.animation.duration;
181
+ this.setAnimationDuration(requestAnimation && configAnimationDuration);
153
182
  if (this.animationDuration && this.rendered) {
154
183
  this._removeAnimated(afterRemoveFunc);
155
184
  } else {
156
185
  this._remove(afterRemoveFunc);
157
186
  }
187
+ this.setAnimationDuration(configAnimationDuration);
158
188
  }
159
189
 
160
190
  protected _remove(afterRemoveFunc: (chartAnimationStopping?: boolean) => void) {
@@ -174,3 +204,7 @@ export class AbstractChartRenderer {
174
204
  return opts.requestAnimation;
175
205
  }
176
206
  }
207
+
208
+ export interface AbstractChartRendererEventMap extends PropertyEventMap {
209
+ 'propertyChange:animationDuration': PropertyChangeEvent<number>;
210
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010, 2023 BSI Business Systems Integration AG
2
+ * Copyright (c) 2010, 2024 BSI Business Systems Integration AG
3
3
  *
4
4
  * This program and the accompanying materials are made
5
5
  * available under the terms of the Eclipse Public License 2.0
@@ -10,7 +10,7 @@
10
10
  import {AbstractChartRenderer, ChartEventMap, ChartJsRenderer, ChartLayout, ChartModel, FulfillmentChartRenderer, SalesfunnelChartRenderer, SpeedoChartRenderer, VennChartRenderer} from '../index';
11
11
  import {aria, arrays, ColorScheme, colorSchemes, EnumObject, HtmlComponent, InitModelOf, objects, Widget} from '@eclipse-scout/core';
12
12
  import {GreenAreaPosition} from './SpeedoChartRenderer';
13
- import {ChartConfiguration, LinearScaleOptions, RadialLinearScaleOptions} from 'chart.js';
13
+ import {CategoryScaleOptions, ChartConfiguration, ChartOptions, LinearScaleOptions, LogarithmicScaleOptions, RadialLinearScaleOptions, ScaleType, TimeScaleOptions as ChartJsTimeScaleOptions} from 'chart.js';
14
14
  import $ from 'jquery';
15
15
 
16
16
  export class Chart extends Widget implements ChartModel {
@@ -107,7 +107,14 @@ export class Chart extends Widget implements ChartModel {
107
107
 
108
108
  protected override _renderOnAttach() {
109
109
  super._renderOnAttach();
110
- this._updateChartOptsWhileNotAttached.splice(0).forEach(opts => this.updateChart($.extend(true, {}, opts, {debounce: true})));
110
+ const updateChartOptsWhileNotAttached = this._updateChartOptsWhileNotAttached.splice(0);
111
+ if (!this.chartRenderer?.isDetachSupported()) {
112
+ // the chartRenderer does not support detach => recreate it
113
+ this._updateChartRenderer();
114
+ updateChartOptsWhileNotAttached.forEach(opts => delete opts.requestAnimation);
115
+ updateChartOptsWhileNotAttached.push({requestAnimation: false});
116
+ }
117
+ updateChartOptsWhileNotAttached.forEach(opts => this.updateChart($.extend(true, {}, opts, {debounce: true})));
111
118
  }
112
119
 
113
120
  protected override _remove() {
@@ -407,60 +414,72 @@ export type ChartValueGroup = {
407
414
  cssClass?: string;
408
415
  };
409
416
 
410
- export type ChartConfig = Partial<Omit<ChartConfiguration, 'type'>> & {
417
+ export type ChartConfig = Partial<Omit<ChartConfiguration, 'type' | 'options'>> & {
411
418
  type: ChartType;
412
- options?: {
413
- autoColor?: boolean;
414
- colorScheme?: ColorScheme | string;
415
- transparent?: boolean;
416
- maxSegments?: number;
417
- otherSegmentClickable?: boolean;
418
- adjustGridMaxMin?: boolean;
419
- clickable?: boolean;
420
- checkable?: boolean;
421
- scaleLabelByTypeMap?: Record<ChartType, Record<string, string>>;
422
- numberFormatter?: NumberFormatter;
423
- reformatLabels?: boolean;
424
- handleResize?: boolean;
425
- animation?: {
426
- duration?: number;
427
- };
428
- scales?: {
429
- x?: LinearScaleOptions & {
430
- minSpaceBetweenTicks?: number;
431
- };
432
- y?: LinearScaleOptions & {
433
- minSpaceBetweenTicks?: number;
434
- };
435
- yDiffType?: LinearScaleOptions;
436
- r?: RadialLinearScaleOptions & {
437
- minSpaceBetweenTicks?: number;
438
- };
439
- };
440
- bubble?: {
441
- sizeOfLargestBubble?: number;
442
- minBubbleSize?: number;
443
- };
444
- fulfillment?: {
445
- startValue?: number;
446
- };
447
- salesfunnel?: {
448
- normalized?: boolean;
449
- calcConversionRate?: boolean;
450
- };
451
- speedo?: {
452
- greenAreaPosition?: GreenAreaPosition;
453
- };
454
- venn?: {
455
- numberOfCircles?: 1 | 2 | 3;
456
- };
457
- plugins?: {
458
- legend?: {
459
- clickable?: boolean;
460
- };
419
+ options?: ChartConfigOptions;
420
+ };
421
+
422
+ export type ChartConfigOptions = Omit<ChartOptions, 'scales'> & {
423
+ autoColor?: boolean;
424
+ colorScheme?: ColorScheme | string;
425
+ transparent?: boolean;
426
+ maxSegments?: number;
427
+ otherSegmentClickable?: boolean;
428
+ adjustGridMaxMin?: boolean;
429
+ clickable?: boolean;
430
+ checkable?: boolean;
431
+ scaleLabelByTypeMap?: Record<ChartType, Record<string, string>>;
432
+ numberFormatter?: NumberFormatter;
433
+ reformatLabels?: boolean;
434
+ handleResize?: boolean;
435
+ animation?: {
436
+ duration?: number;
437
+ };
438
+ scales?: {
439
+ x?: CartesianChartScale;
440
+ y?: CartesianChartScale;
441
+ yDiffType?: CartesianChartScale;
442
+ r?: RadialChartScale;
443
+ };
444
+ bubble?: {
445
+ sizeOfLargestBubble?: number;
446
+ minBubbleSize?: number;
447
+ };
448
+ fulfillment?: {
449
+ startValue?: number;
450
+ };
451
+ salesfunnel?: {
452
+ normalized?: boolean;
453
+ calcConversionRate?: boolean;
454
+ };
455
+ speedo?: {
456
+ greenAreaPosition?: GreenAreaPosition;
457
+ };
458
+ venn?: {
459
+ numberOfCircles?: 1 | 2 | 3;
460
+ };
461
+ plugins?: {
462
+ legend?: {
463
+ clickable?: boolean;
461
464
  };
462
465
  };
463
466
  };
467
+
468
+ export type RadialChartScale = DeepPartial<RadialLinearScaleOptions> & {
469
+ type?: ScaleType;
470
+ minSpaceBetweenTicks?: number;
471
+ };
472
+
473
+ export type CartesianChartScale = DeepPartial<LinearScaleOptions | CategoryScaleOptions | TimeScaleOptions | LogarithmicScaleOptions> & {
474
+ type?: ScaleType;
475
+ minSpaceBetweenTicks?: number;
476
+ };
477
+
478
+ export type TimeScaleOptions = Omit<ChartJsTimeScaleOptions, 'min' | 'max'> & {
479
+ min?: string | number | Date | (() => string | number | Date);
480
+ max?: string | number | Date | (() => string | number | Date);
481
+ };
482
+
464
483
  export type ChartType = EnumObject<typeof Chart.Type>;
465
484
  export type ChartPosition = EnumObject<typeof Chart.Position>;
466
485
  export type NumberFormatter = (label: number | string, defaultFormatter: (label: number | string) => string) => string;
@@ -491,3 +510,7 @@ export type UpdateChartOptions = {
491
510
  onlyRefresh?: boolean;
492
511
  enforceRerender?: boolean;
493
512
  };
513
+
514
+ type DeepPartial<T> = T extends object ? {
515
+ [P in keyof T]?: DeepPartial<T[P]>;
516
+ } : T;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010, 2023 BSI Business Systems Integration AG
2
+ * Copyright (c) 2010, 2024 BSI Business Systems Integration AG
3
3
  *
4
4
  * This program and the accompanying materials are made
5
5
  * available under the terms of the Eclipse Public License 2.0
@@ -7,10 +7,11 @@
7
7
  *
8
8
  * SPDX-License-Identifier: EPL-2.0
9
9
  */
10
- import {AbstractChartRenderer, Chart, chartJsDateAdapter} from '../index';
10
+ import {AbstractChartRenderer, CartesianChartScale, Chart, chartJsDateAdapter, RadialChartScale} from '../index';
11
11
  import {
12
12
  _adapters as chartJsAdapters, ActiveElement, ArcElement, BarElement, BubbleDataPoint, CartesianScaleOptions, Chart as ChartJs, ChartArea, ChartConfiguration, ChartDataset, ChartEvent, ChartType as ChartJsType, Color, DefaultDataPoint,
13
- FontSpec, LegendElement, LegendItem, LegendOptions, LinearScaleOptions, PointElement, PointHoverOptions, RadialLinearScaleOptions, Scale, ScatterDataPoint, TooltipCallbacks, TooltipItem, TooltipLabelStyle, TooltipModel, TooltipOptions
13
+ FontSpec, LegendElement, LegendItem, LegendOptions, LinearScaleOptions, PointElement, PointHoverOptions, RadialLinearScaleOptions, Scale, ScatterDataPoint, Scriptable, ScriptableContext, TooltipCallbacks, TooltipItem, TooltipLabelStyle,
14
+ TooltipModel, TooltipOptions
14
15
  } from 'chart.js';
15
16
  import 'chart.js/auto'; // Import from auto to register charts
16
17
  import {aria, arrays, colorSchemes, graphics, numbers, objects, Point, scout, strings, styles, Tooltip, tooltips} from '@eclipse-scout/core';
@@ -241,10 +242,10 @@ export class ChartJsRenderer extends AbstractChartRenderer {
241
242
  }
242
243
  let config = $.extend(true, {}, this.chart.config);
243
244
  this._adjustConfig(config);
244
- this._renderChart(config, true);
245
+ this._renderChart(config);
245
246
  }
246
247
 
247
- protected _renderChart(config: ChartConfig, animated: boolean) {
248
+ protected _renderChart(config: ChartConfig) {
248
249
  if (this.chartJs) {
249
250
  this.chartJs.destroy();
250
251
  }
@@ -253,11 +254,11 @@ export class ChartJsRenderer extends AbstractChartRenderer {
253
254
  animation: {}
254
255
  }
255
256
  }, config);
256
- config.options.animation.duration = animated ? this.animationDuration : 0;
257
+ config.options.animation.duration = this.animationDuration;
257
258
 
258
259
  this.chartJs = new ChartJs(this.$canvas[0].getContext('2d'), config as ChartConfiguration) as ChartJsChart;
259
260
  this._adjustSize(this.chartJs.config, this.chartJs.chartArea);
260
- this.chartJs.update();
261
+ this.refresh();
261
262
  }
262
263
 
263
264
  protected override _updateData() {
@@ -435,16 +436,22 @@ export class ChartJsRenderer extends AbstractChartRenderer {
435
436
  (axis.ticks || {} as (LinearScaleOptions | RadialLinearScaleOptions)['ticks']).stepSize = undefined;
436
437
  });
437
438
 
438
- this.chartJs.update();
439
+ this.refresh();
439
440
 
440
441
  this._adjustSize(this.chartJs.config, this.chartJs.chartArea);
441
- this.chartJs.update();
442
+ this.refresh();
442
443
  }
443
444
 
444
445
  override isDataUpdatable(): boolean {
445
446
  return true;
446
447
  }
447
448
 
449
+ override isDetachSupported(): boolean {
450
+ // chart.js removes the animation-listeners onProgress and onComplete on detach and does not add them again on attach
451
+ // these listeners are needed for the datalabels => this renderer does not support detach
452
+ return false;
453
+ }
454
+
448
455
  override refresh() {
449
456
  if (this.chartJs) {
450
457
  this.chartJs.update();
@@ -453,9 +460,23 @@ export class ChartJsRenderer extends AbstractChartRenderer {
453
460
  }
454
461
  }
455
462
 
463
+ protected override _renderAnimationDuration() {
464
+ if (!this.chartJs) {
465
+ return;
466
+ }
467
+ $.extend(true, this.chartJs.config, {
468
+ options: {
469
+ animation: {
470
+ duration: this.animationDuration
471
+ }
472
+ }
473
+ });
474
+ this.refresh();
475
+ }
476
+
456
477
  protected override _renderCheckedItems() {
457
478
  if (this.chartJs && this._checkItems(this.chartJs.config)) {
458
- this.chartJs.update();
479
+ this.refresh();
459
480
  }
460
481
  }
461
482
 
@@ -2249,7 +2270,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
2249
2270
  }
2250
2271
  });
2251
2272
  if (update) {
2252
- this.chartJs.update();
2273
+ this.refresh();
2253
2274
  }
2254
2275
  }
2255
2276
 
@@ -2297,7 +2318,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
2297
2318
  datasetType = dataset ? dataset.type : null;
2298
2319
  if ((datasetType || type) === Chart.Type.LINE) {
2299
2320
  this._setHoverBackgroundColor(dataset);
2300
- this.chartJs.update();
2321
+ this.refresh();
2301
2322
  }
2302
2323
  this._updateHoverStyle(index, true);
2303
2324
  this.chartJs.render();
@@ -2328,7 +2349,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
2328
2349
  datasetType = dataset ? dataset.type : null;
2329
2350
  if ((datasetType || type) === Chart.Type.LINE) {
2330
2351
  this._restoreBackgroundColor(dataset);
2331
- this.chartJs.update();
2352
+ this.refresh();
2332
2353
  }
2333
2354
  this._updateHoverStyle(index, false);
2334
2355
  this.chartJs.render();
@@ -2782,7 +2803,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
2782
2803
  });
2783
2804
  }
2784
2805
 
2785
- protected _adjustAxisMaxMin(axis: LinearScaleOptions | RadialLinearScaleOptions, maxTicks: number, maxMinValue: Boundary) {
2806
+ protected _adjustAxisMaxMin(axis: AxisWithMaxMin, maxTicks: number, maxMinValue: Boundary) {
2786
2807
  if (!axis) {
2787
2808
  return;
2788
2809
  }
@@ -2845,6 +2866,12 @@ export type DatasetColors = {
2845
2866
 
2846
2867
  export type Boundary = { maxValue: number; minValue: number };
2847
2868
 
2869
+ export type AxisWithMaxMin = (CartesianChartScale | RadialChartScale) & {
2870
+ ticks?: (CartesianChartScale | RadialChartScale)['ticks'] & {
2871
+ stepSize?: number;
2872
+ };
2873
+ };
2874
+
2848
2875
  // extend chart.js
2849
2876
 
2850
2877
  export type ChartJsChart = Omit<ChartJs, 'config'> & {
@@ -2861,10 +2888,10 @@ declare module 'chart.js' {
2861
2888
  datasetId?: string;
2862
2889
  yAxisID?: 'y' | 'yDiffType';
2863
2890
 
2864
- pointBackgroundColor?: Color;
2865
- pointHoverBackgroundColor?: Color;
2866
- pointRadius?: number;
2867
- legendColor?: Color;
2891
+ pointBackgroundColor?: Scriptable<Color, ScriptableContext<TType>>;
2892
+ pointHoverBackgroundColor?: Scriptable<Color, ScriptableContext<TType>>;
2893
+ pointRadius?: Scriptable<number, ScriptableContext<TType>>;
2894
+ legendColor?: Scriptable<Color, number>;
2868
2895
 
2869
2896
  checkedBackgroundColor?: Color;
2870
2897
  checkedHoverBackgroundColor?: Color;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010, 2023 BSI Business Systems Integration AG
2
+ * Copyright (c) 2010, 2024 BSI Business Systems Integration AG
3
3
  *
4
4
  * This program and the accompanying materials are made
5
5
  * available under the terms of the Eclipse Public License 2.0
@@ -103,6 +103,8 @@ export class VennChartRenderer extends AbstractSvgChartRenderer {
103
103
  }
104
104
 
105
105
  // Final callback
106
+ // In the case of 3 circles, draw will be called async after render is completed. Therefore, the current animationDuration needs to be set again when _draw is finally called.
107
+ const animationDurationRender = this.animationDuration;
106
108
  let draw = function() {
107
109
  this.readyToDraw = true;
108
110
  if (!this.$svg.isAttached()) {
@@ -110,7 +112,10 @@ export class VennChartRenderer extends AbstractSvgChartRenderer {
110
112
  return;
111
113
  }
112
114
  this.readyToDraw = false;
115
+ const animationDuration = this.animationDuration;
116
+ this.setAnimationDuration(animationDurationRender);
113
117
  this._draw(true, true);
118
+ this.setAnimationDuration(animationDuration);
114
119
  }.bind(this);
115
120
 
116
121
  // save callback if user navigated away while calculating and _draw is not executed.