@devexperts/dxcharts-lite 2.7.26 → 2.7.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,15 +39,15 @@
39
39
 
40
40
  Get started with DXCharts Lite by installing the library and configuring it to your needs.
41
41
 
42
- - 🚀 [Quick start](#quick-start)
43
- - 📦 [Installation](#installation)
44
- - 🛠️ [Create Chart](#create-chart)
45
- - 📈 [Set data](#set-data)
46
- - 📄 [HTML markup](#html-markup)
47
- - ⚙️ [Configuration](#configuration)
48
- - 🔌 [API](#api)
49
- - 📒 [Examples](#examples)
50
- - 🧮 [Demo](#demo)
42
+ - 🚀 [Quick start](#quick-start)
43
+ - 📦 [Installation](#installation)
44
+ - 🛠️ [Create Chart](#create-chart)
45
+ - 📈 [Set data](#set-data)
46
+ - 📄 [HTML markup](#html-markup)
47
+ - ⚙️ [Configuration](#configuration)
48
+ - 🔌 [API](#api)
49
+ - 📒 [Examples](#examples)
50
+ - 🧮 [Demo](#demo)
51
51
 
52
52
  ## Quick-start
53
53
 
@@ -84,8 +84,8 @@ The `createChart` method creates a new chart instance using `ChartBootstrap` cla
84
84
 
85
85
  It accepts two parameters:
86
86
 
87
- - `element`: The HTML element where the chart will be rendered.
88
- - `config` (optional): An instance of [ChartConfig](/chart/chart-config/overview).
87
+ - `element`: The HTML element where the chart will be rendered.
88
+ - `config` (optional): An instance of [ChartConfig](/chart/chart-config/overview).
89
89
 
90
90
  > Note: Set `width: 100%` and `height: 100%` for the parent container.
91
91
  > By default, the chart auto-resizes to the parent, but you can change this by setting `fixedSize` in the config.
@@ -149,7 +149,7 @@ You can configure the chart using a `ChartConfig` object (optional).
149
149
  `ChartConfig` sets the initial properties for the chart instance.
150
150
  Below is a table of available options (see documentation for details).
151
151
 
152
- - [`FullChartConfig`](docs/generated/FullChartConfig.md)
152
+ - [`FullChartConfig`](docs/generated/FullChartConfig.md)
153
153
 
154
154
  ## API
155
155
 
@@ -157,18 +157,18 @@ Each chart component has an API that allows you to change many parameters on the
157
157
 
158
158
  Main components include:
159
159
 
160
- - [`ChartComponent`](docs/generated/ChartComponent.md): Set data, subscribe to data changes
161
- - [`XAxisComponent`](docs/generated/XAxisComponent.md): Configure x-axis labels
162
- - [`YAxisComponent`](docs/generated/YAxisComponent.md): Configure y-axis labels and type
163
- - [`CrossToolComponent`](docs/generated/CrossToolComponent.md): Crosshair type, OHLC magnet
164
- - [`EventsComponent`](docs/generated/EventsComponent.md): Set events data
165
- - [`VolumesComponent`](docs/generated/VolumesComponent.md): Set volume data
166
- - [`WaterMarkComponent`](docs/generated/WaterMarkComponent.md): Create and manage a watermark
167
- - [`NavigationMapComponent`](docs/generated/NavigationMapComponent.md): Create a navigation map
168
- - [`SnapshotComponent`](docs/generated/SnapshotComponent.md): Create a snapshot
169
- - [`HighlightsComponent`](docs/generated/HighlightsComponent.md): Draw highlights on canvas objects such as labels
170
- - [`PaneManager`](docs/generated/PaneManager.md): Create and manage panes
171
- - [`PaneComponent`](docs/generated/PaneComponent.md): Create and manage pane data series
160
+ - [`ChartComponent`](docs/generated/ChartComponent.md): Set data, subscribe to data changes
161
+ - [`XAxisComponent`](docs/generated/XAxisComponent.md): Configure x-axis labels
162
+ - [`YAxisComponent`](docs/generated/YAxisComponent.md): Configure y-axis labels and type
163
+ - [`CrossToolComponent`](docs/generated/CrossToolComponent.md): Crosshair type, OHLC magnet
164
+ - [`EventsComponent`](docs/generated/EventsComponent.md): Set events data
165
+ - [`VolumesComponent`](docs/generated/VolumesComponent.md): Set volume data
166
+ - [`WaterMarkComponent`](docs/generated/WaterMarkComponent.md): Create and manage a watermark
167
+ - [`NavigationMapComponent`](docs/generated/NavigationMapComponent.md): Create a navigation map
168
+ - [`SnapshotComponent`](docs/generated/SnapshotComponent.md): Create a snapshot
169
+ - [`HighlightsComponent`](docs/generated/HighlightsComponent.md): Draw highlights on canvas objects such as labels
170
+ - [`PaneManager`](docs/generated/PaneManager.md): Create and manage panes
171
+ - [`PaneComponent`](docs/generated/PaneComponent.md): Create and manage pane data series
172
172
 
173
173
  ## Examples
174
174
 
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { DEFAULT_ANIMATION_TIME_MS, VIEWPORT_ANIMATION_ID } from './canvas-animation';
7
7
  const VIEWPORT_ANIMATION_DURATION_MS = DEFAULT_ANIMATION_TIME_MS;
8
- const STUCK_ANIMATION_THRESHOLD = 0.90; // Force finish animations stuck at 90%+
8
+ const STUCK_ANIMATION_THRESHOLD = 0.9; // Force finish animations stuck at 90%+
9
9
  /**
10
10
  * Starts the animation for chart viewport movement for safari.
11
11
  * @param canvasAnimation
@@ -545,7 +545,7 @@ export class CanvasBoundsContainer {
545
545
  const nMap = this.getBounds(CanvasElement.N_MAP);
546
546
  const { height, width } = this.config.components.navigationMap.knots;
547
547
  const knotHeightFromConfig = height !== null && height !== void 0 ? height : 0;
548
- const knotWidthFromConfig = isMobile() ? width * KNOTS_W_MOBILE_MULTIPLIER : width !== null && width !== void 0 ? width : 0;
548
+ const knotWidthFromConfig = isMobile() ? width * KNOTS_W_MOBILE_MULTIPLIER : (width !== null && width !== void 0 ? width : 0);
549
549
  const knotY = !knotHeightFromConfig ? nMap.y : nMap.y + (nMap.height - knotHeightFromConfig) / 2;
550
550
  // time labels
551
551
  const timeLabelsVisible = (_b = (_a = this.config.components.navigationMap) === null || _a === void 0 ? void 0 : _a.timeLabels) === null || _b === void 0 ? void 0 : _b.visible;
@@ -13,6 +13,7 @@ import { deviceDetector } from '../../utils/device/device-detector.utils';
13
13
  import { getTouchpadSensitivity } from '../../utils/device/touchpad.utils';
14
14
  import { DragNDropXComponent } from '../dran-n-drop_helper/drag-n-drop-x.component';
15
15
  import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.component';
16
+ import { ONE_FRAME_MS } from '../../utils/numeric-constants.utils';
16
17
  /**
17
18
  * ChartAreaPanHandler is a class that handles the panning and zooming of the chart area.
18
19
  * It extends the ChartBaseElement class and has the following properties:
@@ -45,7 +46,7 @@ export class ChartAreaPanHandler extends ChartBaseElement {
45
46
  // number of candles delta changed during X dragging: 1, 5 or -3 for ex.
46
47
  this.xDraggedCandlesDelta = 0;
47
48
  this.lastXStart = 0;
48
- this.wheelThrottleTime = 15; // in ms
49
+ this.wheelThrottleTime = ONE_FRAME_MS;
49
50
  this.chartPanningOptions = {
50
51
  horizontal: true,
51
52
  vertical: true,
@@ -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 { treasuryPriceFormatter, parseTreasuryPrice, isTreasuryPriceFormat, TREASURY_32ND } from '../treasury-price.formatter';
6
+ import { treasuryPriceFormatter, parseTreasuryPrice, isTreasuryPriceFormat, TREASURY_32ND, } from '../treasury-price.formatter';
7
7
  describe('Treasury Price Formatter', () => {
8
8
  describe('treasuryPriceFormatter', () => {
9
9
  it('should format decimal prices to treasury format', () => {
@@ -33,12 +33,12 @@ describe('Treasury Price Formatter', () => {
33
33
  expect(parseTreasuryPrice("1'00")).toBe(1.0);
34
34
  });
35
35
  it('should return NaN for invalid formats', () => {
36
- expect(parseTreasuryPrice("invalid")).toBe(NaN);
36
+ expect(parseTreasuryPrice('invalid')).toBe(NaN);
37
37
  expect(parseTreasuryPrice("132'")).toBe(NaN);
38
38
  expect(parseTreasuryPrice("'10")).toBe(NaN);
39
39
  expect(parseTreasuryPrice("132'1")).toBe(NaN);
40
40
  expect(parseTreasuryPrice("132'100")).toBe(NaN);
41
- expect(parseTreasuryPrice("abc123")).toBe(NaN);
41
+ expect(parseTreasuryPrice('abc123')).toBe(NaN);
42
42
  });
43
43
  });
44
44
  describe('isTreasuryPriceFormat', () => {
@@ -49,8 +49,8 @@ describe('Treasury Price Formatter', () => {
49
49
  expect(isTreasuryPriceFormat("1'31")).toBe(true);
50
50
  });
51
51
  it('should reject invalid formats', () => {
52
- expect(isTreasuryPriceFormat("invalid")).toBe(false);
53
- expect(isTreasuryPriceFormat("132")).toBe(false);
52
+ expect(isTreasuryPriceFormat('invalid')).toBe(false);
53
+ expect(isTreasuryPriceFormat('132')).toBe(false);
54
54
  expect(isTreasuryPriceFormat("132'")).toBe(false);
55
55
  expect(isTreasuryPriceFormat("'10")).toBe(false);
56
56
  expect(isTreasuryPriceFormat("132'1")).toBe(false);
@@ -31,6 +31,9 @@ export const createRegularPriceFormatter = (extent, config) => (value) => {
31
31
  return `${checkedValue}`;
32
32
  };
33
33
  export const createPercentFormatter = (extent) => (value, dataSeries) => {
34
+ if (value === 0) {
35
+ return '0.00 %';
36
+ }
34
37
  const [mainDataSeries] = extent.dataSeries;
35
38
  let valueUnit = value;
36
39
  const series = dataSeries !== null && dataSeries !== void 0 ? dataSeries : mainDataSeries;
@@ -40,7 +40,7 @@ export const parseTreasuryPrice = (value) => {
40
40
  const integerPart = parseInt(match[1], 10);
41
41
  const thirtySeconds = parseInt(match[2], 10);
42
42
  // Convert 32nds to decimal
43
- const decimalPart = (thirtySeconds * TREASURY_32ND);
43
+ const decimalPart = thirtySeconds * TREASURY_32ND;
44
44
  return integerPart + decimalPart;
45
45
  }
46
46
  // Return Number(value) for non-treasury formats (this will be NaN for invalid strings)
@@ -8,7 +8,7 @@ import { ChartBaseElement } from '../../model/chart-base-element';
8
8
  import { ChartModel } from '../chart/chart.model';
9
9
  export type HighlightTextPlacement = 'left-left' | 'left-right' | 'right-left' | 'right-right';
10
10
  export declare const HIGHLIGHTS_TYPES: readonly ["AFTER_MARKET", "PRE_MARKET", "NO_TRADING", "REGULAR"];
11
- export type HighlightType = typeof HIGHLIGHTS_TYPES[number];
11
+ export type HighlightType = (typeof HIGHLIGHTS_TYPES)[number];
12
12
  export type VisualHighlights = Partial<Record<HighlightType, Highlight[]>>;
13
13
  export interface Highlight {
14
14
  type: HighlightType;
@@ -29,7 +29,7 @@ export class VolumesComponent extends ChartBaseElement {
29
29
  this.volumesModel = volumesModel;
30
30
  this.addChildEntity(volumesModel);
31
31
  this.separateVolumes = new SeparateVolumesComponent(chartComponent, config, volumesModel, paneManager);
32
- 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);
32
+ 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);
33
33
  config.components.volumes.visible && this.syncVolumesDynamicObject();
34
34
  this.addChildEntity(this.separateVolumes);
35
35
  this.registerDefaultVolumeColorResolvers();
@@ -7,8 +7,8 @@ declare const weekWeekday: "week-weekday";
7
7
  declare const timeFormatsConfirugable: readonly ["second", "minute", "hour", "day", "month", "year"];
8
8
  declare const timeFormatsNoNConfirugable: readonly ["lessThanSecond"];
9
9
  type TimeFormatWeekWeekdayType = typeof weekWeekday;
10
- type TimeFormatConfirugableType = typeof timeFormatsConfirugable[number];
11
- type TimeFormatNonConfirugableType = typeof timeFormatsNoNConfirugable[number];
10
+ type TimeFormatConfirugableType = (typeof timeFormatsConfirugable)[number];
11
+ type TimeFormatNonConfirugableType = (typeof timeFormatsNoNConfirugable)[number];
12
12
  export type TimeFormat = TimeFormatConfirugableType | TimeFormatNonConfirugableType | TimeFormatWeekWeekdayType;
13
13
  type TimeFormatConfirugableWithDurationType = `${TimeFormatConfirugableType}_${number}` | `${TimeFormatConfirugableType}_${number}!` | `${TimeFormatWeekWeekdayType}_${number | '$'}_${number}`;
14
14
  export type TimeFormatWithDuration = TimeFormatConfirugableWithDurationType | TimeFormatNonConfirugableType;
@@ -7,7 +7,7 @@ import EventBus from '../events/event-bus';
7
7
  import { ChartResizeHandler } from '../inputhandlers/chart-resize.handler';
8
8
  export declare const HIT_TEST_PREFIX = "HIT_TEST_";
9
9
  declare const drawerTypes: readonly ["MAIN_BACKGROUND", "MAIN_CLEAR", "HIT_TEST_CLEAR", "YAXIS_CLEAR", "SERIES_CLEAR", "OVER_SERIES_CLEAR", "HIT_TEST_DRAWINGS", "GRID", "X_AXIS", "Y_AXIS", "HIGH_LOW", "DYNAMIC_OBJECTS", "N_MAP_CHART", "PL_CHART", "WATERMARK", "EMPTY_CHART", "OFFLINE_CHART", "LABELS", "EVENTS", "HIT_TEST_EVENTS", "ZERO_LINE", "PL_ZERO_LINE_BACKGROUND", "CROSS_TOOL"];
10
- export type DrawerType = typeof drawerTypes[number];
10
+ export type DrawerType = (typeof drawerTypes)[number];
11
11
  /**
12
12
  * Manages the drawing process.
13
13
  * Can re-order drawers to make one be on top of the other.
@@ -58,6 +58,10 @@ export declare class HoverProducerComponent extends ChartBaseElement {
58
58
  hoverSubject: BehaviorSubject<Hover | null>;
59
59
  get hover(): Hover | null;
60
60
  longTouchActivatedSubject: BehaviorSubject<boolean>;
61
+ /**
62
+ * When true, mobile long-touch (e.g. 200ms) does not activate crosshair / disable pan.
63
+ */
64
+ private longTouchCrosshairSuppressed;
61
65
  private hoverProducerParts;
62
66
  xFormatter: DateTimeFormatter;
63
67
  constructor(crossEventProducer: CrossEventProducerComponent, scale: ScaleModel, config: FullChartConfig, chartModel: ChartModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, paneManager: PaneManager, timeZoneModel: TimeZoneModel, mainCanvasTouchHandler: MainCanvasTouchHandler, formatterFactory: (format: string) => (timestamp: number) => string);
@@ -125,6 +129,7 @@ export declare class HoverProducerComponent extends ChartBaseElement {
125
129
  * Fires the last hover update if there is a last cross.
126
130
  */
127
131
  fireLastCross(): void;
132
+ setLongTouchCrosshairSuppressed(value: boolean): void;
128
133
  /**
129
134
  * Registers a hover producer part with the given id.
130
135
  *
@@ -34,6 +34,10 @@ export class HoverProducerComponent extends ChartBaseElement {
34
34
  this.formatterFactory = formatterFactory;
35
35
  this.hoverSubject = new BehaviorSubject(null);
36
36
  this.longTouchActivatedSubject = new BehaviorSubject(false);
37
+ /**
38
+ * When true, mobile long-touch (e.g. 200ms) does not activate crosshair / disable pan.
39
+ */
40
+ this.longTouchCrosshairSuppressed = false;
37
41
  this.xFormatter = () => '';
38
42
  const candleHoverProducerPart = new CandleHoverProducerPart(this.chartModel);
39
43
  const compareSeriesHoverProducerPart = new CompareSeriesHoverProducerPart(this.chartModel);
@@ -104,6 +108,9 @@ export class HoverProducerComponent extends ChartBaseElement {
104
108
  const hitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
105
109
  this.addRxSubscription(this.canvasInputListener.observeLongTouchStart(hitTest).subscribe(event => {
106
110
  var _a;
111
+ if (this.longTouchCrosshairSuppressed) {
112
+ return;
113
+ }
107
114
  this.crossEventProducer.crossToolHover = null;
108
115
  this.crossEventProducer.crossToolTouchInfo.isCommonTap = false;
109
116
  // don't lock chart and show crosshair if chart is being moved, crosstool is not enabled or we do pinch event
@@ -283,6 +290,9 @@ export class HoverProducerComponent extends ChartBaseElement {
283
290
  this.createAndFireHover(lastCross);
284
291
  }
285
292
  }
293
+ setLongTouchCrosshairSuppressed(value) {
294
+ this.longTouchCrosshairSuppressed = value;
295
+ }
286
296
  /**
287
297
  * Registers a hover producer part with the given id.
288
298
  *
@@ -128,13 +128,14 @@ export class ScaleModel extends ViewportModel {
128
128
  * @param zoomSensitivity - The sensitivity of the zoom. Default value is taken from the configuration object.
129
129
  */
130
130
  zoomXToEnd(zoomIn, zoomSensitivity) {
131
- if (this.config.scale.disableAnimations) {
131
+ const disableAnimations = this.config.scale.disableAnimations || this.config.components.yAxis.type === 'percent';
132
+ if (disableAnimations) {
132
133
  this.haltAnimation();
133
134
  }
134
135
  this.beforeStartAnimationSubject.next();
135
136
  const state = this.export();
136
137
  zoomXToEndViewportCalculator(this, state, zoomSensitivity, zoomIn);
137
- this.zoomXTo(state, zoomIn, this.config.scale.disableAnimations);
138
+ this.zoomXTo(state, zoomIn, disableAnimations);
138
139
  }
139
140
  haltAnimation() {
140
141
  var _a;
@@ -232,7 +233,7 @@ export class ScaleModel extends ViewportModel {
232
233
  const vCandles = visualCandleSource.slice(Math.max(visualCandleSource.length - this.state.defaultViewportItems, 0));
233
234
  const endCandle = vCandles[vCandles.length - 1];
234
235
  const xEnd = endCandle.startUnit + endCandle.width + this.offsets.right;
235
- const xStart = xEnd - (this.getBounds().width * this.zoomX);
236
+ const xStart = xEnd - this.getBounds().width * this.zoomX;
236
237
  const state = Object.assign(Object.assign({}, initialStateCopy), { xStart, xEnd });
237
238
  const constrainedState = this.scalePostProcessor(initialStateCopy, state);
238
239
  if (this.state.auto) {
@@ -8,7 +8,7 @@ export declare const MouseButton: {
8
8
  middle: number;
9
9
  right: number;
10
10
  };
11
- export type MouseButtonType = typeof MouseButton[keyof typeof MouseButton];
11
+ export type MouseButtonType = (typeof MouseButton)[keyof typeof MouseButton];
12
12
  /**
13
13
  * @param {Element} element
14
14
  * @param {function} listener