@devexperts/dxcharts-lite 2.0.2 → 2.2.0

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.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/chart/__tests__/chart.test.d.ts +6 -0
  3. package/dist/chart/__tests__/chart.test.js +51 -0
  4. package/dist/chart/__tests__/env.d.ts +5 -0
  5. package/dist/chart/__tests__/env.js +28 -0
  6. package/dist/chart/bootstrap.js +2 -2
  7. package/dist/chart/chart.config.d.ts +4 -1
  8. package/dist/chart/chart.config.js +1 -1
  9. package/dist/chart/components/chart/chart-base.model.d.ts +1 -1
  10. package/dist/chart/components/chart/chart.component.js +13 -3
  11. package/dist/chart/components/chart/chart.model.d.ts +2 -2
  12. package/dist/chart/components/chart/chart.model.js +9 -7
  13. package/dist/chart/components/cross_tool/cross-tool.component.d.ts +2 -1
  14. package/dist/chart/components/cross_tool/cross-tool.component.js +4 -3
  15. package/dist/chart/components/cross_tool/cross-tool.model.js +1 -0
  16. package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.d.ts +3 -1
  17. package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +3 -2
  18. package/dist/chart/components/dynamic-objects/dynamic-objects.component.js +1 -1
  19. package/dist/chart/components/dynamic-objects/dynamic-objects.model.d.ts +30 -10
  20. package/dist/chart/components/dynamic-objects/dynamic-objects.model.js +119 -57
  21. package/dist/chart/components/grid/grid.drawer.js +3 -1
  22. package/dist/chart/components/pane/extent/y-extent-component.js +2 -1
  23. package/dist/chart/components/pane/pane-hit-test.controller.js +2 -2
  24. package/dist/chart/components/volumes/volumes.component.d.ts +3 -0
  25. package/dist/chart/components/volumes/volumes.component.js +21 -4
  26. package/dist/chart/components/volumes/volumes.model.d.ts +2 -0
  27. package/dist/chart/components/volumes/volumes.model.js +2 -0
  28. package/dist/chart/components/x_axis/x-axis.component.js +2 -2
  29. package/dist/chart/components/y_axis/label-color.functions.d.ts +2 -1
  30. package/dist/chart/components/y_axis/label-color.functions.js +17 -0
  31. package/dist/chart/components/y_axis/price_labels/data-series-y-axis-labels.provider.d.ts +2 -2
  32. package/dist/chart/components/y_axis/price_labels/data-series-y-axis-labels.provider.js +27 -25
  33. package/dist/chart/components/y_axis/price_labels/labels-positions-calculator.js +24 -13
  34. package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.d.ts +3 -3
  35. package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.js +58 -40
  36. package/dist/chart/components/y_axis/price_labels/y-axis-price-labels.drawer.d.ts +3 -3
  37. package/dist/chart/components/y_axis/price_labels/y-axis-price-labels.drawer.js +15 -13
  38. package/dist/chart/components/y_axis/y-axis-scale.handler.js +1 -1
  39. package/dist/chart/components/y_axis/y-axis.component.d.ts +2 -1
  40. package/dist/chart/components/y_axis/y-axis.component.js +6 -2
  41. package/dist/chart/drawers/ht-data-series.drawer.js +1 -1
  42. package/dist/chart/inputhandlers/cross-event-producer.component.js +2 -1
  43. package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
  44. package/dist/chart/inputhandlers/hover-producer.component.js +8 -8
  45. package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +12 -5
  46. package/dist/chart/inputlisteners/canvas-input-listener.component.js +74 -62
  47. package/dist/chart/model/candle-series.model.d.ts +1 -1
  48. package/dist/chart/model/candle-series.model.js +2 -2
  49. package/dist/chart/model/compare-series-hover.d.ts +2 -1
  50. package/dist/chart/model/compare-series-hover.js +1 -0
  51. package/dist/chart/model/data-series.model.d.ts +3 -2
  52. package/dist/chart/model/data-series.model.js +2 -1
  53. package/dist/chart/model/main-candle-series.model.d.ts +1 -1
  54. package/dist/chart/model/main-candle-series.model.js +2 -2
  55. package/dist/chart/model/scale.model.d.ts +2 -0
  56. package/dist/chart/model/scale.model.js +11 -2
  57. package/dist/chart/utils/dom.utils.d.ts +7 -0
  58. package/dist/chart/utils/dom.utils.js +12 -0
  59. package/dist/chart/utils/linkedList.utils.d.ts +3 -3
  60. package/dist/chart/utils/linkedList.utils.js +55 -57
  61. package/dist/dxchart.min.js +4 -4
  62. package/dist/index.d.ts +2 -1
  63. package/dist/index.js +2 -8
  64. package/package.json +10 -4
