@devexperts/dxcharts-lite 2.5.8 → 2.6.1

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 (68) hide show
  1. package/dist/chart/__tests__/chart.test.js +5 -5
  2. package/dist/chart/__tests__/env.js +1 -1
  3. package/dist/chart/bootstrap.js +1 -1
  4. package/dist/chart/canvas/canvas-bounds-container.d.ts +1 -0
  5. package/dist/chart/canvas/canvas-bounds-container.js +28 -4
  6. package/dist/chart/chart.config.d.ts +10 -0
  7. package/dist/chart/chart.config.js +4 -2
  8. package/dist/chart/components/chart/candle-transformer.functions.js +1 -1
  9. package/dist/chart/components/chart/candle.functions.d.ts +1 -1
  10. package/dist/chart/components/chart/candle.functions.js +3 -2
  11. package/dist/chart/components/chart/chart.component.d.ts +29 -8
  12. package/dist/chart/components/chart/chart.component.js +33 -4
  13. package/dist/chart/components/chart/chart.model.d.ts +41 -4
  14. package/dist/chart/components/chart/chart.model.js +90 -16
  15. package/dist/chart/components/chart/fake-candles.js +2 -0
  16. package/dist/chart/components/chart/fake-visual-candle.d.ts +4 -4
  17. package/dist/chart/components/chart/fake-visual-candle.js +4 -4
  18. package/dist/chart/components/cross_tool/cross-tool.component.js +2 -2
  19. package/dist/chart/components/cross_tool/cross-tool.drawer.d.ts +3 -1
  20. package/dist/chart/components/cross_tool/cross-tool.drawer.js +4 -3
  21. package/dist/chart/components/cross_tool/cross-tool.model.d.ts +6 -6
  22. package/dist/chart/components/cross_tool/cross-tool.model.js +42 -11
  23. package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +3 -3
  24. package/dist/chart/components/high_low/high-low.drawer.js +1 -1
  25. package/dist/chart/components/pane/pane-manager.component.d.ts +5 -0
  26. package/dist/chart/components/pane/pane-manager.component.js +20 -0
  27. package/dist/chart/components/pane/pane.component.d.ts +9 -1
  28. package/dist/chart/components/pane/pane.component.js +16 -0
  29. package/dist/chart/components/volumes/separate-volumes.component.d.ts +1 -3
  30. package/dist/chart/components/volumes/separate-volumes.component.js +1 -3
  31. package/dist/chart/components/volumes/volumes.component.js +1 -1
  32. package/dist/chart/components/volumes/volumes.drawer.js +3 -3
  33. package/dist/chart/components/watermark/water-mark.component.d.ts +3 -12
  34. package/dist/chart/components/watermark/water-mark.component.js +1 -1
  35. package/dist/chart/components/x_axis/time/parser/time-formats-parser.functions.js +1 -1
  36. package/dist/chart/components/x_axis/x-axis-draw.functions.js +2 -2
  37. package/dist/chart/components/x_axis/x-axis-scale.handler.d.ts +1 -0
  38. package/dist/chart/components/x_axis/x-axis-scale.handler.js +39 -10
  39. package/dist/chart/components/x_axis/x-axis-time-labels.drawer.js +2 -2
  40. package/dist/chart/components/x_axis/x-axis.component.js +1 -1
  41. package/dist/chart/components/y_axis/y-axis-scale.handler.js +3 -3
  42. package/dist/chart/drawers/drawing-manager.d.ts +1 -1
  43. package/dist/chart/drawers/drawing-manager.js +0 -1
  44. package/dist/chart/inputhandlers/cross-event-producer.component.d.ts +22 -0
  45. package/dist/chart/inputhandlers/cross-event-producer.component.js +11 -1
  46. package/dist/chart/inputhandlers/hover-producer.component.d.ts +5 -3
  47. package/dist/chart/inputhandlers/hover-producer.component.js +78 -18
  48. package/dist/chart/inputhandlers/main-canvas-touch.handler.d.ts +10 -0
  49. package/dist/chart/inputhandlers/main-canvas-touch.handler.js +18 -0
  50. package/dist/chart/inputlisteners/canvas-input-listener.component.js +2 -7
  51. package/dist/chart/model/candle-series.model.js +1 -1
  52. package/dist/chart/model/candle.model.d.ts +3 -0
  53. package/dist/chart/model/candle.model.js +7 -1
  54. package/dist/chart/model/data-series.model.d.ts +3 -3
  55. package/dist/chart/model/data-series.model.js +1 -1
  56. package/dist/chart/model/scale.model.js +1 -1
  57. package/dist/chart/model/scaling/viewport.model.d.ts +2 -1
  58. package/dist/chart/model/scaling/viewport.model.js +6 -1
  59. package/dist/chart/model/time-zone.model.js +1 -3
  60. package/dist/chart/utils/candles-generator-ts.utils.d.ts +1 -0
  61. package/dist/chart/utils/candles-generator.utils.d.ts +1 -0
  62. package/dist/chart/utils/candles-generator.utils.js +2 -0
  63. package/dist/chart/utils/string.utils.d.ts +6 -0
  64. package/dist/chart/utils/string.utils.js +19 -0
  65. package/dist/chart/utils/types.utils.d.ts +9 -0
  66. package/dist/chart/utils/types.utils.js +6 -0
  67. package/dist/dxchart.min.js +4 -4
  68. package/package.json +1 -1
