@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
@@ -3,13 +3,13 @@
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 { getPrimaryLabelTextColor } from '../label-color.functions';
6
+ import { getPlainLabelTextColor, getPrimaryLabelTextColor } from '../label-color.functions';
7
7
  import { lastOf } from '../../../utils/array.utils';
8
8
  import { getLabelTextColorByBackgroundColor } from '../../../utils/canvas/canvas-text-functions.utils';
9
9
  export class LastCandleLabelsProvider {
10
- constructor(chartModel, fullConfig, yAxisConfig, lastCandleLabelsByChartType, resolveLabelColorFn) {
10
+ constructor(chartModel, chartConfig, yAxisConfig, lastCandleLabelsByChartType, resolveLabelColorFn) {
11
11
  this.chartModel = chartModel;
12
- this.fullConfig = fullConfig;
12
+ this.chartConfig = chartConfig;
13
13
  this.yAxisConfig = yAxisConfig;
14
14
  this.lastCandleLabelsByChartType = lastCandleLabelsByChartType;
15
15
  this.resolveLabelColorFn = resolveLabelColorFn;
@@ -20,36 +20,37 @@ export class LastCandleLabelsProvider {
20
20
  */
21
21
  getUnorderedLabels() {
22
22
  const collectedLabels = [];
23
- const visible = this.yAxisConfig.labels.settings.lastPrice.mode !== 'none';
24
- if (visible) {
25
- // main candle series
26
- const yAxisVisualLabel = this.getYAxisVisualLabel(this.chartModel.mainCandleSeries);
27
- const mainCandleSeriesVisualLabel = yAxisVisualLabel
28
- ? Object.assign(Object.assign({}, yAxisVisualLabel), this.getLabelDrawConfig(this.chartModel.mainCandleSeries, true)) : yAxisVisualLabel;
29
- if (mainCandleSeriesVisualLabel) {
30
- const mainCandleSeriesLabels = { labels: [mainCandleSeriesVisualLabel] };
31
- const handler = this.lastCandleLabelsByChartType[this.fullConfig.components.chart.type];
32
- handler === null || handler === void 0 ? void 0 : handler(mainCandleSeriesLabels, this.chartModel.mainCandleSeries);
33
- collectedLabels.push(mainCandleSeriesLabels);
34
- }
35
- // compare candle series
36
- this.chartModel.candleSeries.forEach((series, index) => {
37
- if (index === 0) {
38
- return;
39
- }
40
- const yAxisVisualLabel = this.getYAxisVisualLabel(series);
41
- const secondarySeriesVisualLabel = yAxisVisualLabel
42
- ? Object.assign(Object.assign({}, yAxisVisualLabel), this.getLabelDrawConfig(series, false)) : yAxisVisualLabel;
43
- if (secondarySeriesVisualLabel) {
44
- const secondarySeriesLabel = {
45
- labels: [secondarySeriesVisualLabel],
46
- };
47
- const handler = this.lastCandleLabelsByChartType[series.config.type];
48
- handler === null || handler === void 0 ? void 0 : handler(secondarySeriesLabel, this.chartModel.mainCandleSeries);
49
- collectedLabels.push(secondarySeriesLabel);
50
- }
51
- });
23
+ const visible = this.yAxisConfig.labels.settings.lastPrice.mode !== 'none' && this.yAxisConfig.visible;
24
+ if (!visible) {
25
+ return collectedLabels;
26
+ }
27
+ // main candle series
28
+ const yAxisVisualLabel = this.getYAxisVisualLabel(this.chartModel.mainCandleSeries);
29
+ const mainCandleSeriesVisualLabel = yAxisVisualLabel
30
+ ? Object.assign(Object.assign({}, yAxisVisualLabel), this.getLabelDrawConfig(this.chartModel.mainCandleSeries, true)) : yAxisVisualLabel;
31
+ if (mainCandleSeriesVisualLabel) {
32
+ const mainCandleSeriesLabels = { labels: [mainCandleSeriesVisualLabel] };
33
+ const handler = this.lastCandleLabelsByChartType[this.chartConfig.components.chart.type];
34
+ handler === null || handler === void 0 ? void 0 : handler(mainCandleSeriesLabels, this.chartModel.mainCandleSeries);
35
+ collectedLabels.push(mainCandleSeriesLabels);
52
36
  }
37
+ // compare candle series
38
+ this.chartModel.candleSeries.forEach((series, index) => {
39
+ if (index === 0) {
40
+ return;
41
+ }
42
+ const yAxisVisualLabel = this.getYAxisVisualLabel(series);
43
+ const secondarySeriesVisualLabel = yAxisVisualLabel
44
+ ? Object.assign(Object.assign({}, yAxisVisualLabel), this.getLabelDrawConfig(series, false)) : yAxisVisualLabel;
45
+ if (secondarySeriesVisualLabel) {
46
+ const secondarySeriesLabel = {
47
+ labels: [secondarySeriesVisualLabel],
48
+ };
49
+ const handler = this.lastCandleLabelsByChartType[series.config.type];
50
+ handler === null || handler === void 0 ? void 0 : handler(secondarySeriesLabel, this.chartModel.mainCandleSeries);
51
+ collectedLabels.push(secondarySeriesLabel);
52
+ }
53
+ });
53
54
  return collectedLabels;
54
55
  }
55
56
  /**
@@ -79,22 +80,39 @@ export class LastCandleLabelsProvider {
79
80
  /**
80
81
  * Returns the configuration object for drawing the label of the Y-axis.
81
82
  * @param {CandleSeriesModel} series - The series model for which the label configuration is to be returned.
82
- * @param {boolean} primary - A boolean value indicating whether the label is primary or not.
83
+ * @param {boolean} primary - A boolean value indicating whether the label is for the main series or not.
83
84
  * @returns {YAxisLabelDrawConfig} - The configuration object for drawing the label of the Y-axis.
84
85
  */
85
86
  getLabelDrawConfig(series, primary) {
87
+ const appearanceType = this.yAxisConfig.labels.settings.lastPrice.type;
86
88
  const colors = series.colors.labels;
89
+ const { rectLabelTextColor = 'white', rectLabelInvertedTextColor = 'black' } = this.chartConfig.colors.yAxis;
87
90
  const getLabelBoxColor = this.resolveLabelColorFn(series.config.type);
88
- const { rectLabelTextColor, rectLabelInvertedTextColor } = this.chartModel.config.colors.yAxis;
89
- let boxColor = '#FFFFFF';
90
- let textColor = '#FFFFFF';
91
- if (colors) {
92
- boxColor = getLabelBoxColor(series.lastPriceMovement, series.colors);
93
- textColor = primary ? getPrimaryLabelTextColor(series.lastPriceMovement, colors) : rectLabelTextColor;
91
+ if (!colors) {
92
+ return {
93
+ bgColor: '#FFFFFF',
94
+ textColor: getLabelTextColorByBackgroundColor('#FFFFFF', '#000000', rectLabelInvertedTextColor),
95
+ rounded: true,
96
+ };
97
+ }
98
+ const boxColor = getLabelBoxColor(series.lastPriceMovement, series.colors);
99
+ // if the label is for the main candle series
100
+ if (primary) {
101
+ const textColor = getPrimaryLabelTextColor(series.lastPriceMovement, colors);
102
+ return {
103
+ bgColor: boxColor,
104
+ textColor: appearanceType === 'plain'
105
+ ? getPlainLabelTextColor(this.chartConfig.colors, textColor, rectLabelInvertedTextColor, this.yAxisConfig)
106
+ : getLabelTextColorByBackgroundColor(boxColor, textColor, rectLabelInvertedTextColor),
107
+ rounded: true,
108
+ };
94
109
  }
110
+ // if the label is for the secondary candle series
95
111
  return {
96
112
  bgColor: boxColor,
97
- textColor: getLabelTextColorByBackgroundColor(boxColor, textColor, rectLabelInvertedTextColor),
113
+ textColor: appearanceType === 'plain'
114
+ ? getPlainLabelTextColor(this.chartConfig.colors, rectLabelTextColor, rectLabelInvertedTextColor, this.yAxisConfig)
115
+ : getLabelTextColorByBackgroundColor(boxColor, rectLabelTextColor, rectLabelInvertedTextColor),
98
116
  rounded: true,
99
117
  };
100
118
  }
@@ -4,7 +4,7 @@
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 { CanvasBoundsContainer } from '../../../canvas/canvas-bounds-container';
7
- import { FullChartColors } from '../../../chart.config';
7
+ import { FullChartConfig } from '../../../chart.config';
8
8
  import { Drawer } from '../../../drawers/drawing-manager';
9
9
  import { CanvasModel } from '../../../model/canvas.model';
10
10
  import { PaneManager } from '../../pane/pane-manager.component';
@@ -13,9 +13,9 @@ export declare class YAxisPriceLabelsDrawer implements Drawer {
13
13
  private yAxisLabelsCanvasModel;
14
14
  private backgroundCanvasModel;
15
15
  private canvasBoundsContainer;
16
- private yAxisColors;
16
+ private fullConfig;
17
17
  private paneManager;
18
- constructor(yAxisLabelsCanvasModel: CanvasModel, backgroundCanvasModel: CanvasModel, canvasBoundsContainer: CanvasBoundsContainer, yAxisColors: FullChartColors['yAxis'], paneManager: PaneManager);
18
+ constructor(yAxisLabelsCanvasModel: CanvasModel, backgroundCanvasModel: CanvasModel, canvasBoundsContainer: CanvasBoundsContainer, fullConfig: FullChartConfig, paneManager: PaneManager);
19
19
  draw(): void;
20
20
  drawHighlightedBackgroundBetweenLabels(orderedLabels: LabelGroup[]): void;
21
21
  getCanvasIds(): Array<string>;
@@ -7,28 +7,30 @@ import { CanvasElement, CHART_UUID, limitYToBounds, } from '../../../canvas/canv
7
7
  import { fillRect } from '../../../utils/canvas/canvas-drawing-functions.utils';
8
8
  import { drawLabel } from './price-label.drawer';
9
9
  export class YAxisPriceLabelsDrawer {
10
- constructor(yAxisLabelsCanvasModel, backgroundCanvasModel, canvasBoundsContainer, yAxisColors, paneManager) {
10
+ constructor(yAxisLabelsCanvasModel, backgroundCanvasModel, canvasBoundsContainer, fullConfig, paneManager) {
11
11
  this.yAxisLabelsCanvasModel = yAxisLabelsCanvasModel;
12
12
  this.backgroundCanvasModel = backgroundCanvasModel;
13
13
  this.canvasBoundsContainer = canvasBoundsContainer;
14
- this.yAxisColors = yAxisColors;
14
+ this.fullConfig = fullConfig;
15
15
  this.paneManager = paneManager;
16
16
  }
17
17
  draw() {
18
18
  const ctx = this.yAxisLabelsCanvasModel.ctx;
19
19
  const backgroundCtx = this.backgroundCanvasModel.ctx;
20
20
  this.paneManager.yExtents.forEach(extent => {
21
- const yAxisBounds = extent.getYAxisBounds();
22
- const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.ALL_PANES);
23
- const orderedLabels = extent.yAxis.model.fancyLabelsModel.orderedLabels;
24
- this.drawHighlightedBackgroundBetweenLabels(orderedLabels);
25
- orderedLabels.forEach(l => {
26
- var _a;
27
- const bounds = (_a = l.bounds) !== null && _a !== void 0 ? _a : yAxisBounds;
28
- l.labels.forEach(vl => drawLabel(ctx, backgroundCtx, bounds, paneBounds, vl, this.canvasBoundsContainer, extent.yAxis.state, this.yAxisColors));
29
- });
30
- // TODO I added this as a simple mechanism to add custom labels, we need to review it
31
- Object.values(extent.yAxis.model.fancyLabelsModel.customLabels).forEach(l => drawLabel(ctx, backgroundCtx, yAxisBounds, paneBounds, l, this.canvasBoundsContainer, extent.yAxis.state, this.yAxisColors));
21
+ if (extent.yAxis.state.visible) {
22
+ const yAxisBounds = extent.getYAxisBounds();
23
+ const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.ALL_PANES);
24
+ const orderedLabels = extent.yAxis.model.fancyLabelsModel.orderedLabels;
25
+ this.drawHighlightedBackgroundBetweenLabels(orderedLabels);
26
+ orderedLabels.forEach(l => {
27
+ var _a;
28
+ const bounds = (_a = l.bounds) !== null && _a !== void 0 ? _a : yAxisBounds;
29
+ l.labels.forEach(vl => drawLabel(ctx, backgroundCtx, bounds, paneBounds, vl, this.canvasBoundsContainer, extent.yAxis.state, this.fullConfig.colors.yAxis));
30
+ });
31
+ // TODO I added this as a simple mechanism to add custom labels, we need to review it
32
+ Object.values(extent.yAxis.model.fancyLabelsModel.customLabels).forEach(l => drawLabel(ctx, backgroundCtx, yAxisBounds, paneBounds, l, this.canvasBoundsContainer, extent.yAxis.state, this.fullConfig.colors.yAxis));
33
+ }
32
34
  });
33
35
  }
34
36
  // this is a very simple solution which matches 2 labels with same "subGroupId"
@@ -56,7 +56,7 @@ export class YAxisScaleHandler extends ChartBaseElement {
56
56
  };
57
57
  // drag to Y-scale and double click to auto scale
58
58
  if (config.customScale) {
59
- const dragPredicate = () => config.type !== 'percent';
59
+ const dragPredicate = () => config.type !== 'percent' && config.visible;
60
60
  const dragNDropYComponent = new DragNDropYComponent(hitTest, {
61
61
  onDragTick: callIfPredicateTrue(this.onYDragTick, dragPredicate),
62
62
  onDragStart: callIfPredicateTrue(this.onYDragStart, dragPredicate),
@@ -27,6 +27,7 @@ export type LabelColorResolver = (priceMovement: PriceMovement, colors: FullChar
27
27
  */
28
28
  export declare class YAxisComponent extends ChartBaseElement {
29
29
  private eventBus;
30
+ private config;
30
31
  private canvasModel;
31
32
  scale: ScaleModel;
32
33
  private canvasBoundsContainer;
@@ -111,7 +112,7 @@ export declare class YAxisComponent extends ChartBaseElement {
111
112
  */
112
113
  setYAxisAlign(align: YAxisAlign): void;
113
114
  /**
114
- * Controls visibility of the y-axis
115
+ * Controls visibility of the y-axis (additionally disable/enable component)
115
116
  */
116
117
  setVisible(isVisible: boolean): void;
117
118
  /**
@@ -19,6 +19,7 @@ export class YAxisComponent extends ChartBaseElement {
19
19
  constructor(eventBus, config, canvasModel, scale, canvasInputListeners, canvasBoundsContainer, chartPanComponent, cursors, valueFormatter, dataSeriesProvider, paneUUID, extentIdx) {
20
20
  super();
21
21
  this.eventBus = eventBus;
22
+ this.config = config;
22
23
  this.canvasModel = canvasModel;
23
24
  this.scale = scale;
24
25
  this.canvasBoundsContainer = canvasBoundsContainer;
@@ -166,11 +167,14 @@ export class YAxisComponent extends ChartBaseElement {
166
167
  this.eventBus.fireDraw();
167
168
  }
168
169
  /**
169
- * Controls visibility of the y-axis
170
+ * Controls visibility of the y-axis (additionally disable/enable component)
170
171
  */
171
172
  setVisible(isVisible) {
172
173
  this.state.visible = isVisible;
173
- this.eventBus.fireDraw();
174
+ this.config.components.yAxis.visible = isVisible;
175
+ isVisible ? this.enable() : this.disable();
176
+ this.model.fancyLabelsModel.updateLabels();
177
+ this.model.baseLabelsModel.updateLabels();
174
178
  }
175
179
  /**
176
180
  * If visible, when you can see the y-axis on the chart
@@ -28,7 +28,7 @@ export class HTDataSeriesDrawer {
28
28
  const drawer = this.seriesDrawers[paintTool];
29
29
  if (drawer) {
30
30
  const drawConfig = {
31
- singleColor: this.canvasModel.idToColor(series.id),
31
+ singleColor: this.canvasModel.idToColor(series.htId),
32
32
  forceBold: 7,
33
33
  };
34
34
  // +- 1 to correctly draw points which are partly inside bounds
@@ -3,7 +3,8 @@
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 { BehaviorSubject, combineLatest, filter } from 'rxjs';
6
+ import { BehaviorSubject, combineLatest } from 'rxjs';
7
+ import { filter } from 'rxjs/operators';
7
8
  import { ChartBaseElement } from '../model/chart-base-element';
8
9
  export class CrossEventProducerComponent extends ChartBaseElement {
9
10
  constructor(canvasInputListener, canvasBoundsContainer) {
@@ -55,7 +55,7 @@ export declare class HoverProducerComponent extends ChartBaseElement {
55
55
  private formatterFactory;
56
56
  hoverSubject: BehaviorSubject<Hover | null>;
57
57
  get hover(): Hover | null;
58
- private longTouchActivated;
58
+ private longTouchActivatedSubject;
59
59
  private hoverProducerParts;
60
60
  xFormatter: DateTimeFormatter;
61
61
  constructor(crossEventProducer: CrossEventProducerComponent, scale: ScaleModel, config: FullChartConfig, chartModel: ChartModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, paneManager: PaneManager, timeZoneModel: TimeZoneModel, formatterFactory: (format: string) => (timestamp: number | Date) => string);
@@ -30,7 +30,7 @@ export class HoverProducerComponent extends ChartBaseElement {
30
30
  this.timeZoneModel = timeZoneModel;
31
31
  this.formatterFactory = formatterFactory;
32
32
  this.hoverSubject = new BehaviorSubject(null);
33
- this.longTouchActivated = false;
33
+ this.longTouchActivatedSubject = new BehaviorSubject(false);
34
34
  this.xFormatter = () => '';
35
35
  const candleHoverProducerPart = new CandleHoverProducerPart(this.chartModel);
36
36
  const compareSeriesHoverProducerPart = new CompareSeriesHoverProducerPart(this.chartModel);
@@ -74,7 +74,7 @@ export class HoverProducerComponent extends ChartBaseElement {
74
74
  }));
75
75
  this.addRxSubscription(this.scale.xChanged.subscribe(() => this.fireLastCross()));
76
76
  this.addRxSubscription(this.canvasInputListener.observeTouchStart().subscribe(event => {
77
- const x = event.touches[0].clientX;
77
+ const x = event.touches[0].clientX - this.canvasBoundsContainer.canvasOnPageLocation.x;
78
78
  const y = event.touches[0].clientY - this.canvasBoundsContainer.canvasOnPageLocation.y;
79
79
  const candle = this.chartModel.candleFromX(x, true);
80
80
  if (candle) {
@@ -84,17 +84,18 @@ export class HoverProducerComponent extends ChartBaseElement {
84
84
  // special handling for mobile
85
85
  // on long touch - disable panning and show cross tool
86
86
  const hitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
87
- this.addRxSubscription(this.canvasInputListener.observeLongTouch(hitTest).subscribe(event => {
87
+ this.addRxSubscription(this.canvasInputListener.observeLongTouchStart(hitTest).subscribe(event => {
88
88
  this.paneManager.chartPanComponent.deactivatePanHandlers();
89
- this.longTouchActivated = true;
90
- const x = event.touches[0].clientX;
89
+ this.longTouchActivatedSubject.next(true);
90
+ const x = event.touches[0].clientX - this.canvasBoundsContainer.canvasOnPageLocation.x;
91
91
  const y = event.touches[0].clientY - this.canvasBoundsContainer.canvasOnPageLocation.y;
92
92
  this.createAndFireHover([x, y, '']);
93
+ this.crossEventProducer.crossSubject.next([x, y, '']);
93
94
  }));
94
95
  this.addRxSubscription(this.canvasInputListener.observeTouchEndDocument().subscribe(() => {
95
96
  this.paneManager.chartPanComponent.activateChartPanHandlers();
96
- if (this.longTouchActivated) {
97
- this.longTouchActivated = false;
97
+ if (this.longTouchActivatedSubject.getValue()) {
98
+ this.longTouchActivatedSubject.next(false);
98
99
  this.crossEventProducer.fireCrossClose();
99
100
  }
100
101
  }));
@@ -195,7 +196,6 @@ export class HoverProducerComponent extends ChartBaseElement {
195
196
  const candle = (_a = hover.candleHover) === null || _a === void 0 ? void 0 : _a.visualCandle.candle;
196
197
  candle && this.chartModel.mainCandleSeries.setActiveCandle(candle);
197
198
  }
198
- // const showCrossToolOverride = isMobile() ? this.longTouchActivated : showCrossTool;
199
199
  this.hoverSubject.next(hover);
200
200
  }
201
201
  else {
@@ -47,8 +47,9 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
47
47
  private touchMoveSubject;
48
48
  private touchEndSubject;
49
49
  private touchCancelSubject;
50
+ private longTouchStartSubject;
51
+ private longTouchEndSubject;
50
52
  private contextMenuSubject;
51
- private longTouchSubject;
52
53
  private pinchSubject;
53
54
  private scrollGestureSubject;
54
55
  mouseLeavesCanvasSubject: Subject<boolean>;
@@ -85,9 +86,9 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
85
86
  private dragListener;
86
87
  private updateElementOffsetListener;
87
88
  private dragEndListener;
88
- private clickHandler;
89
89
  /**
90
- * Prevents text selection inside chart-core canvas. TODO Do we need it?
90
+ * TODO: Do we need it?
91
+ * Prevents text selection inside chart-core canvas.
91
92
  */
92
93
  private fixTextSelection;
93
94
  doActivate(): void;
@@ -300,11 +301,17 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
300
301
  */
301
302
  observeContextMenu(hitBoundsTest?: HitBoundsTest): Observable<MouseEvent>;
302
303
  /**
303
- * Returns an Observable that emits a TouchEvent when a long touch is detected on the current element.
304
+ * Returns an Observable that emits a TouchEvent when a long touch start is detected on the current element.
304
305
  * @param {HitBoundsTest} [hitBoundsTest=() => true] - A function that returns a boolean indicating whether the touch event occurred within the bounds of the current element.
305
306
  * @returns {Observable<TouchEvent>} - An Observable that emits a TouchEvent when a long touch is detected on the current element.
306
307
  */
307
- observeLongTouch(hitBoundsTest?: HitBoundsTest): Observable<TouchEvent>;
308
+ observeLongTouchStart(hitBoundsTest?: HitBoundsTest): Observable<TouchEvent>;
309
+ /**
310
+ * Returns an Observable that emits a TouchEvent when a long touch end is detected on the current element.
311
+ * @param {HitBoundsTest} [hitBoundsTest=() => true] - A function that returns a boolean indicating whether the touch event occurred within the bounds of the current element.
312
+ * @returns {Observable<TouchEvent>} - An Observable that emits a TouchEvent when a long touch is detected on the current element.
313
+ */
314
+ observeLongTouchEnd(hitBoundsTest?: HitBoundsTest): Observable<TouchEvent>;
308
315
  /**
309
316
  * Returns the current point of the object.
310
317
  * @returns {Point} The current point of the object.
@@ -3,19 +3,13 @@
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 { subscribeListener } from '../utils/dom.utils';
6
+ import { MouseButton, leftMouseButtonListener, subscribeListener } from '../utils/dom.utils';
7
7
  import { merge, Subject } from 'rxjs';
8
8
  import { ChartBaseElement } from '../model/chart-base-element';
9
9
  import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators';
10
10
  import { EVENT_RESIZED } from '../events/events';
11
- import { deviceDetector } from '../utils/device/device-detector.utils';
12
11
  import { touchpadDetector } from '../utils/device/touchpad.utils';
13
- var MouseButton;
14
- (function (MouseButton) {
15
- MouseButton[MouseButton["left"] = 0] = "left";
16
- MouseButton[MouseButton["middle"] = 1] = "middle";
17
- MouseButton[MouseButton["right"] = 2] = "right";
18
- })(MouseButton || (MouseButton = {}));
12
+ import { deviceDetector } from '../utils/device/device-detector.utils';
19
13
  /**
20
14
  * Gathers user input on canvas element:
21
15
  * Chart update order should be following:
@@ -55,8 +49,9 @@ class CanvasInputListenerComponent extends ChartBaseElement {
55
49
  this.touchMoveSubject = new Subject();
56
50
  this.touchEndSubject = new Subject();
57
51
  this.touchCancelSubject = new Subject();
52
+ this.longTouchStartSubject = new Subject();
53
+ this.longTouchEndSubject = new Subject();
58
54
  this.contextMenuSubject = new Subject();
59
- this.longTouchSubject = new Subject();
60
55
  this.pinchSubject = new Subject();
61
56
  this.scrollGestureSubject = new Subject();
62
57
  this.mouseLeavesCanvasSubject = new Subject();
@@ -114,7 +109,6 @@ class CanvasInputListenerComponent extends ChartBaseElement {
114
109
  this.xDragEndSubject.next();
115
110
  this.yDragEndSubject.next();
116
111
  };
117
- this.clickHandler = () => this.clickSubject.next(this.currentPoint);
118
112
  this.updateCurrentPoints = (e) => {
119
113
  this.updateCurrentDocumentPoint(e);
120
114
  this.updateCurrentMousePoint(e);
@@ -155,7 +149,8 @@ class CanvasInputListenerComponent extends ChartBaseElement {
155
149
  this.dragEndListener();
156
150
  }
157
151
  /**
158
- * Prevents text selection inside chart-core canvas. TODO Do we need it?
152
+ * TODO: Do we need it?
153
+ * Prevents text selection inside chart-core canvas.
159
154
  */
160
155
  fixTextSelection() {
161
156
  const selectListener = (e) => {
@@ -185,59 +180,64 @@ class CanvasInputListenerComponent extends ChartBaseElement {
185
180
  document.addEventListener(dragEndEvent, this.dragEndListener);
186
181
  this.addSubscription(document.removeEventListener.bind(document, dragEndEvent, this.dragEndListener));
187
182
  });
188
- this.addSubscription(subscribeListener(this.element, this.clickHandler, 'click'));
189
- const clickDocumentListener = (e) => {
190
- this.clickDocumentSubject.next(e);
191
- };
192
- this.addSubscription(subscribeListener(document, clickDocumentListener, 'click'));
183
+ this.addSubscription(subscribeListener(this.element, leftMouseButtonListener(() => this.clickSubject.next(this.currentPoint)), 'click'));
184
+ this.addSubscription(subscribeListener(document, leftMouseButtonListener(e => this.clickDocumentSubject.next(e)), 'click'));
193
185
  const device = deviceDetector();
194
186
  if (device === 'apple' || device === 'mobile') {
195
187
  // workaround to handle double taps for iOS
196
- const doubleTapListenerProducer = () => {
197
- let timeoutId = null;
198
- return () => {
199
- if (timeoutId) {
200
- this.dbTapSubject.next(this.currentPoint);
201
- clearTimeout(timeoutId);
202
- timeoutId = null;
188
+ let dbTapTimeout = null;
189
+ const doubleTapListenerProducer = (e) => {
190
+ e.preventDefault();
191
+ if (dbTapTimeout) {
192
+ this.dbTapSubject.next(this.currentPoint);
193
+ clearTimeout(dbTapTimeout);
194
+ dbTapTimeout = null;
195
+ }
196
+ else {
197
+ dbTapTimeout = window.setTimeout(() => {
198
+ dbTapTimeout = null;
199
+ }, 250);
200
+ }
201
+ };
202
+ this.addSubscription(subscribeListener(this.element, doubleTapListenerProducer, 'touchend'));
203
+ // workaround to handle long touch start/end for iOS
204
+ const longTouchListeners = (e, delay = 700, pixelsForMoveReset = 3) => {
205
+ e.preventDefault();
206
+ const initialCoords = { x: e.touches[0].clientX, y: e.touches[0].clientY };
207
+ let coords = { x: 0, y: 0 };
208
+ let longTouchStart = false;
209
+ let timerLongTouchStart = null;
210
+ // start timeout for long touch
211
+ timerLongTouchStart = setTimeout(() => {
212
+ longTouchStart = true;
213
+ this.longTouchStartSubject.next(e);
214
+ }, delay);
215
+ const touchMoveHandler = (e) => {
216
+ e.preventDefault();
217
+ coords = { x: e.touches[0].clientX, y: e.touches[0].clientY };
218
+ // clear long touch timeout if move area is bigger than pixelsForMove
219
+ if (Math.sqrt(Math.pow(coords.x - initialCoords.x, 2) + Math.pow(coords.y - initialCoords.y, 2)) >
220
+ pixelsForMoveReset ||
221
+ e.touches.length > 1) {
222
+ timerLongTouchStart && clearTimeout(timerLongTouchStart);
203
223
  }
204
- else {
205
- timeoutId = window.setTimeout(() => {
206
- timeoutId = null;
207
- }, 250);
224
+ };
225
+ const touchEndHandler = (e) => {
226
+ e.preventDefault();
227
+ timerLongTouchStart && clearTimeout(timerLongTouchStart);
228
+ if (longTouchStart) {
229
+ longTouchStart = false;
230
+ this.longTouchEndSubject.next(e);
208
231
  }
232
+ this.element.removeEventListener('touchend', touchEndHandler);
233
+ this.element.removeEventListener('touchmove', touchMoveHandler);
209
234
  };
235
+ this.element.addEventListener('touchmove', touchMoveHandler);
236
+ this.element.addEventListener('touchend', touchEndHandler);
210
237
  };
211
- const doubleTapListener = doubleTapListenerProducer();
212
- this.addSubscription(subscribeListener(this.element, doubleTapListener, 'touchend'));
238
+ this.addSubscription(subscribeListener(this.element, (e) => longTouchListeners(e), 'touchstart'));
213
239
  }
214
- const longTouchListener = (e, delay = 500, pixelsForMoveReset = 2) => {
215
- e.preventDefault();
216
- let timer = null;
217
- const initialCoords = { x: e.touches[0].clientX, y: e.touches[0].clientY };
218
- let coords = { x: 0, y: 0 };
219
- const touchMoveHandler = (e) => {
220
- coords = { x: e.touches[0].clientX, y: e.touches[0].clientY };
221
- if (Math.sqrt(Math.pow(coords.x - initialCoords.x, 2) + Math.pow(coords.y - initialCoords.y, 2)) >
222
- pixelsForMoveReset ||
223
- e.touches.length > 1) {
224
- touchEnd();
225
- }
226
- };
227
- const touchEnd = () => {
228
- if (timer) {
229
- clearTimeout(timer);
230
- timer = null;
231
- }
232
- this.element.removeEventListener('touchend', touchEnd);
233
- this.element.removeEventListener('touchmove', touchMoveHandler);
234
- };
235
- timer = setTimeout(() => this.longTouchSubject.next(e), delay);
236
- this.element.addEventListener('touchmove', touchMoveHandler, { passive: true });
237
- this.element.addEventListener('touchend', touchEnd);
238
- };
239
- this.addSubscription(subscribeListener(this.element, (e) => longTouchListener(e), 'touchstart'));
240
- this.addSubscription(subscribeListener(this.element, () => this.dbClickSubject.next(this.currentPoint), 'dblclick'));
240
+ this.addSubscription(subscribeListener(this.element, leftMouseButtonListener(() => this.dbClickSubject.next(this.currentPoint)), 'dblclick'));
241
241
  this.addSubscription(subscribeListener(this.element, (e) => this.touchStartSubject.next(e), 'touchstart'));
242
242
  this.addSubscription(subscribeListener(this.element, (e) => this.touchMoveSubject.next(e), 'touchmove', true));
243
243
  this.addSubscription(subscribeListener(this.element, (e) => this.touchEndSubject.next(e), 'touchend'));
@@ -260,9 +260,9 @@ class CanvasInputListenerComponent extends ChartBaseElement {
260
260
  e.preventDefault(); // to disable the scroll over the document, if for example chart is used as widget
261
261
  }, 'wheel'));
262
262
  this.addSubscription(subscribeListener(this.element, (e) => this.contextMenuSubject.next(e), 'contextmenu'));
263
- this.addSubscription(subscribeListener(this.element, () => this.mouseDownSubject.next(this.currentPoint), 'mousedown'));
264
- this.addSubscription(subscribeListener(this.element, () => this.mouseUpSubject.next(this.currentPoint), 'mouseup'));
265
- this.addSubscription(subscribeListener(document, () => this.mouseUpDocumentSubject.next(this.currentPoint), 'mouseup'));
263
+ this.addSubscription(subscribeListener(this.element, leftMouseButtonListener(() => this.mouseDownSubject.next(this.currentPoint)), 'mousedown'));
264
+ this.addSubscription(subscribeListener(this.element, leftMouseButtonListener(() => this.mouseUpSubject.next(this.currentPoint)), 'mouseup'));
265
+ this.addSubscription(subscribeListener(document, leftMouseButtonListener(() => this.mouseUpDocumentSubject.next(this.currentPoint)), 'mouseup'));
266
266
  this.addRxSubscription(this.eventBus.observe(EVENT_RESIZED).subscribe(() => {
267
267
  const bcr = this.element.getBoundingClientRect();
268
268
  this.canvasBounds.x = bcr.left;
@@ -624,12 +624,24 @@ class CanvasInputListenerComponent extends ChartBaseElement {
624
624
  return this.contextMenuSubject.asObservable().pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)), tap(p => p.preventDefault()));
625
625
  }
626
626
  /**
627
- * Returns an Observable that emits a TouchEvent when a long touch is detected on the current element.
627
+ * Returns an Observable that emits a TouchEvent when a long touch start is detected on the current element.
628
628
  * @param {HitBoundsTest} [hitBoundsTest=() => true] - A function that returns a boolean indicating whether the touch event occurred within the bounds of the current element.
629
629
  * @returns {Observable<TouchEvent>} - An Observable that emits a TouchEvent when a long touch is detected on the current element.
630
630
  */
631
- observeLongTouch(hitBoundsTest = () => true) {
632
- return this.longTouchSubject.asObservable().pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)), tap(p => p.preventDefault()));
631
+ observeLongTouchStart(hitBoundsTest = () => true) {
632
+ return this.longTouchStartSubject
633
+ .asObservable()
634
+ .pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
635
+ }
636
+ /**
637
+ * Returns an Observable that emits a TouchEvent when a long touch end is detected on the current element.
638
+ * @param {HitBoundsTest} [hitBoundsTest=() => true] - A function that returns a boolean indicating whether the touch event occurred within the bounds of the current element.
639
+ * @returns {Observable<TouchEvent>} - An Observable that emits a TouchEvent when a long touch is detected on the current element.
640
+ */
641
+ observeLongTouchEnd(hitBoundsTest = () => true) {
642
+ return this.longTouchEndSubject
643
+ .asObservable()
644
+ .pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
633
645
  }
634
646
  /**
635
647
  * Returns the current point of the object.
@@ -34,7 +34,7 @@ export declare class CandleSeriesModel extends DataSeriesModel<Candle, VisualCan
34
34
  get instrument(): ChartInstrument;
35
35
  set instrument(instrument: ChartInstrument);
36
36
  meanCandleWidth: Unit;
37
- constructor(extentComponent: YExtentComponent, id: number, eventBus: EventBus, scale: ScaleModel, instrument: ChartInstrument, candlesTransformersByChartType: Partial<Record<DataSeriesType, VisualCandleCalculator>>, candleWidthByChartType: Partial<Record<DataSeriesType, CandleWidthCalculator>>, colors?: CandleSeriesColors);
37
+ constructor(extentComponent: YExtentComponent, id: string, htId: number, eventBus: EventBus, scale: ScaleModel, instrument: ChartInstrument, candlesTransformersByChartType: Partial<Record<DataSeriesType, VisualCandleCalculator>>, candleWidthByChartType: Partial<Record<DataSeriesType, CandleWidthCalculator>>, colors?: CandleSeriesColors);
38
38
  /**
39
39
  * Recalculates data viewport indexes based on xStart and xEnd parameters or values from scaleModel.
40
40
  * Calls superclass method for calculation, recalculates zipped high/low data points, and fires draw event.
@@ -31,8 +31,8 @@ export class CandleSeriesModel extends DataSeriesModel {
31
31
  this._instrument = instrument;
32
32
  this.pricePrecisions = PriceIncrementsUtils.computePrecisions((_a = instrument.priceIncrements) !== null && _a !== void 0 ? _a : [0.01]);
33
33
  }
34
- constructor(extentComponent, id, eventBus, scale, instrument, candlesTransformersByChartType, candleWidthByChartType, colors = DEFAULT_CANDLE_SERIES_CONFIG) {
35
- super(extentComponent, id);
34
+ constructor(extentComponent, id, htId, eventBus, scale, instrument, candlesTransformersByChartType, candleWidthByChartType, colors = DEFAULT_CANDLE_SERIES_CONFIG) {
35
+ super(extentComponent, id, htId);
36
36
  this.eventBus = eventBus;
37
37
  this.candlesTransformersByChartType = candlesTransformersByChartType;
38
38
  this.candleWidthByChartType = candleWidthByChartType;
@@ -8,7 +8,8 @@ import { BaseHover, HoverProducerPart } from '../inputhandlers/hover-producer.co
8
8
  export interface CompareSeriesHover {
9
9
  instrument: string;
10
10
  price: string;
11
- id: number;
11
+ id: string;
12
+ htId: number;
12
13
  }
13
14
  export declare class CompareSeriesHoverProducerPart implements HoverProducerPart<CompareSeriesHover[]> {
14
15
  private chartModel;
@@ -23,6 +23,7 @@ export class CompareSeriesHoverProducerPart {
23
23
  instrument: series.instrument.symbol,
24
24
  price: priceToShow,
25
25
  id: series.id,
26
+ htId: series.htId,
26
27
  };
27
28
  });
28
29
  return compareSeriesHover;