@@ -7,25 +7,58 @@ import { BehaviorSubject } from 'rxjs';
7
7
  import { ChartBaseElement } from '../../model/chart-base-element';
8
8
  import { LinkedList, ListNode } from '../../utils/linkedList.utils';
9
9
  export class DynamicObjectsModel extends ChartBaseElement {
10
- constructor() {
10
+ constructor(canvasModel) {
11
11
  super();
12
- this.modelToObjectMap = new Map();
12
+ this.canvasModel = canvasModel;
13
+ this.modelIdToObjectMap = new Map();
13
14
  this._objects = new BehaviorSubject({});
14
15
  }
16
+ /**
17
+ * @returns the `DynamicObject` itself and pane `LinkedList` where the object is stored.
18
+ *
19
+ */
20
+ getObjectInfoById(id) {
21
+ const obj = this.modelIdToObjectMap.get(id);
22
+ if (!obj) {
23
+ return undefined;
24
+ }
25
+ const paneId = obj.paneId;
26
+ const objects = this.objects;
27
+ const paneList = objects[paneId];
28
+ if (!paneList) {
29
+ return undefined;
30
+ }
31
+ return [obj, paneList];
32
+ }
33
+ /**
34
+ * @returns `DynamicObject` position in associated pane `LinkedList`
35
+ * @returns `-1` if an object was not found
36
+ *
37
+ */
38
+ getObjectPosition(id) {
39
+ const objInfo = this.getObjectInfoById(id);
40
+ if (!objInfo) {
41
+ return -1;
42
+ }
43
+ const [obj, paneList] = objInfo;
44
+ const targetNode = new ListNode(obj);
45
+ return paneList.getNodePosition(targetNode);
46
+ }
15
47
  /**
16
48
  * Adds an object from outside chart-core into model
17
49
  * @param obj
18
50
  * @param paneId
19
51
  */
20
- addObject(obj, paneId) {
52
+ addObject(obj) {
21
53
  var _a;
54
+ const paneId = obj.paneId;
22
55
  const objects = this.objects;
23
56
  const paneList = (_a = objects[paneId]) !== null && _a !== void 0 ? _a : new LinkedList();
24
57
  if (!Object.keys(objects).find(pane => pane === paneId)) {
25
58
  objects[paneId] = paneList;
26
59
  }
27
60
  paneList.insertAtEnd(obj);
28
- this.modelToObjectMap.set(obj.model, obj);
61
+ this.modelIdToObjectMap.set(obj.id, obj);
29
62
  this.setDynamicObjects(objects);
30
63
  }
31
64
  /**
@@ -33,36 +66,61 @@ export class DynamicObjectsModel extends ChartBaseElement {
33
66
  * @param model
34
67
  * @param paneId
35
68
  */
36
- removeObject(model, paneId) {
37
- const objects = this.objects;
38
- const paneList = objects[paneId];
39
- const obj = this.modelToObjectMap.get(model);
40
- if (paneList && obj) {
41
- const targetNode = new ListNode(obj);
42
- const targetPos = paneList.getNodePosition(targetNode);
43
- paneList.removeAt(targetPos);
44
- this.modelToObjectMap.delete(model);
45
- if (paneList.size() === 0) {
46
- delete objects[paneId];
47
- }
48
- this.setDynamicObjects(objects);
69
+ removeObject(id) {
70
+ const objInfo = this.getObjectInfoById(id);
71
+ if (!objInfo) {
72
+ return;
73
+ }
74
+ const [obj, paneList] = objInfo;
75
+ const targetNode = new ListNode(obj);
76
+ const targetPos = paneList.getNodePosition(targetNode);
77
+ paneList.removeAt(targetPos);
78
+ this.modelIdToObjectMap.delete(id);
79
+ if (paneList.size() === 0) {
80
+ delete this.objects[obj.paneId];
49
81
  }
82
+ this.setDynamicObjects(this.objects);
83
+ }
84
+ /**
85
+ * Moves the object inside the associated LinkedList to the specified position
86
+ */
87
+ moveToPosition(id, position) {
88
+ const objInfo = this.getObjectInfoById(id);
89
+ if (!objInfo) {
90
+ return;
91
+ }
92
+ const [obj, paneList] = objInfo;
93
+ const node = new ListNode(obj);
94
+ const currentPos = paneList.getNodePosition(node);
95
+ if (currentPos === position) {
96
+ return;
97
+ }
98
+ if (currentPos < position) {
99
+ paneList.insertAt(position, obj);
100
+ paneList.removeAt(currentPos);
101
+ }
102
+ else {
103
+ paneList.removeAt(currentPos);
104
+ paneList.insertAt(position, obj);
105
+ }
106
+ this.setDynamicObjects(this.objects);
50
107
  }
51
108
  /**
52
109
  * Moves the object inside the drawing order so it's being drawn before the other elements
53
110
  * @param paneId
54
111
  * @param listNode
55
112
  */
56
- bringToFront(paneId, listNode) {
57
- const list = this.objects[paneId];
58
- if (list) {
59
- const targetPos = list.getNodePosition(listNode);
60
- if (targetPos >= 0 && targetPos < list.size()) {
61
- const nodeToReplace = list.removeAt(targetPos);
62
- if (nodeToReplace) {
63
- list.insertAtEnd(nodeToReplace.data);
64
- }
65
- }
113
+ bringToFront(id) {
114
+ const objInfo = this.getObjectInfoById(id);
115
+ if (!objInfo) {
116
+ return;
117
+ }
118
+ const [obj, paneList] = objInfo;
119
+ const targetNode = new ListNode(obj);
120
+ const targetPos = paneList.getNodePosition(targetNode);
121
+ if (targetPos >= 0 && targetPos < paneList.size()) {
122
+ paneList.removeAt(targetPos);
123
+ paneList.insertAtEnd(obj);
66
124
  this.setDynamicObjects(this.objects);
67
125
  }
68
126
  }
@@ -71,16 +129,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
71
129
  * @param paneId
72
130
  * @param listNode
73
131
  */
74
- bringToBack(paneId, listNode) {
75
- const list = this.objects[paneId];
76
- if (list) {
77
- const targetPos = list.getNodePosition(listNode);
78
- if (targetPos > 0 && targetPos <= list.size()) {
79
- const nodeToReplace = list.removeAt(targetPos);
80
- if (nodeToReplace) {
81
- list.insertAt(0, nodeToReplace === null || nodeToReplace === void 0 ? void 0 : nodeToReplace.data);
82
- }
83
- }
132
+ bringToBack(id) {
133
+ const objInfo = this.getObjectInfoById(id);
134
+ if (!objInfo) {
135
+ return;
136
+ }
137
+ const [obj, paneList] = objInfo;
138
+ const targetNode = new ListNode(obj);
139
+ const targetPos = paneList.getNodePosition(targetNode);
140
+ if (targetPos > 0 && targetPos <= paneList.size()) {
141
+ paneList.removeAt(targetPos);
142
+ paneList.insertAt(0, obj);
84
143
  this.setDynamicObjects(this.objects);
85
144
  }
86
145
  }
@@ -89,16 +148,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
89
148
  * @param obj
90
149
  * @param paneId
91
150
  */
92
- moveForward(paneId, listNode) {
93
- const list = this.objects[paneId];
94
- if (list) {
95
- const targetPos = list.getNodePosition(listNode);
96
- if (targetPos >= 0 && targetPos < list.size()) {
97
- const nodeToReplace = list.removeAt(targetPos);
98
- if (nodeToReplace) {
99
- list.insertAt(targetPos + 1, nodeToReplace.data);
100
- }
101
- }
151
+ moveForward(id) {
152
+ const objInfo = this.getObjectInfoById(id);
153
+ if (!objInfo) {
154
+ return;
155
+ }
156
+ const [obj, paneList] = objInfo;
157
+ const targetNode = new ListNode(obj);
158
+ const targetPos = paneList.getNodePosition(targetNode);
159
+ if (targetPos >= 0 && targetPos + 1 < paneList.size()) {
160
+ paneList.removeAt(targetPos);
161
+ paneList.insertAt(targetPos + 1, obj);
102
162
  this.setDynamicObjects(this.objects);
103
163
  }
104
164
  }
@@ -107,16 +167,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
107
167
  * @param obj
108
168
  * @param paneId
109
169
  */
110
- moveBackwards(paneId, listNode) {
111
- const list = this.objects[paneId];
112
- if (list) {
113
- const targetPos = list.getNodePosition(listNode);
114
- if (targetPos > 0 && targetPos <= list.size()) {
115
- const nodeToReplace = list.removeAt(targetPos);
116
- if (nodeToReplace) {
117
- list.insertAt(targetPos - 1, nodeToReplace === null || nodeToReplace === void 0 ? void 0 : nodeToReplace.data);
118
- }
119
- }
170
+ moveBackwards(id) {
171
+ const objInfo = this.getObjectInfoById(id);
172
+ if (!objInfo) {
173
+ return;
174
+ }
175
+ const [obj, paneList] = objInfo;
176
+ const targetNode = new ListNode(obj);
177
+ const targetPos = paneList.getNodePosition(targetNode);
178
+ if (targetPos > 0 && targetPos < paneList.size()) {
179
+ paneList.removeAt(targetPos);
180
+ paneList.insertAt(targetPos - 1, obj);
120
181
  this.setDynamicObjects(this.objects);
121
182
  }
122
183
  }
@@ -132,5 +193,6 @@ export class DynamicObjectsModel extends ChartBaseElement {
132
193
  */
133
194
  setDynamicObjects(objects) {
134
195
  this._objects.next(objects);
196
+ this.canvasModel.fireDraw();
135
197
  }
136
198
  }
@@ -40,9 +40,11 @@ export class GridDrawer {
40
40
  * @param {CanvasRenderingContext2D} ctx - The 2D rendering context of the canvas element.
41
41
  */
42
42
  drawZeroLine(ctx) {
43
+ const yAxisLabels = this.yLabelsProvider();
43
44
  if (this.getBaseline &&
44
45
  this.yAxisState.type === 'percent' &&
45
- this.yAxisState.zeroPercentLine) {
46
+ this.yAxisState.zeroPercentLine &&
47
+ yAxisLabels.length) {
46
48
  const bounds = this.xBoundsProvider();
47
49
  const y = floor(this.getBaseline());
48
50
  ctx.beginPath();
@@ -7,6 +7,7 @@ import { CanvasElement } from '../../../canvas/canvas-bounds-container';
7
7
  import { ChartBaseElement } from '../../../model/chart-base-element';
8
8
  import { DataSeriesModel, VisualSeriesPoint, defaultValueFormatter, } from '../../../model/data-series.model';
9
9
  import { mergeHighLow } from '../../../model/scaling/auto-scale.model';
10
+ import { uuid } from '../../../utils/uuid.utils';
10
11
  import { createYExtentFormatters } from '../../chart/price.formatter';
11
12
  export class YExtentComponent extends ChartBaseElement {
12
13
  constructor(paneUUID, idx, paneComponent, chartBaseModel, canvasBoundsContainer, hitTestController, dynamicObjectsCanvasModel, scale, createYAxisComponent, dragNDrop, dataSeries = new Set(), formatters = {
@@ -66,7 +67,7 @@ export class YExtentComponent extends ChartBaseElement {
66
67
  * @returns {DataSeriesModel} - The newly created DataSeriesModel object.
67
68
  */
68
69
  createDataSeries() {
69
- const series = new DataSeriesModel(this, this.hitTestController.getNewDataSeriesHitTestId());
70
+ const series = new DataSeriesModel(this, uuid(), this.hitTestController.getNewDataSeriesHitTestId());
70
71
  series.toVisualPoints = this.toVisualPoints;
71
72
  return series;
72
73
  }
@@ -32,7 +32,7 @@ export class PaneHitTestController {
32
32
  * @returns {DataSeriesModel | undefined} - The data series with the given ID, or undefined if it does not exist.
33
33
  */
34
34
  lookup(id) {
35
- const result = this.allDataSeries.find(d => d.id === id);
35
+ const result = this.allDataSeries.find(d => d.htId === id);
36
36
  return result;
37
37
  }
38
38
  /**
@@ -41,7 +41,7 @@ export class PaneHitTestController {
41
41
  * @returns {void}
42
42
  */
43
43
  onHover(model) {
44
- this.allDataSeries.forEach(d => (d.hovered = d.id === (model === null || model === void 0 ? void 0 : model.id)));
44
+ this.allDataSeries.forEach(d => (d.hovered = d.htId === (model === null || model === void 0 ? void 0 : model.htId)));
45
45
  this.canvasModel.fireDraw();
46
46
  }
47
47
  onMouseDown(model) {
@@ -21,9 +21,11 @@ export declare class VolumesComponent extends ChartBaseElement {
21
21
  private canvasModel;
22
22
  private canvasBoundsContainer;
23
23
  private config;
24
+ private dynamicObjectsComponent;
24
25
  separateVolumes: SeparateVolumesComponent;
25
26
  volumesColorByChartTypeMap: Partial<Record<BarType, VolumeColorResolver>>;
26
27
  volumesModel: VolumesModel;
28
+ private readonly volumesDrawer;
27
29
  volumeVisibilityChangedSubject: BehaviorSubject<boolean>;
28
30
  volumeIsSeparateModeChangedSubject: BehaviorSubject<boolean>;
29
31
  constructor(canvasModel: CanvasModel, chartComponent: ChartComponent, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, drawingManager: DrawingManager, config: FullChartConfig, paneManager: PaneManager, dynamicObjectsComponent: DynamicObjectsComponent);
@@ -56,4 +58,5 @@ export declare class VolumesComponent extends ChartBaseElement {
56
58
  * @returns {void}
57
59
  */
58
60
  setVisible(visible?: boolean): void;
61
+ private addVolumesToDynamicObjects;
59
62
  }
@@ -9,13 +9,14 @@ import { ChartBaseElement } from '../../model/chart-base-element';
9
9
  import { SeparateVolumesComponent } from './separate-volumes.component';
10
10
  import { resolveColorForBar, resolveColorForCandle, resolveColorForLine } from './volume-color-resolvers.functions';
11
11
  import { VolumesDrawer } from './volumes.drawer';
12
- import { VolumesModel } from './volumes.model';
12
+ import { VOLUMES_UUID, VolumesModel } from './volumes.model';
13
13
  export class VolumesComponent extends ChartBaseElement {
14
14
  constructor(canvasModel, chartComponent, scale, canvasBoundsContainer, drawingManager, config, paneManager, dynamicObjectsComponent) {
15
15
  super();
16
16
  this.canvasModel = canvasModel;
17
17
  this.canvasBoundsContainer = canvasBoundsContainer;
18
18
  this.config = config;
19
+ this.dynamicObjectsComponent = dynamicObjectsComponent;
19
20
  this.volumesColorByChartTypeMap = {};
20
21
  this.volumeVisibilityChangedSubject = new BehaviorSubject(false);
21
22
  this.volumeIsSeparateModeChangedSubject = new BehaviorSubject(false);
@@ -23,8 +24,8 @@ export class VolumesComponent extends ChartBaseElement {
23
24
  this.volumesModel = volumesModel;
24
25
  this.addChildEntity(volumesModel);
25
26
  this.separateVolumes = new SeparateVolumesComponent(chartComponent, drawingManager, config, volumesModel, paneManager);
26
- const volumesDrawer = new VolumesDrawer(config, this.volumesModel, chartComponent.chartModel, () => { var _a, _b; return (this.config.components.volumes.showSeparately ? (_b = (_a = this.separateVolumes.pane) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : scale : scale); }, this.volumesColorByChartTypeMap, () => true);
27
- dynamicObjectsComponent.model.addObject({ drawer: volumesDrawer, model: volumesModel }, CHART_UUID);
27
+ this.volumesDrawer = new VolumesDrawer(config, this.volumesModel, chartComponent.chartModel, () => { var _a, _b; return (this.config.components.volumes.showSeparately ? (_b = (_a = this.separateVolumes.pane) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : scale : scale); }, this.volumesColorByChartTypeMap, () => true);
28
+ config.components.volumes.visible && this.addVolumesToDynamicObjects();
28
29
  this.addChildEntity(this.separateVolumes);
29
30
  this.registerDefaultVolumeColorResolvers();
30
31
  this.volumeVisibilityChangedSubject.next(config.components.volumes.visible);
@@ -83,7 +84,10 @@ export class VolumesComponent extends ChartBaseElement {
83
84
  setVisible(visible = true) {
84
85
  this.config.components.volumes.visible = visible;
85
86
  this.volumeVisibilityChangedSubject.next(visible);
86
- if (this.config.components.volumes.showSeparately === true) {
87
+ visible
88
+ ? this.addVolumesToDynamicObjects()
89
+ : this.dynamicObjectsComponent.model.removeObject(this.volumesModel.id);
90
+ if (this.config.components.volumes.showSeparately) {
87
91
  if (visible) {
88
92
  this.separateVolumes.activateSeparateVolumes();
89
93
  this.volumeIsSeparateModeChangedSubject.next(true);
@@ -96,4 +100,17 @@ export class VolumesComponent extends ChartBaseElement {
96
100
  this.canvasBoundsContainer.recalculatePanesHeightRatios();
97
101
  this.canvasModel.fireDraw();
98
102
  }
103
+ addVolumesToDynamicObjects() {
104
+ // check if the volumes dynamic object is already added
105
+ const position = this.dynamicObjectsComponent.model.getObjectPosition(this.volumesModel.id);
106
+ if (position !== -1) {
107
+ return;
108
+ }
109
+ this.dynamicObjectsComponent.model.addObject({
110
+ id: this.volumesModel.id,
111
+ paneId: this.config.components.volumes.showSeparately ? VOLUMES_UUID : CHART_UUID,
112
+ drawer: this.volumesDrawer,
113
+ model: this.volumesModel,
114
+ });
115
+ }
99
116
  }
@@ -8,9 +8,11 @@ import { ChartBaseElement } from '../../model/chart-base-element';
8
8
  import { ScaleModel } from '../../model/scale.model';
9
9
  import { HighLowProvider } from '../../model/scaling/auto-scale.model';
10
10
  import { ChartComponent } from '../chart/chart.component';
11
+ export declare const VOLUMES_UUID = "volumes";
11
12
  export declare class VolumesModel extends ChartBaseElement {
12
13
  private chartComponent;
13
14
  private scale;
15
+ readonly id = "volumes";
14
16
  volumeMax: BehaviorSubject<number>;
15
17
  highLowProvider: HighLowProvider;
16
18
  constructor(chartComponent: ChartComponent, scale: ScaleModel);
@@ -7,11 +7,13 @@ import { BehaviorSubject, merge } from 'rxjs';
7
7
  import { ChartBaseElement } from '../../model/chart-base-element';
8
8
  import { firstOf, maxMin } from '../../utils/array.utils';
9
9
  const volumeMaxMinFn = maxMin(candle => candle.candle.volume);
10
+ export const VOLUMES_UUID = 'volumes';
10
11
  export class VolumesModel extends ChartBaseElement {
11
12
  constructor(chartComponent, scale) {
12
13
  super();
13
14
  this.chartComponent = chartComponent;
14
15
  this.scale = scale;
16
+ this.id = VOLUMES_UUID;
15
17
  // max volume in all data series
16
18
  this.volumeMax = new BehaviorSubject(0);
17
19
  this.highLowProvider = {
@@ -56,8 +56,8 @@ export class XAxisComponent extends ChartBaseElement {
56
56
  this.xAxisLabelsGenerator.generateLabels();
57
57
  }));
58
58
  this.addRxSubscription(this.chartComponent.chartModel.candlesPrependSubject
59
- .pipe(filter(({ preparedCandles }) => preparedCandles.length !== 0), map(({ preparedCandles }) => {
60
- return this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0, preparedCandles.length);
59
+ .pipe(filter(({ prependedCandles }) => prependedCandles.length !== 0), map(({ prependedCandles }) => {
60
+ return this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0, prependedCandles.length);
61
61
  }))
62
62
  .subscribe(newCandles => {
63
63
  //@ts-ignore
@@ -4,8 +4,9 @@
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
6
  import { PriceMovement } from '../../model/candle-series.model';
7
- import { FullChartColors, YAxisLabelsColors } from '../../chart.config';
7
+ import { FullChartColors, YAxisConfig, YAxisLabelsColors } from '../../chart.config';
8
8
  export declare const DEFAULT_LABEL_COLOR = "#FF00FF";
9
+ export declare function getPlainLabelTextColor(colorsConfig: FullChartColors, textColor: string, invertedTextColor: string, yAxisState: YAxisConfig): string;
9
10
  export declare const getPrimaryLabelTextColor: (lastPriceMovement: PriceMovement, colors: YAxisLabelsColors) => string;
10
11
  export declare const resolveColorForBar: (priceMovement: PriceMovement, colors: FullChartColors) => string;
11
12
  export declare const resolveColorForLine: (priceMovement: PriceMovement, colors: FullChartColors) => string;
@@ -3,7 +3,24 @@
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
+ import { getLabelTextColorByBackgroundColor } from '../../utils/canvas/canvas-text-functions.utils';
6
7
  export const DEFAULT_LABEL_COLOR = '#FF00FF';
8
+ export function getPlainLabelTextColor(colorsConfig, textColor, invertedTextColor, yAxisState) {
9
+ // `plain` label is transparent, so to calculate text color
10
+ // we need to go down to draw hierarchy
11
+ // the next is YAxis bg color
12
+ const yAxisBGColor = colorsConfig.yAxis.backgroundColor;
13
+ // if yAxis bg color is transparent, then we need to check chart area background color
14
+ const plainChartBGColor = colorsConfig.chartAreaTheme.backgroundColor;
15
+ // when chart area bg color is gradient, then we need to check which side yAxis is drawn
16
+ // because color on the right side and left side is different
17
+ const leftChartBGColor = colorsConfig.chartAreaTheme.backgroundGradientTopColor;
18
+ const rightChartBGColor = colorsConfig.chartAreaTheme.backgroundGradientBottomColor;
19
+ const gradientChartBGColor = yAxisState.align === 'left' ? leftChartBGColor : rightChartBGColor;
20
+ const chartBGColor = colorsConfig.chartAreaTheme.backgroundMode === 'gradient' ? gradientChartBGColor : plainChartBGColor;
21
+ const bgColor = yAxisBGColor === 'transparent' ? chartBGColor : yAxisBGColor;
22
+ return getLabelTextColorByBackgroundColor(bgColor, textColor, invertedTextColor);
23
+ }
7
24
  export const getPrimaryLabelTextColor = (lastPriceMovement, colors) => {
8
25
  if (lastPriceMovement === 'down') {
9
26
  return colors.lastPrice.textNegative;
@@ -12,8 +12,8 @@ export declare class DataSeriesYAxisLabelsProvider implements YAxisLabelsProvide
12
12
  private series;
13
13
  private config;
14
14
  yAxisBoundsProvider: BoundsProvider;
15
- axisState?: YAxisConfig | undefined;
16
- constructor(series: DataSeriesModel, config: DataSeriesConfig, yAxisBoundsProvider: BoundsProvider, axisState?: YAxisConfig | undefined);
15
+ axisState: YAxisConfig;
16
+ constructor(series: DataSeriesModel, config: DataSeriesConfig, yAxisBoundsProvider: BoundsProvider, axisState: YAxisConfig);
17
17
  /**
18
18
  * Returns an array of LabelGroup objects that contain VisualYAxisLabel objects.
19
19
  * The labels are unordered and are based on the last data series point or the last visual series point, depending on the configuration.
@@ -21,32 +21,34 @@ export class DataSeriesYAxisLabelsProvider {
21
21
  */
22
22
  getUnorderedLabels() {
23
23
  const visible = this.config.visible;
24
- if (visible) {
25
- const getLastPointForLabel = this.config.labelLastValue === 'series'
26
- ? this.series.getLastDataSeriesPoint
27
- : this.series.getLastVisualSeriesPoint;
28
- const bounds = this.yAxisBoundsProvider();
29
- const mode = this.config.labelMode;
30
- const appearanceType = this.config.labelAppearanceType;
31
- const lastPoint = getLastPointForLabel();
32
- if (lastPoint !== undefined) {
33
- const lastPointY = this.series.view.toY(lastPoint.close);
34
- if (isFinite(lastPointY)) {
35
- const label = this.series.valueFormatter(lastPoint.close);
36
- const drawConfig = this.getLabelDrawConfig();
37
- return [
38
- {
39
- labels: [
40
- Object.assign({ y: lastPointY, description: this.series.name, mode, labelType: appearanceType, labelText: label }, drawConfig),
41
- ],
42
- axisState: this.axisState,
43
- bounds,
44
- },
45
- ];
46
- }
47
- }
24
+ if (!visible) {
25
+ return [];
48
26
  }
49
- return [];
27
+ const getLastPointForLabel = this.config.labelLastValue === 'series'
28
+ ? this.series.getLastDataSeriesPoint
29
+ : this.series.getLastVisualSeriesPoint;
30
+ const bounds = this.yAxisBoundsProvider();
31
+ const mode = this.config.labelMode;
32
+ const appearanceType = this.config.labelAppearanceType;
33
+ const lastPoint = getLastPointForLabel();
34
+ if (lastPoint === undefined) {
35
+ return [];
36
+ }
37
+ const lastPointY = this.series.view.toY(lastPoint.close);
38
+ if (!isFinite(lastPointY)) {
39
+ return [];
40
+ }
41
+ const label = this.series.valueFormatter(lastPoint.close);
42
+ const drawConfig = this.getLabelDrawConfig();
43
+ return [
44
+ {
45
+ labels: [
46
+ Object.assign({ y: lastPointY, description: this.series.name, mode, labelType: appearanceType, labelText: label }, drawConfig),
47
+ ],
48
+ axisState: this.axisState,
49
+ bounds,
50
+ },
51
+ ];
50
52
  }
51
53
  /**
52
54
  * Retrieves the `config` object from the `series` object and then retrieves the `paintConfig` object from the `config` object.
@@ -21,23 +21,34 @@ export function calcLabelsYCoordinates(points, labelHeight) {
21
21
  .filter(notEmpty)
22
22
  .sort(sortLabels); // sort labels in ascending order, top -> down
23
23
  const newCoordinates = new Array(formattedCoordinates.length);
24
- formattedCoordinates.forEach((current, idx) => {
25
- if (current === null) {
26
- return;
24
+ const lowestWeight = formattedCoordinates.reduce((acc, curr) => Math.min(acc, curr.labelWeight), Number.POSITIVE_INFINITY);
25
+ const lowestWeightIndex = formattedCoordinates.findIndex(x => x.labelWeight === lowestWeight);
26
+ for (let i = lowestWeightIndex; i >= 0; i--) {
27
+ const current = formattedCoordinates[i];
28
+ const prev = formattedCoordinates[i - 1];
29
+ if (!current) {
30
+ continue;
31
+ }
32
+ if (prev && prev.bottom > current.top) {
33
+ const paddingAdjust = Math.abs(prev.labelWeight - current.labelWeight) === 1 ? 2 : 0;
34
+ prev.bottom = current.top - paddingAdjust;
35
+ prev.top = prev.bottom - labelHeight;
36
+ }
37
+ newCoordinates[current.actualIndex] = (current.top + current.bottom) / 2;
38
+ }
39
+ for (let i = lowestWeightIndex; i < formattedCoordinates.length; i++) {
40
+ const current = formattedCoordinates[i];
41
+ const next = formattedCoordinates[i + 1];
42
+ if (!current) {
43
+ break;
27
44
  }
28
- const next = formattedCoordinates[idx + 1];
29
45
  if (next && next.top < current.bottom) {
30
- /**
31
- * adjust padding if weight diff is 1, used for countdown label padding
32
- * @doc-tags tricky
33
- */
34
- const paddingAdjust = next.labelWeight - current.labelWeight === 1 ? 2 : 0;
35
- const delta = current.bottom - next.top + paddingAdjust;
36
- next.top += delta;
37
- next.bottom += delta;
46
+ const paddingAdjust = Math.abs(next.labelWeight - current.labelWeight) === 1 ? 2 : 0;
47
+ next.top = current.bottom + paddingAdjust;
48
+ next.bottom = next.top + labelHeight;
38
49
  }
39
50
  newCoordinates[current.actualIndex] = (current.top + current.bottom) / 2;
40
- });
51
+ }
41
52
  return newCoordinates;
42
53
  }
43
54
  const toLabel = (point, index, labelHeight) => point
@@ -10,11 +10,11 @@ import { LabelGroup, YAxisLabelsProvider } from './y-axis-labels.model';
10
10
  import { LabelColorResolver } from '../y-axis.component';
11
11
  export declare class LastCandleLabelsProvider implements YAxisLabelsProvider {
12
12
  private chartModel;
13
- private fullConfig;
13
+ private chartConfig;
14
14
  private yAxisConfig;
15
15
  private lastCandleLabelsByChartType;
16
16
  private resolveLabelColorFn;
17
- constructor(chartModel: ChartModel, fullConfig: FullChartConfig, yAxisConfig: YAxisConfig, lastCandleLabelsByChartType: Partial<Record<DataSeriesType, LastCandleLabelHandler>>, resolveLabelColorFn: (chartType: DataSeriesType) => LabelColorResolver);
17
+ constructor(chartModel: ChartModel, chartConfig: FullChartConfig, yAxisConfig: YAxisConfig, lastCandleLabelsByChartType: Partial<Record<DataSeriesType, LastCandleLabelHandler>>, resolveLabelColorFn: (chartType: DataSeriesType) => LabelColorResolver);
18
18
  /**
19
19
  * Returns an array of LabelGroup objects that contain the labels for the yAxis of the chart.
20
20
  * @returns {LabelGroup[]} An array of LabelGroup objects that contain the labels for the yAxis of the chart.
@@ -29,7 +29,7 @@ export declare class LastCandleLabelsProvider implements YAxisLabelsProvider {
29
29
  /**
30
30
  * Returns the configuration object for drawing the label of the Y-axis.
31
31
  * @param {CandleSeriesModel} series - The series model for which the label configuration is to be returned.
32
- * @param {boolean} primary - A boolean value indicating whether the label is primary or not.
32
+ * @param {boolean} primary - A boolean value indicating whether the label is for the main series or not.
33
33
  * @returns {YAxisLabelDrawConfig} - The configuration object for drawing the label of the Y-axis.
34
34
  */
35
35
  private getLabelDrawConfig;