@@ -3,10 +3,10 @@
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 { Candle } from "../../model/candle.model";
7
- import { DataSeriesPoint, VisualSeriesPoint } from "../../model/data-series.model";
8
- import { Index } from "../../model/scaling/viewport.model";
9
- import VisualCandle from "../../model/visual-candle";
6
+ import { Candle } from '../../model/candle.model';
7
+ import { DataSeriesPoint, VisualSeriesPoint } from '../../model/data-series.model';
8
+ import { Index } from '../../model/scaling/viewport.model';
9
+ import VisualCandle from '../../model/visual-candle';
10
10
  /**
11
11
  * Generates fake candle for left and right "out of data range" zones.
12
12
  * Requires period to calculate the fake timestamp.
@@ -3,10 +3,10 @@
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 { nameDirection } from "../../model/candle.model";
7
- import { VisualSeriesPoint } from "../../model/data-series.model";
8
- import VisualCandle from "../../model/visual-candle";
9
- import { DEFAULT_PERIOD, fakeCandle, fakeDataPoint } from "./fake-candles";
6
+ import { nameDirection } from '../../model/candle.model';
7
+ import { VisualSeriesPoint } from '../../model/data-series.model';
8
+ import VisualCandle from '../../model/visual-candle';
9
+ import { DEFAULT_PERIOD, fakeCandle, fakeDataPoint } from './fake-candles';
10
10
  /**
11
11
  * Generates fake candle for left and right "out of data range" zones.
12
12
  * Requires period to calculate the fake timestamp.
@@ -22,11 +22,11 @@ export class CrossToolComponent extends ChartBaseElement {
22
22
  this.drawingManager = drawingManager;
23
23
  this.paneManager = paneManager;
24
24
  this.crossToolTypeDrawers = {};
25
- this.model = new CrossToolModel(config.components.crossTool, this.crossToolCanvasModel, crossEventProducer, hoverProducer);
25
+ this.model = new CrossToolModel(config.components.crossTool, this.crossToolCanvasModel, crossEventProducer, hoverProducer, this.canvasBoundsContainer);
26
26
  this.addChildEntity(this.model);
27
27
  const clearCanvasDrawer = new ClearCanvasDrawer(this.crossToolCanvasModel);
28
28
  this.registerDefaultDrawerTypes();
29
- const crossToolDrawer = new CrossToolDrawer(this.model, this.crossToolCanvasModel, this.crossToolTypeDrawers);
29
+ const crossToolDrawer = new CrossToolDrawer(this.model, this.config, this.crossToolCanvasModel, this.crossToolTypeDrawers);
30
30
  const compositeDrawer = new CompositeDrawer();
31
31
  compositeDrawer.addDrawer(clearCanvasDrawer, 'CLEAR_CANVAS');
32
32
  compositeDrawer.addDrawer(crossToolDrawer, 'CROSS_TOOL_DRAWER');
@@ -6,14 +6,16 @@
6
6
  import { CanvasModel } from '../../model/canvas.model';
7
7
  import { Drawer } from '../../drawers/drawing-manager';
8
8
  import { CrossToolHover, CrossToolModel, CrossToolType } from './cross-tool.model';
9
+ import { FullChartConfig } from '../../chart.config';
9
10
  export interface CrossToolTypeDrawer {
10
11
  draw: (ctx: CanvasRenderingContext2D, hover: CrossToolHover) => void;
11
12
  }
12
13
  export declare class CrossToolDrawer implements Drawer {
13
14
  private model;
15
+ private config;
14
16
  private crossToolCanvasModel;
15
17
  private readonly crossToolTypeDrawers;
16
- constructor(model: CrossToolModel, crossToolCanvasModel: CanvasModel, crossToolTypeDrawers: Record<CrossToolType, CrossToolTypeDrawer>);
18
+ constructor(model: CrossToolModel, config: FullChartConfig, crossToolCanvasModel: CanvasModel, crossToolTypeDrawers: Record<CrossToolType, CrossToolTypeDrawer>);
17
19
  /**
18
20
  * Draws the cross tool on the canvas.
19
21
  * @function
@@ -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
  export class CrossToolDrawer {
7
- constructor(model, crossToolCanvasModel, crossToolTypeDrawers) {
7
+ constructor(model, config, crossToolCanvasModel, crossToolTypeDrawers) {
8
8
  this.model = model;
9
+ this.config = config;
9
10
  this.crossToolCanvasModel = crossToolCanvasModel;
10
11
  this.crossToolTypeDrawers = crossToolTypeDrawers;
11
12
  }
@@ -18,12 +19,12 @@ export class CrossToolDrawer {
18
19
  * @returns {void}
19
20
  */
