@tradecanvas/chart 0.8.1 → 0.9.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 (42) hide show
  1. package/README.md +223 -48
  2. package/dist/Chart.d.ts +11 -0
  3. package/dist/Chart.d.ts.map +1 -1
  4. package/dist/{Chart-Cn_TSMO7.js → DragDropImporter-6QOjnfSj.js} +361 -85
  5. package/dist/DragDropImporter-6QOjnfSj.js.map +1 -0
  6. package/dist/DragDropImporter-CQ3EarQn.cjs +2 -0
  7. package/dist/DragDropImporter-CQ3EarQn.cjs.map +1 -0
  8. package/dist/index.cjs +1 -1
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +26 -26
  13. package/dist/index.js.map +1 -1
  14. package/dist/io/DragDropImporter.d.ts +34 -0
  15. package/dist/io/DragDropImporter.d.ts.map +1 -0
  16. package/dist/io/index.d.ts +5 -0
  17. package/dist/io/index.d.ts.map +1 -0
  18. package/dist/io/parseOHLCV.d.ts +21 -0
  19. package/dist/io/parseOHLCV.d.ts.map +1 -0
  20. package/dist/widget/ChartWidget.d.ts +46 -1
  21. package/dist/widget/ChartWidget.d.ts.map +1 -1
  22. package/dist/widget/WidgetHotkeySheet.d.ts +20 -0
  23. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -0
  24. package/dist/widget/WidgetReplayBar.d.ts +41 -0
  25. package/dist/widget/WidgetReplayBar.d.ts.map +1 -0
  26. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  27. package/dist/widget/WidgetSymbolSearch.d.ts +32 -0
  28. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -0
  29. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  30. package/dist/widget/WidgetWatchlist.d.ts +39 -0
  31. package/dist/widget/WidgetWatchlist.d.ts.map +1 -0
  32. package/dist/widget/index.cjs +1455 -877
  33. package/dist/widget/index.cjs.map +1 -1
  34. package/dist/widget/index.js +695 -92
  35. package/dist/widget/index.js.map +1 -1
  36. package/dist/widget/types.d.ts +19 -0
  37. package/dist/widget/types.d.ts.map +1 -1
  38. package/dist/widget/widgetConfig.d.ts.map +1 -1
  39. package/package.json +3 -3
  40. package/dist/Chart-Br_N-BCL.cjs +0 -2
  41. package/dist/Chart-Br_N-BCL.cjs.map +0 -1
  42. package/dist/Chart-Cn_TSMO7.js.map +0 -1
@@ -1,57 +1,57 @@
1
1
  import { DARK_THEME as e, DEFAULT_PANEL_HEIGHT as t, LIGHT_THEME as n, LayerType as r, MIN_PANEL_HEIGHT as i, PRICE_AXIS_WIDTH as a, TIME_AXIS_HEIGHT as o, computePriceLimits as s, mergeBar as c, setLocale as l, timeframeToMs as u } from "@tradecanvas/commons";
2
- import { AlertManager as d, Animator as f, AreaRenderer as p, BarCountdown as m, BarRenderer as ee, BaselineRenderer as h, CandlestickRenderer as g, ChartLegend as te, ChartStateManager as _, CompareRenderer as v, CrosshairHandler as ne, CrosshairTooltip as re, CurrentPriceLine as ie, DataExporter as y, DrawingManager as ae, DrawingRenderer as oe, EquivolumeRenderer as se, EventBus as ce, GridRenderer as le, HLCAreaRenderer as ue, HollowCandleRenderer as de, IndicatorEngine as b, InteractionManager as fe, KagiRenderer as x, KeyboardHandler as S, LineRenderer as C, LineWithMarkersRenderer as w, PanHandler as T, PointAndFigureRenderer as E, PriceAxis as D, RenderEngine as O, RenkoRenderer as k, ReplayManager as A, Screenshot as j, SessionBreaks as M, SignalMarkerManager as N, StepLineRenderer as P, StreamManager as F, TimeAxis as I, TradeZoneManager as L, TradingManager as R, TradingRenderer as z, UndoRedoManager as B, Viewport as V, VolumeCandleRenderer as pe, VolumeRenderer as me, Watermark as he, ZoomHandler as ge, registerBuiltInDrawingTools as _e, registerBuiltInIndicators as H, toHeikinAshi as ve, toKagi as ye, toLineBreak as be, toPointAndFigure as xe, toRangeBars as Se, toRenko as Ce } from "@tradecanvas/core";
2
+ import { AlertManager as d, Animator as f, AreaRenderer as p, AxisDragHandler as m, BarCountdown as ee, BarRenderer as te, BaselineRenderer as ne, CandlestickRenderer as h, ChartLegend as g, ChartStateManager as _, CompareRenderer as re, CrosshairHandler as ie, CrosshairTooltip as ae, CurrentPriceLine as oe, DataExporter as v, DrawingManager as se, DrawingRenderer as ce, EquivolumeRenderer as le, EventBus as ue, GridRenderer as de, HLCAreaRenderer as fe, HollowCandleRenderer as pe, IndicatorEngine as y, InteractionManager as me, KagiRenderer as he, KeyboardHandler as ge, LineRenderer as _e, LineWithMarkersRenderer as ve, MeasureOverlay as ye, PanHandler as be, PinnedTooltip as xe, PointAndFigureRenderer as Se, PriceAxis as Ce, RenderEngine as we, RenkoRenderer as Te, ReplayManager as b, Screenshot as x, SessionBreaks as S, SignalMarkerManager as C, StepLineRenderer as w, StreamManager as T, TimeAxis as E, TradeZoneManager as D, TradingManager as O, TradingRenderer as Ee, UndoRedoManager as De, Viewport as Oe, VolumeCandleRenderer as ke, VolumeProfileRenderer as Ae, VolumeRenderer as je, Watermark as Me, ZoomHandler as Ne, registerBuiltInDrawingTools as Pe, registerBuiltInIndicators as k, toHeikinAshi as Fe, toKagi as Ie, toLineBreak as Le, toPointAndFigure as Re, toRangeBars as ze, toRenko as Be } from "@tradecanvas/core";
3
3
  //#region src/charts/ChartTypeStrategy.ts
