@devexperts/dxcharts-lite 2.7.15 → 2.7.17

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 (54) hide show
  1. package/dist/chart/animation/canvas-animation.d.ts +1 -0
  2. package/dist/chart/animation/canvas-animation.js +2 -1
  3. package/dist/chart/animation/viewport-model-animation.d.ts +4 -1
  4. package/dist/chart/animation/viewport-model-animation.js +21 -3
  5. package/dist/chart/bootstrap.js +17 -5
  6. package/dist/chart/chart.config.js +1 -1
  7. package/dist/chart/components/chart/chart-area-pan.handler.d.ts +16 -16
  8. package/dist/chart/components/chart/chart-area-pan.handler.js +8 -2
  9. package/dist/chart/components/chart/chart.component.js +2 -0
  10. package/dist/chart/components/chart/chart.model.d.ts +11 -0
  11. package/dist/chart/components/chart/chart.model.js +20 -0
  12. package/dist/chart/components/chart/price-formatters/__tests__/treasury-price.formatter.test.d.ts +6 -0
  13. package/dist/chart/components/chart/price-formatters/__tests__/treasury-price.formatter.test.js +94 -0
  14. package/dist/chart/components/chart/price-formatters/treasury-price.formatter.d.ts +9 -0
  15. package/dist/chart/components/chart/price-formatters/treasury-price.formatter.js +22 -1
  16. package/dist/chart/components/cross_tool/cross-tool.component.d.ts +3 -1
  17. package/dist/chart/components/cross_tool/cross-tool.component.js +3 -2
  18. package/dist/chart/components/cross_tool/cross-tool.model.d.ts +6 -3
  19. package/dist/chart/components/cross_tool/cross-tool.model.js +9 -5
  20. package/dist/chart/components/grid/grid.component.d.ts +1 -1
  21. package/dist/chart/components/grid/grid.component.js +2 -2
  22. package/dist/chart/components/grid/grid.drawer.d.ts +2 -1
  23. package/dist/chart/components/grid/grid.drawer.js +3 -2
  24. package/dist/chart/components/pan/chart-pan.component.js +17 -1
  25. package/dist/chart/components/pane/pane.component.js +3 -1
  26. package/dist/chart/drawers/data-series-drawers/trend-points.drawer.d.ts +12 -0
  27. package/dist/chart/drawers/data-series-drawers/trend-points.drawer.js +70 -0
  28. package/dist/chart/drawers/drawing-manager.js +0 -1
  29. package/dist/chart/inputhandlers/chart-resize.handler.d.ts +5 -0
  30. package/dist/chart/inputhandlers/chart-resize.handler.js +9 -1
  31. package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +28 -0
  32. package/dist/chart/inputlisteners/canvas-input-listener.component.js +104 -7
  33. package/dist/chart/model/data-series.config.d.ts +1 -1
  34. package/dist/chart/model/hit-test-canvas.model.d.ts +15 -13
  35. package/dist/chart/model/hit-test-canvas.model.js +2 -2
  36. package/dist/chart/model/scale.model.d.ts +5 -0
  37. package/dist/chart/model/scale.model.js +72 -6
  38. package/dist/chart/utils/device/touchpad.utils.d.ts +1 -0
  39. package/dist/chart/utils/device/touchpad.utils.js +1 -1
  40. package/dist/chart/utils/math.utils.js +1 -1
  41. package/dist/chart/utils/performance/queue-microtask.utils.d.ts +5 -0
  42. package/dist/chart/utils/performance/queue-microtask.utils.js +12 -0
  43. package/dist/chart/utils/performance/request-animation-frame-throttle.utils.d.ts +1 -0
  44. package/dist/chart/utils/performance/request-animation-frame-throttle.utils.js +3 -0
  45. package/dist/chart/utils/performance/safari/components/animations/safari-canvas-animation.d.ts +77 -0
  46. package/dist/chart/utils/performance/safari/components/animations/safari-canvas-animation.js +137 -0
  47. package/dist/chart/utils/performance/safari/components/chart-area-pan.handler/safari-chart-area-pan.handler.d.ts +54 -0
  48. package/dist/chart/utils/performance/safari/components/chart-area-pan.handler/safari-chart-area-pan.handler.js +180 -0
  49. package/dist/chart/utils/performance/safari/safari-performance.model.d.ts +32 -0
  50. package/dist/chart/utils/performance/safari/safari-performance.model.js +31 -0
  51. package/dist/chart/utils/performance/safari/safari-performance.utils.d.ts +18 -0
  52. package/dist/chart/utils/performance/safari/safari-performance.utils.js +34 -0
  53. package/dist/dxchart.min.js +4 -4
  54. package/package.json +2 -2