20
21
  draw() {
21
- const drawer = this.crossToolTypeDrawers[this.model.type];
22
+ const drawer = this.crossToolTypeDrawers[this.config.components.crossTool.type];
22
23
  if (drawer) {
23
24
  this.model.currentHover && drawer.draw(this.crossToolCanvasModel.ctx, this.model.currentHover);
24
25
  }
25
26
  else {
26
- console.error(`No cross tool drawer type registered for drawer type ${this.model.type}`);
27
+ console.error(`No cross tool drawer type registered for drawer type ${this.config.components.crossTool.type}`);
27
28
  }
28
29
  }
29
30
  /**
@@ -9,6 +9,7 @@ import { CrossEventProducerComponent } from '../../inputhandlers/cross-event-pro
9
9
  import { Hover, HoverProducerComponent } from '../../inputhandlers/hover-producer.component';
10
10
  import { CanvasModel } from '../../model/canvas.model';
11
11
  import { ChartBaseElement } from '../../model/chart-base-element';
12
+ import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
12
13
  export type CrossToolType = 'cross-and-labels' | 'only-labels' | 'none' | string;
13
14
  export interface CrossToolHover {
14
15
  x: number;
@@ -21,11 +22,11 @@ export declare class CrossToolModel extends ChartBaseElement {
21
22
  private crossToolCanvasModel;
22
23
  private crossEventProducer;
23
24
  private hoverProducer;
25
+ private canvasBoundsContainer;
24
26
  currentHoverSubject: BehaviorSubject<CrossToolHover | null>;
25
27
  get currentHover(): CrossToolHover | null;
26
28
  set currentHover(value: CrossToolHover | null);
27
- type: CrossToolType;
28
- constructor(config: Required<ChartConfigComponentsCrossTool>, crossToolCanvasModel: CanvasModel, crossEventProducer: CrossEventProducerComponent, hoverProducer: HoverProducerComponent);
29
+ constructor(config: Required<ChartConfigComponentsCrossTool>, crossToolCanvasModel: CanvasModel, crossEventProducer: CrossEventProducerComponent, hoverProducer: HoverProducerComponent, canvasBoundsContainer: CanvasBoundsContainer);
29
30
  /**
30
31
  * Sets the type of the CrossTool object.
31
32
  *
@@ -35,9 +36,7 @@ export declare class CrossToolModel extends ChartBaseElement {
35
36
  setType(type: CrossToolType): void;
36
37
  /**
37
38
  * Method to activate the cross tool.
38
- * It subscribes to the canvasInputListener's mouse move event and fires the draw event.
39
- * It also subscribes to the eventBus's hover and close hover events and updates the hover and fires the draw event accordingly.
40
- * It also subscribes to the chartModel's candlesSetSubject and timeZoneModel's observeTimeZoneChanged events and recalculates the cross tool X formatter.
39
+ * It subscribes to the hoverProducer's hover event and updates the crosstool.
41
40
  */
42
41
  protected doActivate(): void;
43
42
  /**
@@ -59,5 +58,6 @@ export declare class CrossToolModel extends ChartBaseElement {
59
58
  * @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
60
59
  * @returns {void}
61
60
  */
62
- updateHover(hover: Hover, magnetTarget?: import("./cross-tool.component").MagnetTarget): void;
61
+ updateCrossTool(hover: Hover, magnetTarget?: import("./cross-tool.component").MagnetTarget): void;
62
+ private updateCrossToolMobile;
63
63
  }
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import { BehaviorSubject } from 'rxjs';
7
7
  import { ChartBaseElement } from '../../model/chart-base-element';