4
- function we(e) {
4
+ function Ve(e) {
5
5
  switch (e) {
6
6
  case "candlestick":
7
7
  case "heikinAshi":
8
8
  case "lineBreak":
9
- case "rangeBars": return new g();
10
- case "line": return new C();
9
+ case "rangeBars": return new h();
10
+ case "line": return new _e();
11
11
  case "area": return new p();
12
- case "bar": return new ee();
13
- case "hollowCandle": return new de();
14
- case "baseline": return new h();
15
- case "renko": return new k();
16
- case "kagi": return new x();
17
- case "pointAndFigure": return new E();
18
- case "volumeCandles": return new pe();
19
- case "equivolume": return new se();
20
- case "hlcArea": return new ue();
21
- case "stepLine": return new P();
22
- case "lineWithMarkers": return new w();
23
- default: return new g();
12
+ case "bar": return new te();
13
+ case "hollowCandle": return new pe();
14
+ case "baseline": return new ne();
15
+ case "renko": return new Te();
16
+ case "kagi": return new he();
17
+ case "pointAndFigure": return new Se();
18
+ case "volumeCandles": return new ke();
19
+ case "equivolume": return new le();
20
+ case "hlcArea": return new fe();
21
+ case "stepLine": return new w();
22
+ case "lineWithMarkers": return new ve();
23
+ default: return new h();
24
24
  }
25
25
  }
26
- function Te(e, t) {
26
+ function He(e, t) {
27
27
  if (t.length === 0) return t;
28
28
  switch (e) {
29
- case "heikinAshi": return ve(t);
30
- case "renko": return Ce(t, {
29
+ case "heikinAshi": return Fe(t);
30
+ case "renko": return Be(t, {
31
31
  brickSize: 0,
32
32
  useATR: !0,
33
33
  atrPeriod: 14
34
34
  });
35
- case "lineBreak": return be(t, 3);
36
- case "kagi": return ye(t, 4);
37
- case "pointAndFigure": return xe(t, U(t) * .01, 3);
38
- case "rangeBars": return Se(t, { rangeSize: U(t) * .005 });
35
+ case "lineBreak": return Le(t, 3);
36
+ case "kagi": return Ie(t, 4);
37
+ case "pointAndFigure": return Re(t, A(t) * .01, 3);
38
+ case "rangeBars": return ze(t, { rangeSize: A(t) * .005 });
39
39
  default: return t;
40
40
  }
41
41
  }
42
- function U(e) {
42
+ function A(e) {
43
43
  let t = 0;
44
44
  for (let n of e) t += n.close;
45
45
  return t / e.length;
46
46
  }
47
47
  //#endregion
48
48
  //#region src/charts/IndicatorPriceRange.ts
49
- var W = {
49
+ var j = {
50
50
  min: 0,
51
51
  max: 100
52
- }, G = .1;
53
- function Ee(e, t, n) {
54
- if (!e) return { ...W };
52
+ }, M = .1;
53
+ function Ue(e, t, n) {
54
+ if (!e) return { ...j };
55
55
  let r = Infinity, i = -Infinity, a = 0;
56
56
  for (let [, o] of e.values) {
57
57
  if (a >= t && a <= n) for (let e in o) {
@@ -60,16 +60,16 @@ function Ee(e, t, n) {
60
60
  }
61
61
  a++;
62
62
  }
63
- if (r === Infinity) return { ...W };
63
+ if (r === Infinity) return { ...j };
64
64
  let o = i - r || 1;
65
65
  return {
66
- min: r - o * G,
67
- max: i + o * G
66
+ min: r - o * M,
67
+ max: i + o * M
68
68
  };
69
69
  }
70
70
  //#endregion
71
71
  //#region src/state/AutoSaveScheduler.ts
72
- var De = class {
72
+ var We = class {
73
73
  timer = null;
74
74
  delayMs = 0;
75
75
  key = null;
@@ -99,12 +99,12 @@ var De = class {
99
99
  };
100
100
  //#endregion
101
101
  //#region src/DataManager.ts
102
- function K(e) {
102
+ function N(e) {
103
103
  if (!e || typeof e.time != "number") return !1;
104
104
  let { open: t, high: n, low: r, close: i } = e;
105
105
  return !(!isFinite(t) || !isFinite(n) || !isFinite(r) || !isFinite(i) || t < 0 || n < 0 || r < 0 || i < 0 || n < r || e.volume !== void 0 && (!isFinite(e.volume) || e.volume < 0));
106
106
  }
107
- function q(e) {
107
+ function P(e) {
108
108
  return {
109
109
  ...e,
110
110
  high: Math.max(e.open, e.high, e.low, e.close),
@@ -112,20 +112,20 @@ function q(e) {
112
112
  volume: e.volume === void 0 ? 0 : Math.max(0, e.volume)
113
113
  };
114
114
  }
115
- var J = class {
115
+ var F = class {
116
116
  data = [];
117
117
  getData() {
118
118
  return this.data;
119
119
  }
120
120
  setData(e) {
121
- this.data = e.filter(K).map(q);
121
+ this.data = e.filter(N).map(P);
122
122
  }
123
123
  appendBar(e) {
124
- K(e) && this.data.push(q(e));
124
+ N(e) && this.data.push(P(e));
125
125
  }
126
126
  updateLastBar(e) {
127
- if (!K(e)) return;
128
- let t = q(e);
127
+ if (!N(e)) return;
128
+ let t = P(e);
129
129
  if (this.data.length === 0) {
130
130
  this.data.push(t);
131
131
  return;
@@ -141,7 +141,7 @@ var J = class {
141
141
  clear() {
142
142
  this.data = [];
143
143
  }
144
- }, Y = class {
144
+ }, I = class {
145
145
  theme;
146
146
  constructor(t) {
147
147
  !t || t === "dark" ? this.theme = { ...e } : t === "light" ? this.theme = { ...n } : this.theme = { ...t };
@@ -152,7 +152,7 @@ var J = class {
152
152
  setTheme(t) {
153
153
  t === "dark" ? this.theme = { ...e } : t === "light" ? this.theme = { ...n } : this.theme = { ...t };
154
154
  }
155
- }, X = 200, Z = 80, Q = class {
155
+ }, L = 200, R = 80, z = class {
156
156
  panels = [];
157
157
  containerWidth = 0;
158
158
  containerHeight = 0;
@@ -164,8 +164,8 @@ var J = class {
164
164
  this.panels.push({
165
165
  id: e,
166
166
  position: n,
167
- size: r ?? (a ? X : t),
168
- minSize: a ? Z : i,
167
+ size: r ?? (a ? L : t),
168
+ minSize: a ? R : i,
169
169
  content: {
170
170
  type: "indicator",
171
171
  indicatorInstanceId: e
@@ -179,7 +179,7 @@ var J = class {
179
179
  let r = this.panels.find((t) => t.id === e);
180
180
  if (r) {
181
181
  let e = r.position === "left" || r.position === "right", a = n === "left" || n === "right";
182
- r.position = n, e !== a && (r.size = a ? X : t, r.minSize = a ? Z : i);
182
+ r.position = n, e !== a && (r.size = a ? L : t, r.minSize = a ? R : i);
183
183
  }
184
184
  }
185
185
  setPanelSize(e, t) {
@@ -280,14 +280,14 @@ var J = class {
280
280
  getMainChartRect() {
281
281
  return this.resolve().mainChartRect;
282
282
  }
283
- }, $ = class {
283
+ }, B = class {
284
284
  constructor(e) {
285
285
  this.indicatorEngine = e;
286
286
  }
287
287
  registerIndicator(e) {
288
288
  this.indicatorEngine.register(e);
289
289
  }
290
- }, Oe = class {
290
+ }, Ge = class {
291
291
  static version = "0.7.0";
292
292
  engine;
293
293
  viewport;
@@ -316,14 +316,17 @@ var J = class {
316
316
  compareRenderer;
317
317
  countdownInterval = null;
318
318
  volumeRenderer;
319
+ volumeProfile;
319
320
  alertManager;
320
321
  signalMarkerManager;
321
322
  tradeZoneManager;
323
+ measureOverlay;
322
324
  replayManager;
323
325
  undoRedoManager;
324
- autoSaveScheduler = new De((e) => this.saveState(e));
326
+ autoSaveScheduler = new We((e) => this.saveState(e));
325
327
  animator;
326
328
  crosshairTooltip;
329
+ pinnedTooltip;
327
330
  interactionManager;
328
331
  crosshairHandler;
329
332
  chartRenderer;
@@ -372,36 +375,36 @@ var J = class {
372
375
  logScale: n.logScale ?? !0,
373
376
  timeframes: n.timeframes ?? [],
374
377
  defaultTimeframeFavorites: n.defaultTimeframeFavorites ?? []
375
- }, e.style.position = "relative", e.style.overflow = "hidden", e.tabIndex = 0, e.style.outline = "none", this.dataManager = new J(), this.themeManager = new Y(t.theme), this.layoutManager = new Q(), this.indicatorEngine = new b(), this.pluginManager = new $(this.indicatorEngine), this.eventBus = new ce(), H(this.indicatorEngine), this.drawingManager = new ae(), _e(this.drawingManager), this.drawingRenderer = new oe(this.drawingManager), this.drawingManager.setRequestRender(() => {
378
+ }, e.style.position = "relative", e.style.overflow = "hidden", e.tabIndex = 0, e.style.outline = "none", this.dataManager = new F(), this.themeManager = new I(t.theme), this.layoutManager = new z(), this.indicatorEngine = new y(), this.pluginManager = new B(this.indicatorEngine), this.eventBus = new ue(), k(this.indicatorEngine), this.drawingManager = new se(), Pe(this.drawingManager), this.drawingRenderer = new ce(this.drawingManager), this.drawingManager.setRequestRender(() => {
376
379
  this.syncRenderContext(), this.engine.requestRender(r.Overlay), this.scheduleAutoSave();
377
380
  }), this.drawingManager.setEventCallback((e, t) => {
378
381
  this.eventBus.emit(e, t);
379
- }), this.undoRedoManager = new B(), this.drawingManager.setUndoRedoManager(this.undoRedoManager), this.drawingManager.setDataGetter(() => this.dataManager.getData()), this.drawingManager.setDisplayDataGetter(() => this.getDisplayData()), t.crosshair?.mode === "magnet" && this.drawingManager.setMagnetMode("magnet"), this.tradingManager = new R({
382
+ }), this.undoRedoManager = new De(), this.drawingManager.setUndoRedoManager(this.undoRedoManager), this.drawingManager.setDataGetter(() => this.dataManager.getData()), this.drawingManager.setDisplayDataGetter(() => this.getDisplayData()), t.crosshair?.mode === "magnet" && this.drawingManager.setMagnetMode("magnet"), this.tradingManager = new O({
380
383
  enabled: this.features.trading,
381
384
  contextMenu: { enabled: this.features.tradingContextMenu }
382
- }), this.tradingRenderer = new z(this.tradingManager), this.tradingManager.setContainer(e), this.tradingManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradingManager.setEventCallback((e, t) => {
385
+ }), this.tradingRenderer = new Ee(this.tradingManager), this.tradingManager.setContainer(e), this.tradingManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradingManager.setEventCallback((e, t) => {
383
386
  this.eventBus.emit(e, t);
384
- }), this.engine = new O(e);
387
+ }), this.engine = new we(e);
385
388
  let i = this.engine.dprManager.getContainerSize();
386
- this.viewport = new V(i.width, i.height, t.minBarSpacing ?? 2, t.maxBarSpacing ?? 30, t.rightMargin ?? 5), this.layoutManager.resize(i.width, i.height), this.engine.onContainerResize = (e) => {
389
+ if (this.viewport = new Oe(i.width, i.height, t.minBarSpacing ?? 2, t.maxBarSpacing ?? 30, t.rightMargin ?? 5), this.layoutManager.resize(i.width, i.height), this.engine.onContainerResize = (e) => {
387
390
  if (e.width <= 0 || e.height <= 0) return;
388
391
  let t = this.viewport.isAtEnd();
389
392
  this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(t);
390
- }, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new le(), t.grid?.visible === !1 && this.gridRenderer.setVisible(!1), this.priceAxis = new D(), this.priceAxis.setLocale(this.numberLocale), this.timeAxis = new I(), this.crosshairHandler = new ne(), this.crosshairHandler.setLocale(this.numberLocale), t.crosshair?.mode && this.crosshairHandler.setMode(t.crosshair.mode), this.crosshairHandler.setCallback((e, t) => {
393
+ }, this.chartRenderer = this.createChartRenderer(t.chartType), this.gridRenderer = new de(), t.grid?.visible === !1 && this.gridRenderer.setVisible(!1), this.priceAxis = new Ce(), this.priceAxis.setLocale(this.numberLocale), this.timeAxis = new E(), this.crosshairHandler = new ie(), this.crosshairHandler.setLocale(this.numberLocale), t.crosshair?.mode && this.crosshairHandler.setMode(t.crosshair.mode), this.crosshairHandler.setCallback((e, t) => {
391
394
  if (e !== null && t) {
392
395
  let n = this.dataManager.getData(), r = e < n.length ? n[e] : void 0;
393
- this.chartLegend.setHoverBar(r ?? null), r && this.crosshairTooltip.show(t, r, this.themeManager.getTheme(), this.cachedContainerSize()), this.eventBus.emit("crosshairMove", {
396
+ this.chartLegend.setHoverBar(r ?? null), r && this.crosshairTooltip.show(t, r, this.themeManager.getTheme(), this.cachedContainerSize()), this.pinnedTooltip.isPinned() && this.pinnedTooltip.reposition(this.viewport.getState(), r ?? null, e, this.themeManager.getTheme()), this.eventBus.emit("crosshairMove", {
394
397
  point: t,
395
398
  bar: r,
396
399
  barIndex: e
397
400
  });
398
401
  } else this.crosshairTooltip.hide(), this.chartLegend.setHoverBar(null);
399
- }), this.chartLegend = new te(), this.chartLegend.setChartType(t.chartType), this.watermark = new he(), t.watermark && this.watermark.setConfig(t.watermark), this.volumeRenderer = new me(), this.barCountdown = new m(), this.sessionBreaks = new M(), this.compareRenderer = new v(), t.sessionBreaks ? this.sessionBreaks.setConfig({
402
+ }), this.chartLegend = new g(), this.chartLegend.setChartType(t.chartType), this.watermark = new Me(), t.watermark && this.watermark.setConfig(t.watermark), this.volumeRenderer = new je(), this.volumeProfile = new Ae(), this.barCountdown = new ee(), this.sessionBreaks = new S(), this.compareRenderer = new re(), t.sessionBreaks ? this.sessionBreaks.setConfig({
400
403
  visible: t.sessionBreaks.visible ?? !0,
401
404
  color: t.sessionBreaks.color,
402
405
  lineStyle: t.sessionBreaks.lineStyle,
403
406
  lineWidth: t.sessionBreaks.lineWidth
404
- }) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new f(), this.crosshairTooltip = new re(), this.crosshairTooltip.create(e), this.keyboardHandler = new S({
407
+ }) : t.features?.sessionBreaks !== !1 && this.sessionBreaks.setVisible(!0), t.logScale && this.viewport.setLogScale(!0), this.animator = new f(), this.crosshairTooltip = new ae(), this.crosshairTooltip.create(e), this.pinnedTooltip = new xe(), this.pinnedTooltip.create(e), this.keyboardHandler = new ge({
405
408
  scrollBars: (e) => {
406
409
  let t = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;
407
410
  this.viewport.scrollBy(e * t), this.updateViewportAndRender();
@@ -421,14 +424,14 @@ var J = class {
421
424
  if (!this.keyboardHandler) return;
422
425
  let t = document.activeElement;
423
426
  t && t !== this.container && !this.container.contains(t) || t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable) || this.keyboardHandler.handleKey(e) && e.preventDefault();
424
- }, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new ie(), this.alertManager = new d(), this.alertManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.alertManager.on("triggered", (e) => {
427
+ }, window.addEventListener("keydown", this.onWindowKeyDown), this.currentPriceLine = new oe(), this.alertManager = new d(), this.alertManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.alertManager.on("triggered", (e) => {
425
428
  this.eventBus.emit("dataUpdate", {
426
429
  alert: "triggered",
427
430
  alertId: e.id,
428
431
  price: e.price,
429
432
  message: e.message
430
433
  });
431
- }), this.signalMarkerManager = new N(), this.signalMarkerManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.signalMarkerManager.setDataGetter(() => this.dataManager.getData()), this.signalMarkerManager.on("added", (e) => {
434
+ }), this.signalMarkerManager = new C(), this.signalMarkerManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.signalMarkerManager.setDataGetter(() => this.dataManager.getData()), this.signalMarkerManager.on("added", (e) => {
432
435
  this.eventBus.emit("signalMarkerAdd", {
433
436
  id: e.id,
434
437
  source: e.source,
@@ -436,25 +439,54 @@ var J = class {
436
439
  });
437
440
  }), this.signalMarkerManager.on("removed", (e) => {
438
441
  this.eventBus.emit("signalMarkerRemove", { id: e });
439
- }), this.tradeZoneManager = new L(), this.tradeZoneManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradeZoneManager.setDataGetter(() => this.dataManager.getData()), this.tradeZoneManager.on("added", (e) => {
442
+ }), this.tradeZoneManager = new D(), this.tradeZoneManager.setRequestRender(() => this.engine.requestRender(r.Overlay)), this.tradeZoneManager.setDataGetter(() => this.dataManager.getData()), this.tradeZoneManager.on("added", (e) => {
440
443
  this.eventBus.emit("tradeZoneAdd", {
441
444
  id: e.id,
442
445
  direction: e.direction
443
446
  });
444
447
  }), this.tradeZoneManager.on("removed", (e) => {
445
448
  this.eventBus.emit("tradeZoneRemove", { id: e });
446
- }), this.replayManager = new A(), this.interactionManager = new fe(e), this.features.panning && this.interactionManager.setPanHandler(new T((e) => {
449
+ }), this.replayManager = new b(), this.measureOverlay = new ye(), this.interactionManager = new me(e), this.features.panning && this.interactionManager.setPanHandler(new be((e) => {
447
450
  this.viewport.scrollBy(e), this.updateViewportAndRender();
448
- })), this.features.zooming && this.interactionManager.setZoomHandler(new ge((e, t) => {
449
- this.viewport.zoom(e, t), this.updateViewportAndRender();
450
- })), this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () => ({
451
+ })), this.features.zooming) {
452
+ this.interactionManager.setZoomHandler(new Ne((e, t) => {
453
+ this.viewport.zoom(e, t), this.updateViewportAndRender();
454
+ }));
455
+ let e = new m((e) => {
456
+ this.options.autoScale = !1, this.viewport.scalePriceRange(e), this.syncRenderContext(), this.engine.requestRender();
457
+ }, (e) => {
458
+ let t = this.viewport.getState().chartRect.width;
459
+ this.viewport.zoom(1 / e - 1, t / 2), this.updateViewportAndRender();
460
+ });
461
+ this.interactionManager.setAxisDragHandler(e, () => this.viewport.getState(), (e) => {
462
+ e === "price" ? (this.options.autoScale = !0, this.updateViewportAndRender()) : this.fitContent();
463
+ });
464
+ }
465
+ this.features.crosshair && this.interactionManager.setCrosshairHandler(this.crosshairHandler), this.features.drawings && this.interactionManager.setDrawingManager(this.drawingManager, () => ({
451
466
  ...this.viewport.getState(),
452
467
  data: this.getDisplayData()
453
468
  })), this.features.trading && this.interactionManager.setTradingManager(this.tradingManager, () => ({
454
469
  ...this.viewport.getState(),
455
470
  data: this.getDisplayData()
456
- })), this.interactionManager.setOverlayDirtyCallback(() => {
457
- this.engine.requestRender(r.Overlay), this.layoutManager.getPanels().length > 0 && this.engine.requestRender(r.UI);
471
+ })), this.interactionManager.setAltClickHandler((e) => {
472
+ let t = this.getDisplayData();
473
+ if (t.length === 0) return;
474
+ let n = this.viewport.getState(), i = n.barWidth + n.barSpacing, a = Math.round((n.offset + e.x) / i);
475
+ a < 0 || a >= t.length || (this.pinnedTooltip.isPinned() && this.pinnedTooltip.getPinnedIndex() === a ? this.pinnedTooltip.unpin() : this.pinnedTooltip.pin(t[a], a, this.themeManager.getTheme()), this.pinnedTooltip.reposition(this.viewport.getState(), this.dataManager.getData()[a] ?? null, a, this.themeManager.getTheme()), this.engine.requestRender(r.Overlay));
476
+ }), this.interactionManager.setEscapeHandler(() => {
477
+ this.pinnedTooltip.isPinned() && (this.pinnedTooltip.unpin(), this.engine.requestRender(r.Overlay));
478
+ }), this.interactionManager.setMeasureHandlers({
479
+ begin: (e) => {
480
+ this.measureOverlay.begin(e, this.viewport.getState(), this.getDisplayData());
481
+ },
482
+ move: (e) => {
483
+ this.measureOverlay.update(e, this.viewport.getState(), this.getDisplayData());
484
+ },
485
+ end: () => {
486
+ this.measureOverlay.end();
487
+ }
488
+ }), this.interactionManager.setOverlayDirtyCallback(() => {
489
+ this.engine.requestRender(r.Overlay), this.engine.requestRender(r.UI);
458
490
  }), this.interactionManager.attach(), this.syncRenderContext(), this.engine.start();
459
491
  }
460
492
  setData(e) {
@@ -500,8 +532,8 @@ var J = class {
500
532
  this.pluginManager.registerIndicator(e);
501
533
  }
502
534
  static indicators() {
503
- let e = new b();
504
- return H(e), e.getAvailableIndicators();
535
+ let e = new y();
536
+ return k(e), e.getAvailableIndicators();
505
537
  }
506
538
  setPanelPosition(e, t) {
507
539
  this.layoutManager.setPanelPosition(e, t), this.engine.requestRender();
@@ -567,21 +599,21 @@ var J = class {
567
599
  exportVisibleData(e = "csv", t) {
568
600
  let n = this.viewport.getState(), r = this.dataManager.getData(), i = Math.max(0, n.visibleRange.from), a = Math.min(r.length - 1, n.visibleRange.to), o = r.slice(i, a + 1);
569
601
  if (e === "json") {
570
- let e = y.toJSON(o);
571
- y.download(e, t ?? "chart-data.json", "application/json");
602
+ let e = v.toJSON(o);
603
+ v.download(e, t ?? "chart-data.json", "application/json");
572
604
  } else {
573
- let e = y.toCSV(o);
574
- y.download(e, t ?? "chart-data.csv", "text/csv");
605
+ let e = v.toCSV(o);
606
+ v.download(e, t ?? "chart-data.csv", "text/csv");
575
607
  }
576
608
  }
577
609
  exportAllData(e = "csv", t) {
578
610
  let n = this.dataManager.getData();
579
611
  if (e === "json") {
580
- let e = y.toJSON(n);
581
- y.download(e, t ?? "chart-data.json", "application/json");
612
+ let e = v.toJSON(n);
613
+ v.download(e, t ?? "chart-data.json", "application/json");
582
614
  } else {
583
- let e = y.toCSV(n);
584
- y.download(e, t ?? "chart-data.csv", "text/csv");
615
+ let e = v.toCSV(n);
616
+ v.download(e, t ?? "chart-data.csv", "text/csv");
585
617
  }
586
618
  }
587
619
  setAutoSave(e, t = 5e3) {
@@ -632,7 +664,7 @@ var J = class {
632
664
  this.features.trading && this.tradingManager.setConfig(e);
633
665
  }
634
666
  async connect(e) {
635
- this.disconnectStream(), this.streamManager = new F(), this.streamManager.on("snapshot", (e) => {
667
+ this.disconnectStream(), this.streamManager = new T(), this.streamManager.on("snapshot", (e) => {
636
668
  this.setData(e);
637
669
  }), this.streamManager.on("barClose", (e) => {
638
670
  this.dataManager.appendBar(e), this.crosshairHandler.setData(this.dataManager.getData()), this.autoScrollOnNewBar && this.viewport.scrollToEnd(), this.indicatorEngine.recalculateAll(this.dataManager.getData()), this.updateViewportAndRender();
@@ -799,6 +831,15 @@ var J = class {
799
831
  setVolumeVisible(e) {
800
832
  this.volumeRenderer.setVisible(e), this.engine.requestRender(r.Main);
801
833
  }
834
+ setVolumeProfileVisible(e) {
835
+ this.volumeProfile.setVisible(e), this.engine.requestRender(r.Main);
836
+ }
837
+ isVolumeProfileVisible() {
838
+ return this.volumeProfile.isVisible();
839
+ }
840
+ setVolumeProfileConfig(e) {
841
+ e.buckets !== void 0 && this.volumeProfile.setBuckets(e.buckets), e.widthRatio !== void 0 && this.volumeProfile.setWidthRatio(e.widthRatio), e.opacity !== void 0 && this.volumeProfile.setOpacity(e.opacity), e.highlightPoC !== void 0 && this.volumeProfile.setHighlightPoC(e.highlightPoC), this.engine.requestRender(r.Main);
842
+ }
802
843
  setTooltipVisible(e) {
803
844
  e || this.crosshairTooltip.hide();
804
845
  }
@@ -812,13 +853,13 @@ var J = class {
812
853
  this.chartLegend.setStatusText(e), this.engine.requestRender(r.UI);
813
854
  }
814
855
  screenshot(e) {
815
- this.features.screenshot && j.download(this.container, e, this.themeManager.getTheme().background);
856
+ this.features.screenshot && x.download(this.container, e, this.themeManager.getTheme().background);
816
857
  }
817
858
  screenshotDataURL() {
818
- return this.features.screenshot ? j.toDataURL(this.container, this.themeManager.getTheme().background) : null;
859
+ return this.features.screenshot ? x.toDataURL(this.container, this.themeManager.getTheme().background) : null;
819
860
  }
820
861
  async screenshotBlob() {
821
- return this.features.screenshot ? j.toBlob(this.container, this.themeManager.getTheme().background) : null;
862
+ return this.features.screenshot ? x.toBlob(this.container, this.themeManager.getTheme().background) : null;
822
863
  }
823
864
  addAlert(e, t = "crossing", n) {
824
865
  if (!this.features.alerts) return null;
@@ -993,16 +1034,16 @@ var J = class {
993
1034
  this.viewport.resize(e.width, e.height), this.layoutManager.resize(e.width, e.height), this.updateViewportAndRender(n), this.eventBus.emit("resize", e);
994
1035
  }
995
1036
  destroy() {
996
- this.countdownInterval && clearInterval(this.countdownInterval), this.disableAutoSave(), this.disconnectStream(), this.onWindowKeyDown &&= (window.removeEventListener("keydown", this.onWindowKeyDown), null), this.keyboardHandler = null, this.interactionManager.detach(), this.tradingManager.destroy(), this.animator.dispose(), this.crosshairTooltip.destroy(), this.replayManager.dispose(), this.undoRedoManager.clear(), this.engine.destroy(), this.eventBus.destroy(), this.container.innerHTML = "";
1037
+ this.countdownInterval && clearInterval(this.countdownInterval), this.disableAutoSave(), this.disconnectStream(), this.onWindowKeyDown &&= (window.removeEventListener("keydown", this.onWindowKeyDown), null), this.keyboardHandler = null, this.interactionManager.detach(), this.tradingManager.destroy(), this.animator.dispose(), this.crosshairTooltip.destroy(), this.pinnedTooltip.destroy(), this.replayManager.dispose(), this.undoRedoManager.clear(), this.engine.destroy(), this.eventBus.destroy(), this.container.innerHTML = "";
997
1038
  }
998
1039
  createChartRenderer(e) {
999
- return we(e);
1040
+ return Ve(e);
1000
1041
  }
1001
1042
  getDisplayData() {
1002
1043
  if (this.displayDataCache) return this.displayDataCache;
1003
1044
  let e = this.dataManager.getData();
1004
1045
  if (e.length === 0) return e;
1005
- let t = Te(this.options.chartType, e);
1046
+ let t = He(this.options.chartType, e);
1006
1047
  return this.displayDataCache = t, t;
1007
1048
  }
1008
1049
  scheduleRender() {
@@ -1039,7 +1080,7 @@ var J = class {
1039
1080
  buildPanelRenderInfos() {
1040
1081
  if (this.panelInfoCache) return this.panelInfoCache;
1041
1082
  let e = this.getResolvedLayout(), t = this.viewport.getState(), { from: n, to: r } = t.visibleRange, i = e.panels.map((e) => {
1042
- let i = Ee(this.indicatorEngine.getOutput(e.config.id), n, r), a = {
1083
+ let i = Ue(this.indicatorEngine.getOutput(e.config.id), n, r), a = {
1043
1084
  x: e.rect.x,
1044
1085
  y: e.rect.y + 20,
1045
1086
  width: e.rect.width,
@@ -1058,6 +1099,7 @@ var J = class {
1058
1099
  return this.panelInfoCache = i, i;
1059
1100
  }
1060
1101
  syncRenderContext() {
1102
+ this.pinnedTooltip.isPinned() && this.pinnedTooltip.reposition(this.viewport.getState(), null, null, this.themeManager.getTheme());
1061
1103
  let e = this.getResolvedLayout(), t = this.features.indicators ? this.buildPanelRenderInfos() : [], n = e.panels.filter((e) => e.config.position === "bottom").reduce((e, t) => e + t.rect.height, 0), r = e.mainChartRect.y + e.mainChartRect.height + n, i = this.getDisplayData();
1062
1104
  this.engine.setRenderContext({
1063
1105
  chartRenderer: this.chartRenderer,
@@ -1071,11 +1113,13 @@ var J = class {
1071
1113
  currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine,
1072
1114
  chartLegend: this.features.legend ? this.chartLegend : null,
1073
1115
  volumeRenderer: this.features.volume ? this.volumeRenderer : null,
1116
+ volumeProfile: this.volumeProfile,
1074
1117
  watermark: this.features.watermark ? this.watermark : null,
1075
1118
  barCountdown: this.barCountdown,
1076
1119
  sessionBreaks: this.sessionBreaks,
1077
1120
  compareRenderer: this.compareRenderer,
1078
1121
  alertManager: this.features.alerts ? this.alertManager : null,
1122
+ measureOverlay: this.measureOverlay,
1079
1123
  signalMarkerManager: this.signalMarkerManager,
1080
1124
  tradeZoneManager: this.tradeZoneManager,
1081
1125
  panels: t,
@@ -1102,8 +1146,240 @@ var J = class {
1102
1146
  } : void 0
1103
1147
  } : null;
1104
1148
  }
1149
+ }, V = [
1150
+ "time",
1151
+ "timestamp",
1152
+ "date",
1153
+ "datetime",
1154
+ "t"
1155
+ ], H = ["open", "o"], U = ["high", "h"], W = ["low", "l"], G = ["close", "c"], K = [
1156
+ "volume",
1157
+ "vol",
1158
+ "v"
1159
+ ];
1160
+ function q(e) {
1161
+ let t = e.trim();
1162
+ return t ? t[0] === "[" || t[0] === "{" ? Ke(t) : qe(t) : {
1163
+ data: [],
1164
+ rowCount: 0,
1165
+ skipped: 0
1166
+ };
1167
+ }
1168
+ function Ke(e) {
1169
+ let t;
1170
+ try {
1171
+ t = JSON.parse(e);
1172
+ } catch (e) {
1173
+ throw Error(`Invalid JSON: ${e.message}`);
1174
+ }
1175
+ if (!Array.isArray(t)) throw Error("Expected a JSON array of OHLCV rows");
1176
+ let n = [], r = 0;
1177
+ for (let e of t) {
1178
+ let t = Array.isArray(e) ? Xe(e) : Ye(e);
1179
+ t ? n.push(t) : r++;
1180
+ }
1181
+ return Q(n, t.length, r);
1182
+ }
1183
+ function qe(e) {
1184
+ let t = e.split(/\r?\n/).filter((e) => e.trim().length > 0);
1185
+ if (t.length === 0) return {
1186
+ data: [],
1187
+ rowCount: 0,
1188
+ skipped: 0
1189
+ };
1190
+ let n = Je(t[0]), r = J(t[0], n).map((e) => e.trim().toLowerCase()), i = r.some((e) => isNaN(Number(e)) && e.length > 0), a = i ? Y(r) : {
1191
+ time: 0,
1192
+ open: 1,
1193
+ high: 2,
1194
+ low: 3,
1195
+ close: 4,
1196
+ volume: 5
1197
+ };
1198
+ if (a.time < 0 || a.open < 0 || a.high < 0 || a.low < 0 || a.close < 0) throw Error("CSV is missing required column(s): time, open, high, low, close");
1199
+ let o = [], s = 0;
1200
+ for (let e = +!!i; e < t.length; e++) {
1201
+ let r = J(t[e], n), i = Z(r[a.time]), c = X(r[a.open]), l = X(r[a.high]), u = X(r[a.low]), d = X(r[a.close]), f = a.volume >= 0 ? Number(r[a.volume]) : 0;
1202
+ if (i === null || ![
1203
+ c,
1204
+ l,
1205
+ u,
1206
+ d
1207
+ ].every(Number.isFinite)) {
1208
+ s++;
1209
+ continue;
1210
+ }
1211
+ o.push({
1212
+ time: i,
1213
+ open: c,
1214
+ high: l,
1215
+ low: u,
1216
+ close: d,
1217
+ volume: Number.isFinite(f) ? f : 0
1218
+ });
1219
+ }
1220
+ return Q(o, t.length - +!!i, s);
1221
+ }
1222
+ function Je(e) {
1223
+ let t = {
1224
+ ",": 0,
1225
+ ";": 0,
1226
+ " ": 0,
1227
+ "|": 0
1228
+ };
1229
+ for (let n of e) n in t && t[n]++;
1230
+ let n = ",", r = 0;
1231
+ for (let [e, i] of Object.entries(t)) i > r && (n = e, r = i);
1232
+ return n;
1233
+ }
1234
+ function J(e, t) {
1235
+ let n = [], r = "", i = !1;
1236
+ for (let a = 0; a < e.length; a++) {
1237
+ let o = e[a];
1238
+ o === "\"" ? i && e[a + 1] === "\"" ? (r += "\"", a++) : i = !i : o === t && !i ? (n.push(r), r = "") : r += o;
1239
+ }
1240
+ return n.push(r), n;
1241
+ }
1242
+ function Y(e) {
1243
+ let t = (t) => e.findIndex((e) => t.includes(e));
1244
+ return {
1245
+ time: t(V),
1246
+ open: t(H),
1247
+ high: t(U),
1248
+ low: t(W),
1249
+ close: t(G),
1250
+ volume: t(K)
1251
+ };
1252
+ }
1253
+ function Ye(e) {
1254
+ let t = (t) => {
1255
+ for (let n of t) {
1256
+ if (e[n] !== void 0) return e[n];
1257
+ let t = n.toUpperCase();
1258
+ if (e[t] !== void 0) return e[t];
1259
+ }
1260
+ }, n = Z(String(t(V) ?? "")), r = Number(t(H)), i = Number(t(U)), a = Number(t(W)), o = Number(t(G)), s = Number(t(K) ?? 0);
1261
+ return n === null || ![
1262
+ r,
1263
+ i,
1264
+ a,
1265
+ o
1266
+ ].every(Number.isFinite) ? null : {
1267
+ time: n,
1268
+ open: r,
1269
+ high: i,
1270
+ low: a,
1271
+ close: o,
1272
+ volume: Number.isFinite(s) ? s : 0
1273
+ };
1274
+ }
1275
+ function Xe(e) {
1276
+ if (e.length < 5) return null;
1277
+ let t = Z(String(e[0])), n = Number(e[1]), r = Number(e[2]), i = Number(e[3]), a = Number(e[4]), o = e.length >= 6 ? Number(e[5]) : 0;
1278
+ return t === null || ![
1279
+ n,
1280
+ r,
1281
+ i,
1282
+ a
1283
+ ].every(Number.isFinite) ? null : {
1284
+ time: t,
1285
+ open: n,
1286
+ high: r,
1287
+ low: i,
1288
+ close: a,
1289
+ volume: Number.isFinite(o) ? o : 0
1290
+ };
1291
+ }
1292
+ function X(e) {
1293
+ return e === void 0 || e.trim() === "" ? NaN : Number(e);
1294
+ }
1295
+ function Z(e) {
1296
+ let t = e.trim();
1297
+ if (!t) return null;
1298
+ let n = Number(t);
1299
+ if (Number.isFinite(n) && n > 0) return n < 0xe8d4a51000 ? n * 1e3 : n;
1300
+ let r = Date.parse(t);
1301
+ return Number.isFinite(r) ? r : null;
1302
+ }
1303
+ function Q(e, t, n) {
1304
+ e.sort((e, t) => e.time - t.time);
1305
+ let r = [];
1306
+ for (let t of e) r.length > 0 && r[r.length - 1].time === t.time ? r[r.length - 1] = t : r.push(t);
1307
+ return {
1308
+ data: r,
1309
+ rowCount: t,
1310
+ skipped: n
1311
+ };
1312
+ }
1313
+ //#endregion
1314
+ //#region src/io/DragDropImporter.ts
1315
+ var Ze = class {
1316
+ host;
1317
+ overlay = null;
1318
+ callbacks;
1319
+ bound;
1320
+ depth = 0;
1321
+ constructor(e, t) {
1322
+ this.host = e, this.callbacks = t, this.bound = {
1323
+ dragenter: (e) => this.onDragEnter(e),
1324
+ dragover: (e) => this.onDragOver(e),
1325
+ dragleave: (e) => this.onDragLeave(e),
1326
+ drop: (e) => this.onDrop(e)
1327
+ };
1328
+ }
1329
+ attach() {
1330
+ this.host.addEventListener("dragenter", this.bound.dragenter), this.host.addEventListener("dragover", this.bound.dragover), this.host.addEventListener("dragleave", this.bound.dragleave), this.host.addEventListener("drop", this.bound.drop);
1331
+ }
1332
+ detach() {
1333
+ this.host.removeEventListener("dragenter", this.bound.dragenter), this.host.removeEventListener("dragover", this.bound.dragover), this.host.removeEventListener("dragleave", this.bound.dragleave), this.host.removeEventListener("drop", this.bound.drop), this.hideOverlay();
1334
+ }
1335
+ onDragEnter(e) {
1336
+ $(e) && (e.preventDefault(), this.depth++, this.showOverlay());
1337
+ }
1338
+ onDragOver(e) {
1339
+ $(e) && (e.preventDefault(), e.dataTransfer && (e.dataTransfer.dropEffect = "copy"));
1340
+ }
1341
+ onDragLeave(e) {
1342
+ $(e) && (this.depth = Math.max(0, this.depth - 1), this.depth === 0 && this.hideOverlay());
1343
+ }
1344
+ async onDrop(e) {
1345
+ e.preventDefault(), this.depth = 0, this.hideOverlay();
1346
+ let t = e.dataTransfer?.files?.[0];
1347
+ if (t) try {
1348
+ let e = q(await t.text());
1349
+ if (e.data.length === 0) throw Error(`No valid OHLCV rows found in "${t.name}"`);
1350
+ this.callbacks.onData(e.data, e, t);
1351
+ } catch (e) {
1352
+ this.callbacks.onError?.(e, t);
1353
+ }
1354
+ }
1355
+ showOverlay() {
1356
+ this.overlay || (this.overlay = document.createElement("div"), Object.assign(this.overlay.style, {
1357
+ position: "absolute",
1358
+ inset: "8px",
1359
+ zIndex: "90",
1360
+ pointerEvents: "none",
1361
+ borderRadius: "10px",
1362
+ border: "2px dashed var(--tcw-accent, #4f88ff)",
1363
+ background: "rgba(79, 136, 255, 0.06)",
1364
+ display: "flex",
1365
+ alignItems: "center",
1366
+ justifyContent: "center",
1367
+ color: "var(--tcw-accent, #4f88ff)",
1368
+ fontSize: "14px",
1369
+ fontWeight: "600",
1370
+ letterSpacing: "-0.005em",
1371
+ fontFamily: "inherit",
1372
+ backdropFilter: "blur(2px)"
1373
+ }), this.overlay.textContent = "Drop CSV or JSON to load chart data", getComputedStyle(this.host).position === "static" && (this.host.style.position = "relative"), this.host.appendChild(this.overlay));
1374
+ }
1375
+ hideOverlay() {
1376
+ this.overlay?.remove(), this.overlay = null;
1377
+ }
1105
1378
  };
1379
+ function $(e) {
1380
+ return e.dataTransfer?.types?.includes("Files") ?? !1;
1381
+ }
1106
1382
  //#endregion
1107
- export { J as a, Y as i, $ as n, Q as r, Oe as t };
1383
+ export { z as a, B as i, q as n, I as o, Ge as r, F as s, Ze as t };
1108
1384
 
1109
- //# sourceMappingURL=Chart-Cn_TSMO7.js.map
1385
+ //# sourceMappingURL=DragDropImporter-6QOjnfSj.js.map