@@ -0,0 +1,180 @@
1
+ /*
2
+ * Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
3
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
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
+ */
6
+ import { animationFrameScheduler } from 'rxjs';
7
+ import { throttleTime, filter, debounceTime } from 'rxjs/operators';
8
+ import { CanvasElement } from '../../../../../canvas/canvas-bounds-container';
9
+ import { pixelsToUnits } from '../../../../../model/scaling/viewport.model';
10
+ import { deviceDetector } from '../../../../../utils/device/device-detector.utils';
11
+ import { ONE_FRAME_MS } from '../../../../../utils/numeric-constants.utils';
12
+ import { EVENT_RESIZED } from '../../../../../events/events';
13
+ import { DEFAULT_THROTTLE_MS, LARGE_SCREEN_PIXEL_THRESHOLD, LARGE_SCREEN_THROTTLE_MS, LOW_WHEEL_EVENTS_THRESHOLD, SAFARI_THROTTLE_MS, WHEEL_MONITORING_INTERVAL_MS, } from '../../safari-performance.model';
14
+ import { ChartAreaPanHandler } from '../../../../../components/chart/chart-area-pan.handler';
15
+ /**
16
+ * SafariChartAreaPanHandler is a class that handles the panning and zooming of the chart area for Safari.
17
+ */
18
+ export class SafariChartAreaPanHandler extends ChartAreaPanHandler {
19
+ constructor(bus, config, scale, canvasInputListener, canvasBoundsContainer, canvasAnimation, chartPanComponent, hitTestCanvasModel) {
20
+ super(bus, config, scale, canvasInputListener, canvasBoundsContainer, canvasAnimation, chartPanComponent, hitTestCanvasModel);
21
+ this.bus = bus;
22
+ this.config = config;
23
+ this.scale = scale;
24
+ this.canvasInputListener = canvasInputListener;
25
+ this.canvasBoundsContainer = canvasBoundsContainer;
26
+ this.canvasAnimation = canvasAnimation;
27
+ this.chartPanComponent = chartPanComponent;
28
+ this.hitTestCanvasModel = hitTestCanvasModel;
29
+ this.currentPoint = { x: 0, y: 0 };
30
+ this.xDraggedCandlesDelta = 0;
31
+ this.lastXStart = 0;
32
+ this.wheelThrottleTime = ONE_FRAME_MS;
33
+ this.wheelSubscription = null;
34
+ this.initFrameId = null;
35
+ this.isActivated = false;
36
+ this.lastWheelTime = 0;
37
+ this.wheelCount = 0;
38
+ this.consecutiveLowWheelEvents = 0;
39
+ this.chartPanningOptions = { horizontal: true, vertical: true };
40
+ }
41
+ /**
42
+ * This method is used to activate the zoom functionality of the canvas. It extends the doActivate method of the parent class.
43
+ * @protected
44
+ * @returns {void}
45
+ */
46
+ doActivate() {
47
+ if (this.isActivated) {
48
+ return;
49
+ }
50
+ this.isActivated = true;
51
+ super.doActivate();
52
+ this.canvasInputListener.initializeRectCache();
53
+ this.createWheelSubscription();
54
+ this.initFrameId = requestAnimationFrame(() => {
55
+ this.bus.fireDraw();
56
+ });
57
+ this.addRxSubscription(this.chartPanComponent.chartBaseModel.dataPrependSubject
58
+ .asObservable()
59
+ .subscribe(({ prependedCandlesWidth }) => {
60
+ this.lastXStart += prependedCandlesWidth;
61
+ }));
62
+ this.addRxSubscription(this.bus
63
+ .observe(EVENT_RESIZED)
64
+ .pipe(debounceTime(100))
65
+ .subscribe(() => {
66
+ if (this.scale && typeof this.scale.haltAnimation === 'function') {
67
+ this.scale.haltAnimation();
68
+ }
69
+ }));
70
+ }
71
+ /**
72
+ * Creates wheel subscription with optimized throttling
73
+ */
74
+ createWheelSubscription() {
75
+ if (this.wheelSubscription) {
76
+ this.wheelSubscription.unsubscribe();
77
+ this.wheelSubscription = null;
78
+ }
79
+ const allPanesHitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
80
+ const canvasBounds = this.canvasBoundsContainer.getBounds(CanvasElement.CANVAS);
81
+ const totalPixels = canvasBounds.width * canvasBounds.height;
82
+ if (totalPixels > 0) {
83
+ if (totalPixels > LARGE_SCREEN_PIXEL_THRESHOLD) {
84
+ this.wheelThrottleTime = LARGE_SCREEN_THROTTLE_MS;
85
+ }
86
+ else {
87
+ this.wheelThrottleTime = SAFARI_THROTTLE_MS;
88
+ }
89
+ }
90
+ else {
91
+ this.wheelThrottleTime = DEFAULT_THROTTLE_MS;
92
+ }
93
+ this.wheelSubscription = this.canvasInputListener
94
+ .observeWheel(allPanesHitTest)
95
+ .pipe(filter(() => this.chartPanningOptions.horizontal && this.chartPanningOptions.vertical), filter((e) => {
96
+ const device = deviceDetector();
97
+ if (device === 'apple') {
98
+ const minDelta = 1.0;
99
+ return Math.abs(e.deltaY) > minDelta || Math.abs(e.deltaX) > minDelta;
100
+ }
101
+ return true;
102
+ }), throttleTime(this.wheelThrottleTime, animationFrameScheduler, { trailing: true, leading: true }))
103
+ .subscribe(e => {
104
+ const now = performance.now();
105
+ if (!this.lastWheelTime) {
106
+ this.lastWheelTime = now;
107
+ this.wheelCount = 0;
108
+ }
109
+ this.wheelCount++;
110
+ if (now - this.lastWheelTime > WHEEL_MONITORING_INTERVAL_MS) {
111
+ const wheelEventsPerSecond = Math.round((this.wheelCount * 1000) / (now - this.lastWheelTime));
112
+ if (wheelEventsPerSecond < LOW_WHEEL_EVENTS_THRESHOLD) {
113
+ this.consecutiveLowWheelEvents++;
114
+ if (this.consecutiveLowWheelEvents >= 1) {
115
+ this.triggerPerformanceCleanup();
116
+ this.consecutiveLowWheelEvents = 0;
117
+ }
118
+ }
119
+ else {
120
+ this.consecutiveLowWheelEvents = 0;
121
+ }
122
+ this.lastWheelTime = now;
123
+ this.wheelCount = 0;
124
+ }
125
+ const device = deviceDetector();
126
+ const direction = device === 'apple' || device === 'mobile' ? -1 : 1;
127
+ const deltaX = 0 + e.deltaX * direction;
128
+ const deltaY = 0 + e.deltaY * direction;
129
+ if (e.ctrlKey) {
130
+ const zoomSensitivity = this.calculateDynamicSesitivity(e, this.config.scale.zoomSensitivity.wheel);
131
+ this.zoomXHandler(e, zoomSensitivity);
132
+ this.bus.fireDraw();
133
+ return;
134
+ }
135
+ if (deltaY !== 0 && Math.abs(deltaY) > Math.abs(deltaX)) {
136
+ const zoomSensitivity = this.calculateDynamicSesitivity(e, this.config.scale.zoomSensitivity.wheel);
137
+ this.zoomXHandler(e, zoomSensitivity);
138
+ this.bus.fireDraw();
139
+ }
140
+ if (deltaX !== 0 && Math.abs(deltaX) > Math.abs(deltaY)) {
141
+ const unitsDelta = pixelsToUnits(deltaX, this.scale.zoomX);
142
+ this.scale.moveXStart(this.scale.xStart - unitsDelta);
143
+ this.bus.fireDraw();
144
+ return;
145
+ }
146
+ });
147
+ this.addRxSubscription(this.wheelSubscription);
148
+ }
149
+ /**
150
+ * Manual cleanup trigger for immediate performance recovery
151
+ */
152
+ triggerPerformanceCleanup() {
153
+ window.dispatchEvent(new Event('resize'));
154
+ if (window.gc) {
155
+ window.gc();
156
+ }
157
+ if (this.initFrameId) {
158
+ cancelAnimationFrame(this.initFrameId);
159
+ this.initFrameId = null;
160
+ }
161
+ if (this.scale && typeof this.scale.haltAnimation === 'function') {
162
+ this.scale.haltAnimation();
163
+ }
164
+ this.consecutiveLowWheelEvents = 0;
165
+ this.wheelCount = 0;
166
+ this.lastWheelTime = 0;
167
+ }
168
+ doDeactivate() {
169
+ if (this.wheelSubscription) {
170
+ this.wheelSubscription.unsubscribe();
171
+ this.wheelSubscription = null;
172
+ }
173
+ if (this.initFrameId) {
174
+ cancelAnimationFrame(this.initFrameId);
175
+ this.initFrameId = null;
176
+ }
177
+ this.isActivated = false;
178
+ super.doDeactivate();
179
+ }
180
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
3
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
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
+ */
6
+ export type SafariThrottleTimeMS = number;
7
+ /**
8
+ * Safari canvas performance limits because of Safari's GPU limits
9
+ */
10
+ export declare const SAFARI_CANVAS_LIMITS: {
11
+ readonly MAX_DIMENSION: 2048;
12
+ readonly MAX_TOTAL_PIXELS: 1800000;
13
+ readonly ZOOM_OPTIMIZED_PIXELS: 1200000;
14
+ };
15
+ export declare const LARGE_SCREEN_PIXEL_THRESHOLD = 2000000;
16
+ export declare const LARGE_SCREEN_THROTTLE_MS = 24;
17
+ export declare const SAFARI_THROTTLE_MS = 20;
18
+ export declare const DEFAULT_THROTTLE_MS = 16;
19
+ export declare const LOW_WHEEL_EVENTS_THRESHOLD = 10;
20
+ export declare const WHEEL_MONITORING_INTERVAL_MS = 1000;
21
+ /**
22
+ * Threshold for significant canvas area change to trigger subscription recreation
23
+ * Prevents unnecessary recreation for minor size adjustments
24
+ */
25
+ export declare const CANVAS_AREA_CHANGE_THRESHOLD = 50000;
26
+ export declare const SafariThrottleTimeMSMap: {
27
+ readonly MIN: 60;
28
+ readonly LOW: 80;
29
+ readonly MEDIUM: 100;
30
+ readonly HIGH: 120;
31
+ readonly MAX: 150;
32
+ };
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
3
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
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
+ */
6
+ /**
7
+ * Safari canvas performance limits because of Safari's GPU limits
8
+ */
9
+ export const SAFARI_CANVAS_LIMITS = {
10
+ MAX_DIMENSION: 2048,
11
+ MAX_TOTAL_PIXELS: 1800000,
12
+ ZOOM_OPTIMIZED_PIXELS: 1200000,
13
+ };
14
+ export const LARGE_SCREEN_PIXEL_THRESHOLD = 2000000; // 2M pixels
15
+ export const LARGE_SCREEN_THROTTLE_MS = 24;
16
+ export const SAFARI_THROTTLE_MS = 20;
17
+ export const DEFAULT_THROTTLE_MS = 16;
18
+ export const LOW_WHEEL_EVENTS_THRESHOLD = 10; // Minimum wheel events per second
19
+ export const WHEEL_MONITORING_INTERVAL_MS = 1000;
20
+ /**
21
+ * Threshold for significant canvas area change to trigger subscription recreation
22
+ * Prevents unnecessary recreation for minor size adjustments
23
+ */
24
+ export const CANVAS_AREA_CHANGE_THRESHOLD = 50000;
25
+ export const SafariThrottleTimeMSMap = {
26
+ MIN: 60,
27
+ LOW: 80,
28
+ MEDIUM: 100,
29
+ HIGH: 120,
30
+ MAX: 150,
31
+ };
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
3
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
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
+ */
6
+ import { SafariThrottleTimeMS } from './safari-performance.model';
7
+ /**
8
+ * Safari Performance Optimization Utilities
9
+ *
10
+ * This module contains utilities specifically designed to address Safari performance issues
11
+ * during drag/zoom operations on charts.
12
+ */
13
+ /**
14
+ * Calculates optimal throttle time for hit-test wheel events based on canvas size and browser
15
+ * @param canvasArea - Total canvas area in pixels (width * height)
16
+ * @returns Throttle time in milliseconds
17
+ */
18
+ export declare function calculateHitTestThrottleTime(canvasArea: number): SafariThrottleTimeMS;
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
3
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
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
+ */
6
+ import { SAFARI_CANVAS_LIMITS, SafariThrottleTimeMSMap } from './safari-performance.model';
7
+ /**
8
+ * Safari Performance Optimization Utilities
9
+ *
10
+ * This module contains utilities specifically designed to address Safari performance issues
11
+ * during drag/zoom operations on charts.
12
+ */
13
+ /**
14
+ * Calculates optimal throttle time for hit-test wheel events based on canvas size and browser
15
+ * @param canvasArea - Total canvas area in pixels (width * height)
16
+ * @returns Throttle time in milliseconds
17
+ */
18
+ export function calculateHitTestThrottleTime(canvasArea) {
19
+ if (canvasArea > SAFARI_CANVAS_LIMITS.ZOOM_OPTIMIZED_PIXELS) {
20
+ return SafariThrottleTimeMSMap.MAX;
21
+ }
22
+ else if (canvasArea > SAFARI_CANVAS_LIMITS.ZOOM_OPTIMIZED_PIXELS * 0.75) {
23
+ return SafariThrottleTimeMSMap.HIGH;
24
+ }
25
+ else if (canvasArea > SAFARI_CANVAS_LIMITS.ZOOM_OPTIMIZED_PIXELS * 0.5) {
26
+ return SafariThrottleTimeMSMap.MEDIUM;
27
+ }
28
+ else if (canvasArea > SAFARI_CANVAS_LIMITS.ZOOM_OPTIMIZED_PIXELS * 0.25) {
29
+ return SafariThrottleTimeMSMap.LOW;
30
+ }
31
+ else {
32
+ return SafariThrottleTimeMSMap.MIN;
33
+ }
34
+ }