8
- import { CHART_UUID } from '../../canvas/canvas-bounds-container';
8
+ import { CanvasElement, CHART_UUID } from '../../canvas/canvas-bounds-container';
9
+ import { isMobile } from '../../utils/device/browser.utils';
9
10
  export class CrossToolModel extends ChartBaseElement {
10
11
  get currentHover() {
11
12
  return this.currentHoverSubject.getValue();
@@ -13,16 +14,15 @@ export class CrossToolModel extends ChartBaseElement {
13
14
  set currentHover(value) {
14
15
  this.currentHoverSubject.next(value);
15
16
  }
16
- constructor(config, crossToolCanvasModel, crossEventProducer, hoverProducer) {
17
+ constructor(config, crossToolCanvasModel, crossEventProducer, hoverProducer, canvasBoundsContainer) {
17
18
  super();
18
19
  this.config = config;
19
20
  this.crossToolCanvasModel = crossToolCanvasModel;
20
21
  this.crossEventProducer = crossEventProducer;
21
22
  this.hoverProducer = hoverProducer;
23
+ this.canvasBoundsContainer = canvasBoundsContainer;
22
24
  // the main hover object which will be presented on UI
23
25
  this.currentHoverSubject = new BehaviorSubject(null);
24
- this.type = 'cross-and-labels';
25
- this.type = config.type;
26
26
  }
27
27
  /**
28
28
  * Sets the type of the CrossTool object.
@@ -31,19 +31,17 @@ export class CrossToolModel extends ChartBaseElement {
31
31
  * @returns {void}
32
32
  */
33
33
  setType(type) {
34
- this.type = type;
34
+ this.config.type = type;
35
35
  }
36
36
  /**
37
37
  * Method to activate the cross tool.
38
- * It subscribes to the canvasInputListener's mouse move event and fires the draw event.
39
- * It also subscribes to the eventBus's hover and close hover events and updates the hover and fires the draw event accordingly.
40
- * It also subscribes to the chartModel's candlesSetSubject and timeZoneModel's observeTimeZoneChanged events and recalculates the cross tool X formatter.
38
+ * It subscribes to the hoverProducer's hover event and updates the crosstool.
41
39
  */
42
40
  doActivate() {
43
41
  super.doActivate();
44
42
  this.addRxSubscription(this.hoverProducer.hoverSubject.subscribe(hover => {
45
43
  if (this.crossEventProducer.crossSubject.getValue() !== null && hover !== null) {
46
- this.updateHover(hover);
44
+ isMobile() ? this.updateCrossToolMobile(hover) : this.updateCrossTool(hover);
47
45
  }
48
46
  else {
49
47
  this.currentHover = null;
@@ -56,7 +54,7 @@ export class CrossToolModel extends ChartBaseElement {
56
54
  * @private
57
55
  */
58
56
  fireDraw() {
59
- if (this.type !== 'none') {
57
+ if (this.config.type !== 'none') {
60
58
  this.crossToolCanvasModel.fireDraw();
61
59
  }
62
60
  }
@@ -74,7 +72,7 @@ export class CrossToolModel extends ChartBaseElement {
74
72
  * @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
75
73
  * @returns {void}
76
74
  */
77
- updateHover(hover, magnetTarget = this.config.magnetTarget) {
75
+ updateCrossTool(hover, magnetTarget = this.config.magnetTarget) {
78
76
  if (this.currentHover === null) {
79
77
  this.currentHover = { x: hover.x, y: 0, time: hover.timeFormatted, paneId: hover.paneId };
80
78
  }
@@ -110,4 +108,37 @@ export class CrossToolModel extends ChartBaseElement {
110
108
  this.currentHover.paneId = hover.paneId;
111
109
  this.currentHoverSubject.next(this.currentHover);
112
110
  }
111
+ updateCrossToolMobile(hover) {
112
+ var _a;
113
+ // mobile crosstool works only after long touch event
114
+ if (!this.hoverProducer.longTouchActivatedSubject.getValue()) {
115
+ return;
116
+ }
117
+ const { fixed, temp, isSet } = this.crossEventProducer.crossToolTouchInfo;
118
+ // long touch makes crosstool fixed and the further moving will place crosstool under the current hover coordinates (ordinary logic)
119
+ // if crosstool is already set (long touch end event happened) the moving of chart will move crosstool according to it's initial (fixed position)
120
+ if (!isSet) {
121
+ this.updateCrossTool(hover);
122
+ return;
123
+ }
124
+ // additional crosstool move logic
125
+ const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(hover.paneId));
126
+ const offset = 5;
127
+ // take a difference inbetween current hover and temporary crosstool coordinates
128
+ const xDiff = hover.x - temp.x;
129
+ const yDiff = hover.y - temp.y;
130
+ // apply the difference to the fixed coordinates
131
+ const rawX = fixed.x + xDiff;
132
+ const rawY = fixed.y + yDiff;
133
+ const paneYStart = paneBounds.y + offset;
134
+ const paneYEnd = paneBounds.y + paneBounds.height - offset;
135
+ // check for chart bounds and don't move crosstool outside of it
136
+ const x = rawX < offset ? offset : rawX > paneBounds.width - offset ? paneBounds.width - offset : rawX;
137
+ const y = rawY < paneYStart ? paneYStart : rawY > paneYEnd ? paneYEnd : rawY;
138
+ const crossToolHover = (_a = this.hoverProducer.createHover(x, y, hover.paneId)) !== null && _a !== void 0 ? _a : hover;
139
+ const updatedHover = Object.assign(Object.assign({}, crossToolHover), { x,
140
+ y });
141
+ this.crossEventProducer.crossToolHover = updatedHover;
142
+ this.updateCrossTool(updatedHover);
143
+ }
113
144
  }
@@ -3,7 +3,7 @@
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 { CanvasElement } from '../../../canvas/canvas-bounds-container';
6
+ import { CanvasElement, X_AXIS_MOBILE_PADDING } from '../../../canvas/canvas-bounds-container';
7
7
  import { avoidAntialiasing, drawRoundedRect } from '../../../utils/canvas/canvas-drawing-functions.utils';
8
8
  import { priceLabelDrawersMap } from '../../y_axis/price_labels/price-label.drawer';
9
9
  export class CrossAndLabelsDrawerType {
@@ -98,12 +98,12 @@ export class CrossAndLabelsDrawerType {
98
98
  const boxWidth = width + xLabelPaddingLeft + xLabelPaddingRight;
99
99
  const boxHeight = fontHeight + xLabelPaddingTop + xLabelPaddingBottom;
100
100
  const xBoxPos = Math.max(x - boxWidth / 2, 0);
101
- const yBoxPos = xAxis.y + xLabelMarginTop;
101
+ const yBoxPos = xAxis.y + xLabelMarginTop + X_AXIS_MOBILE_PADDING / 2;
102
102
  drawRoundedRect(ctx, xBoxPos, yBoxPos, boxWidth, boxHeight);
103
103
  // label
104
104
  ctx.fillStyle = crossToolColors.labelTextColor;
105
105
  const xTextPos = Math.max(x - width / 2, xLabelPaddingLeft);
106
- const yTextPos = xAxis.y + xLabelMarginTop + fontHeight + xLabelPaddingTop - 1; // -1 for vertical adjustment
106
+ const yTextPos = xAxis.y + xLabelMarginTop + fontHeight + X_AXIS_MOBILE_PADDING / 2 + xLabelPaddingTop - 1; // -1 for vertical adjustment
107
107
  ctx.fillText(labelText, xTextPos, yTextPos);
108
108
  ctx.restore();
109
109
  }
@@ -73,7 +73,7 @@ export class HighLowDrawer {
73
73
  */
74
74
  getMarkerText(yValue, type) {
75
75
  const formattedValue = this.chartModel.pane.regularFormatter(yValue);
76
- const prefix = type === 'high' ? 'H:' : 'L:';
76
+ const prefix = type === 'high' ? this.config.components.highLow.prefix.high : this.config.components.highLow.prefix.low;
77
77
  return `${prefix} ${formattedValue}`;
78
78
  }
79
79
  /**
@@ -24,6 +24,7 @@ import { PaneComponent } from './pane.component';
24
24
  import { DataSeriesModel } from '../../model/data-series.model';
25
25
  import { HitTestCanvasModel } from '../../model/hit-test-canvas.model';
26
26
  import { ChartResizeHandler } from '../../inputhandlers/chart-resize.handler';
27
+ export type MoveDataSeriesToPaneDirection = 'above' | 'below';
27
28
  export declare class PaneManager extends ChartBaseElement {
28
29
  private chartBaseModel;
29
30
  private dynamicObjectsCanvasModel;
@@ -107,6 +108,10 @@ export declare class PaneManager extends ChartBaseElement {
107
108
  * Shows a pane, use if the pane is hidden
108
109
  */
109
110
  showPane(paneUUID: string): void;
111
+ /**
112
+ * Move data series to a certain pane, or create a new one if no pane is found
113
+ */
114
+ moveDataSeriesToPane(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, paneUUID?: string, extent?: YExtentComponent, direction?: MoveDataSeriesToPaneDirection): void;
110
115
  /**
111
116
  * Adds cursors to the chart elements based on the provided uuid and cursor type.
112
117
  * @private
@@ -188,6 +188,26 @@ export class PaneManager extends ChartBaseElement {
188
188
  this.canvasBoundsContainer.showPaneBounds(paneUUID);
189
189
  this.recalculateState();
190
190
  }
191
+ /**
192
+ * Move data series to a certain pane, or create a new one if no pane is found
193
+ */
194
+ moveDataSeriesToPane(dataSeries, initialPane, initialExtent, paneUUID, extent, direction) {
195
+ const pane = paneUUID && this.panes[paneUUID];
196
+ if (!pane) {
197
+ const order = direction && direction === 'above' ? 0 : this.panesOrder.length;
198
+ const newPane = this.createPane(undefined, { order });
199
+ newPane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, newPane.mainExtent);
200
+ initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
201
+ return;
202
+ }
203
+ if (extent) {
204
+ pane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extent);
205
+ }
206
+ else {
207
+ pane.moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent);
208
+ }
209
+ initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
210
+ }
191
211
  /**
192
212
  * Adds cursors to the chart elements based on the provided uuid and cursor type.
193
213
  * @private
@@ -7,7 +7,7 @@ import { Subject } from 'rxjs';
7
7
  import { CanvasAnimation } from '../../animation/canvas-animation';
8
8
  import { CanvasBoundsContainer, HitBoundsTest } from '../../canvas/canvas-bounds-container';
9
9
  import { CursorHandler } from '../../canvas/cursor.handler';
10
- import { FullChartConfig } from '../../chart.config';
10
+ import { FullChartConfig, YAxisAlign } from '../../chart.config';
11
11
  import { DrawingManager } from '../../drawers/drawing-manager';
12
12
  import EventBus from '../../events/event-bus';
13
13
  import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-listener.component';
@@ -84,6 +84,14 @@ export declare class PaneComponent extends ChartBaseElement {
84
84
  private addCursors;
85
85
  createExtentComponent(options?: AtLeastOne<YExtentCreationOptions>): YExtentComponent;
86
86
  removeExtentComponent(extentComponent: YExtentComponent): void;
87
+ /**
88
+ * Create new pane extent and attach data series to it
89
+ */
90
+ moveDataSeriesToNewExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, align?: YAxisAlign): void;
91
+ /**
92
+ * Attach data series to existing y axis extent
93
+ */
94
+ moveDataSeriesToExistingExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, extentComponent: YExtentComponent): void;
87
95
  /**
88
96
  * This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
89
97
  * @private
@@ -149,6 +149,22 @@ export class PaneComponent extends ChartBaseElement {
149
149
  this.yExtentComponents.forEach((c, idx) => (c.idx = idx));
150
150
  this.canvasBoundsContainer.updateYAxisWidths();
151
151
  }
152
+ /**
153
+ * Create new pane extent and attach data series to it
154
+ */
155
+ moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent, align = 'right') {
156
+ const extent = this.createExtentComponent();
157
+ extent.yAxis.setYAxisAlign(align);
158
+ dataSeries.forEach(series => series.moveToExtent(extent));
159
+ initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
160
+ }
161
+ /**
162
+ * Attach data series to existing y axis extent
163
+ */
164
+ moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extentComponent) {
165
+ dataSeries.forEach(series => series.moveToExtent(extentComponent));
166
+ initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
167
+ }
152
168
  /**
153
169
  * This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
154
170
  * @private
@@ -4,7 +4,6 @@
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 { FullChartConfig } from '../../chart.config';
7
- import { DrawingManager } from '../../drawers/drawing-manager';
8
7
  import { ChartBaseElement } from '../../model/chart-base-element';
9
8
  import { Pixel, Unit } from '../../model/scaling/viewport.model';
10
9
  import { ChartComponent } from '../chart/chart.component';
@@ -13,13 +12,12 @@ import { PaneComponent } from '../pane/pane.component';
13
12
  import { VolumesModel } from './volumes.model';
14
13
  export declare class SeparateVolumesComponent extends ChartBaseElement {
15
14
  private chartComponent;
16
- private drawingManager;
17
15
  config: FullChartConfig;
18
16
  private volumesModel;
19
17
  private paneManager;
20
18
  static UUID: string;
21
19
  pane: PaneComponent | undefined;
22
- constructor(chartComponent: ChartComponent, drawingManager: DrawingManager, config: FullChartConfig, volumesModel: VolumesModel, paneManager: PaneManager);
20
+ constructor(chartComponent: ChartComponent, config: FullChartConfig, volumesModel: VolumesModel, paneManager: PaneManager);
23
21
  protected doActivate(): void;
24
22
  /**
25
23
  * Activates the separate volumes feature.
@@ -7,10 +7,9 @@ import { ChartBaseElement } from '../../model/chart-base-element';
7
7
  import { createCandlesOffsetProvider } from '../chart/data-series.high-low-provider';
8
8
  import { volumeFormatter } from './volumes.formatter';
9
9
  class SeparateVolumesComponent extends ChartBaseElement {
10
- constructor(chartComponent, drawingManager, config, volumesModel, paneManager) {
10
+ constructor(chartComponent, config, volumesModel, paneManager) {
11
11
  super();
12
12
  this.chartComponent = chartComponent;
13
- this.drawingManager = drawingManager;
14
13
  this.config = config;
15
14
  this.volumesModel = volumesModel;
16
15
  this.paneManager = paneManager;
@@ -53,7 +52,6 @@ class SeparateVolumesComponent extends ChartBaseElement {
53
52
  deactiveSeparateVolumes() {
54
53
  this.paneManager.removePane(SeparateVolumesComponent.UUID);
55
54
  delete this.pane;
56
- this.drawingManager.removeDrawerByName('UNDERLAY_VOLUMES_AREA');
57
55
  }
58
56
  /**
59
57
  * Converts a pixel value from the Y-axis of the scale model to the corresponding data value.
@@ -23,7 +23,7 @@ export class VolumesComponent extends ChartBaseElement {
23
23
  const volumesModel = new VolumesModel(chartComponent, scale);
24
24
  this.volumesModel = volumesModel;
25
25
  this.addChildEntity(volumesModel);
26
- this.separateVolumes = new SeparateVolumesComponent(chartComponent, drawingManager, config, volumesModel, paneManager);
26
+ this.separateVolumes = new SeparateVolumesComponent(chartComponent, config, volumesModel, paneManager);
27
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
28
  config.components.volumes.visible && this.syncVolumesDynamicObject();
29
29
  this.addChildEntity(this.separateVolumes);
@@ -101,12 +101,12 @@ export class VolumesDrawer {
101
101
  const width = nextX !== undefined ? nextX - x : floorToDPR(unitToPixels(vCandle.width, viewportModel.zoomX));
102
102
  if (this.config.components.volumes.showSeparately) {
103
103
  const y = floorToDPR(viewportModel.toY(vCandle.candle.volume));
104
- const height = floorToDPR(viewportModel.toY(0)) - y;
104
+ const height = ceilToDPR(viewportModel.toY(0)) - y;
105
105
  this.drawVolume(canvasModel, vCandle, x, y, width, height);
106
106
  }
107
107
  else {
108
108
  const zoomY = volumeMax / (fullVHeight / OVERLAY_VOLUME_TOTAL_HEIGHT_DIVISOR);
109
- const height = Math.max(unitToPixels(vCandle.candle.volume, zoomY), 2);
109
+ const height = Math.max(ceilToDPR(unitToPixels(vCandle.candle.volume, zoomY)), 2);
110
110
  const y = floorToDPR(bounds.y + fullVHeight - height);
111
111
  this.drawVolume(canvasModel, vCandle, x, y, width, height);
112
112
  }
@@ -139,7 +139,7 @@ export class VolumesDrawer {
139
139
  ctx.stroke();
140
140
  }
141
141
  else {
142
- ctx.fillRect(x, y, width, ceilToDPR(height));
142
+ ctx.fillRect(x, y, width, height);
143
143
  }
144
144
  }
145
145
  }
@@ -5,21 +5,12 @@
5
5
  */
6
6
  import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
7
7
  import { ChartBaseElement } from '../../model/chart-base-element';
8
- import { FullChartConfig } from '../../chart.config';
8
+ import { ChartConfigComponentsWaterMark, FullChartConfig } from '../../chart.config';
9
9
  import { CanvasModel } from '../../model/canvas.model';
10
10
  import { DrawingManager } from '../../drawers/drawing-manager';
11
11
  import EventBus from '../../events/event-bus';
12
12
  import { ChartModel } from '../chart/chart.model';
13
13
  import { PaneManager } from '../pane/pane-manager.component';
14
- export interface WaterMarkConfig {
15
- isVisible?: boolean;
16
- fontFamily?: string;
17
- firstRowFontSize?: number;
18
- firstRowBottomPadding?: number;
19
- secondRowFontSize?: number;
20
- secondRowBottomPadding?: number;
21
- thirdRowFontSize?: number;
22
- }
23
14
  export interface WaterMarkData {
24
15
  firstRow?: string;
25
16
  secondRow?: string;
@@ -55,11 +46,11 @@ export declare class WaterMarkComponent extends ChartBaseElement {
55
46
  private getWaterMarkData;
56
47
  /**
57
48
  * Sets the watermark configuration for the chart.
58
- * @param {WaterMarkConfig} watermarkConfig - The configuration object for the watermark.
49
+ * @param {ChartConfigComponentsWaterMark} watermarkConfig - The configuration object for the watermark.
59
50
  * @returns {void}
60
51
 
61
52
  */
62
- setWaterMarkConfig(watermarkConfig: WaterMarkConfig): void;
53
+ setWaterMarkConfig(watermarkConfig: ChartConfigComponentsWaterMark): void;
63
54
  /**
64
55
  * Sets the logo image to be used as a watermark.
65
56
  * @param {CanvasImageSource} img - The image to be used as a watermark.
@@ -56,7 +56,7 @@ export class WaterMarkComponent extends ChartBaseElement {
56
56
  }
57
57
  /**
58
58
  * Sets the watermark configuration for the chart.
59
- * @param {WaterMarkConfig} watermarkConfig - The configuration object for the watermark.
59
+ * @param {ChartConfigComponentsWaterMark} watermarkConfig - The configuration object for the watermark.
60
60
  * @returns {void}
61
61
 
62
62
  */
@@ -75,7 +75,7 @@ export const parseTimeFormatsFromKey = (format) => {
75
75
  };
76
76
  }
77
77
  else {
78
- console.warn(`${format} is not fit, check the documentation to see available formats https://webdev.prosp.devexperts.com:8095/docs/chart/x-axis`);
78
+ console.warn(`${format} is not fit, check the documentation to see available formats in dxchart-lite documentation.`);
79
79
  return null;
80
80
  }
81
81
  };
@@ -3,7 +3,7 @@
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 { CanvasElement } from '../../canvas/canvas-bounds-container';
6
+ import { CanvasElement, X_AXIS_MOBILE_PADDING } from '../../canvas/canvas-bounds-container';
7
7
  const DEFAULT_X_LABEL_PADDING = { x: 4, y: 4 };
8
8
  /**
9
9
  * Draws the label on X axis.
@@ -50,7 +50,7 @@ export function drawXAxisLabel(ctx, canvasBoundsContainer, config, label) {
50
50
  }
51
51
  ctx.fillStyle = label.color;
52
52
  const xTextPos = boxStart + DEFAULT_X_LABEL_PADDING.x;
53
- const yTextPos = xAxisBounds.y + offsetTop + fontSize; // -2 for vertical adjustment
53
+ const yTextPos = xAxisBounds.y + offsetTop + fontSize + X_AXIS_MOBILE_PADDING / 2;
54
54
  ctx.fillText(label.text, xTextPos, yTextPos);
55
55
  ctx.restore();
56
56
  }
@@ -24,6 +24,7 @@ export declare class XAxisScaleHandler extends ChartBaseElement {
24
24
  private hitTest;
25
25
  private hitTestCanvasModel;
26
26
  lastXStart: Unit;
27
+ lastXEnd: Unit;
27
28
  lastXWidth: Unit;
28
29
  lastXPxWidth: Pixel;
29
30
  private dblClickCallback;
@@ -6,6 +6,8 @@
6
6
  import { ChartBaseElement } from '../../model/chart-base-element';
7
7
  import { CanvasElement } from '../../canvas/canvas-bounds-container';
8
8
  import { DragNDropXComponent } from '../dran-n-drop_helper/drag-n-drop-x.component';
9
+ // if you drag full X width from left to right - you will have x3 zoom, and vice-versa
10
+ const FULL_X_WIDTH_ZOOM_FACTOR = 3;
9
11
  /**
10
12
  * Handles the mouse drag on X axis - to zoom the viewport horizontally.
11
13
  * @doc-tags scaling,zoom,viewport
@@ -21,10 +23,12 @@ export class XAxisScaleHandler extends ChartBaseElement {
21
23
  this.hitTest = hitTest;
22
24
  this.hitTestCanvasModel = hitTestCanvasModel;
23
25
  this.lastXStart = 0;
26
+ this.lastXEnd = 0;
24
27
  this.lastXWidth = 0;
25
28
  this.lastXPxWidth = 0;
26
29
  this.onXDragStart = () => {
27
30
  this.lastXStart = this.scale.xStart;
31
+ this.lastXEnd = this.scale.xEnd;
28
32
  this.lastXWidth = this.scale.xEnd - this.scale.xStart;
29
33
  const bounds = this.canvasBoundsContainer.getBounds(CanvasElement.X_AXIS);
30
34
  this.lastXPxWidth = bounds.width - this.canvasInputListener.currentPoint.x;
@@ -32,23 +36,48 @@ export class XAxisScaleHandler extends ChartBaseElement {
32
36
  this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(false);
33
37
  };
34
38
  this.onXDragTick = (dragInfo) => {
35
- const { delta: absoluteXDelta } = dragInfo;
36
- const newPxWidth = this.lastXPxWidth - absoluteXDelta;
37
- // cursor goes beyond x-axis - maximum scale is reached
38
- if (newPxWidth < 0) {
39
+ let { delta: absoluteXDelta } = dragInfo;
40
+ // mouse click or single tap drag
41
+ if (!this.touches || this.touches.length === 1) {
42
+ const newPxWidth = this.lastXPxWidth - absoluteXDelta;
43
+ // cursor goes beyond x-axis - maximum scale is reached
44
+ if (newPxWidth < 0) {
45
+ return;
46
+ }
47
+ const xZoomMult = this.lastXPxWidth / newPxWidth;
48
+ const newWidth = this.lastXWidth * xZoomMult;
49
+ const newXStart = this.lastXStart + (this.lastXWidth - newWidth);
50
+ this.scale.setXScale(newXStart, this.scale.xEnd);
39
51
  return;
40
52
  }
41
- const xZoomMult = this.lastXPxWidth / newPxWidth;
42
- const newWidth = this.lastXWidth * xZoomMult;
43
- const newXStart = this.lastXStart + (this.lastXWidth - newWidth);
44
- this.scale.setXScale(newXStart, this.scale.xEnd);
53
+ // if multitouch - take the first two touch events and apply delta the following way:
54
+ // the touch on the left keeps the initial delta because left => right gesture
55
+ // the touch on the right has the reversed delta because the gesture is right => left
56
+ if (this.touches.length > 1) {
57
+ const left = Math.min(this.touches[0].clientX, this.touches[1].clientX);
58
+ absoluteXDelta = left === this.touches[0].clientX ? absoluteXDelta : -absoluteXDelta;
59
+ let xZoomMult;
60
+ if (absoluteXDelta < 0) {
61
+ xZoomMult = 1 / (1 + (-absoluteXDelta / this.lastXPxWidth) * (FULL_X_WIDTH_ZOOM_FACTOR - 1));
62
+ }
63
+ else {
64
+ xZoomMult = 1 + (absoluteXDelta / this.lastXPxWidth) * (FULL_X_WIDTH_ZOOM_FACTOR - 1);
65
+ }
66
+ const newXWidth = this.lastXWidth * xZoomMult;
67
+ const delta = (newXWidth - this.lastXWidth) / 2;
68
+ const newXStart = this.lastXStart - delta;
69
+ const newXEnd = this.lastXEnd + delta;
70
+ if (this.lastXStart !== newXStart || this.lastXEnd !== newXEnd) {
71
+ this.scale.setXScale(newXStart, newXEnd);
72
+ }
73
+ }
45
74
  };
46
75
  this.onXDragEnd = () => {
47
76
  // Continue redrawing hit test
48
77
  this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(true);
49
78
  };
50
- this.setDblTapCallback = (cb) => this.dblTapCallback = cb;
51
- this.setDblClickCallback = (cb) => this.dblClickCallback = cb;
79
+ this.setDblTapCallback = (cb) => (this.dblTapCallback = cb);
80
+ this.setDblClickCallback = (cb) => (this.dblClickCallback = cb);
52
81
  this.dblClickCallback = () => chartModel.doBasicScale();
53
82
  this.dblTapCallback = () => chartModel.doBasicScale();
54
83
  const dragNDropXComponent = new DragNDropXComponent(hitTest, {