@pipsend/charts 2.3.13 → 2.3.15
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/dist/pipsend-charts.development.mjs +297 -86
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +297 -86
- package/dist/pipsend-charts.standalone.development.mjs +297 -86
- package/dist/pipsend-charts.standalone.production.js +2 -2
- package/dist/pipsend-charts.standalone.production.mjs +2 -2
- package/dist/typings.d.ts +41 -3
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v2.3.
|
|
3
|
+
* Pipsend Charts v2.3.15
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -14684,6 +14684,9 @@ function calculateShapeHeight(barSpacing) {
|
|
|
14684
14684
|
function shapeMargin(barSpacing) {
|
|
14685
14685
|
return Math.max(size(barSpacing, 0.1), 3 /* Constants.MinShapeMargin */);
|
|
14686
14686
|
}
|
|
14687
|
+
function barGap(barSpacing) {
|
|
14688
|
+
return Math.max(shapeMargin(barSpacing), 10 /* Constants.MinBarGap */);
|
|
14689
|
+
}
|
|
14687
14690
|
function calculateAdjustedMargin(margin, hasSide, hasInBar) {
|
|
14688
14691
|
if (hasSide) {
|
|
14689
14692
|
return margin;
|
|
@@ -15310,17 +15313,18 @@ class SeriesMarkersPaneView {
|
|
|
15310
15313
|
}
|
|
15311
15314
|
let prevTimeIndex = NaN;
|
|
15312
15315
|
const shapeMargin$1 = shapeMargin(timeScale.options().barSpacing);
|
|
15316
|
+
const barGap$1 = barGap(timeScale.options().barSpacing);
|
|
15313
15317
|
const offsets = {
|
|
15314
|
-
_internal_aboveBar:
|
|
15315
|
-
_internal_belowBar:
|
|
15318
|
+
_internal_aboveBar: barGap$1,
|
|
15319
|
+
_internal_belowBar: barGap$1,
|
|
15316
15320
|
};
|
|
15317
15321
|
this._private__data._internal_visibleRange = visibleTimedValues(this._private__data._internal_items, visibleBarsRange, true);
|
|
15318
15322
|
for (let index = this._private__data._internal_visibleRange.from; index < this._private__data._internal_visibleRange.to; index++) {
|
|
15319
15323
|
const marker = seriesMarkers[index];
|
|
15320
15324
|
if (marker.time !== prevTimeIndex) {
|
|
15321
15325
|
// new bar, reset stack counter
|
|
15322
|
-
offsets._internal_aboveBar =
|
|
15323
|
-
offsets._internal_belowBar =
|
|
15326
|
+
offsets._internal_aboveBar = barGap$1;
|
|
15327
|
+
offsets._internal_belowBar = barGap$1;
|
|
15324
15328
|
prevTimeIndex = marker.time;
|
|
15325
15329
|
}
|
|
15326
15330
|
const rendererItem = this._private__data._internal_items[index];
|
|
@@ -15437,7 +15441,7 @@ class SeriesMarkersPrimitive {
|
|
|
15437
15441
|
this._private__cachedBarSpacing = barSpacing;
|
|
15438
15442
|
if (this._private__markers.length > 0) {
|
|
15439
15443
|
const shapeMargin$1 = shapeMargin(barSpacing);
|
|
15440
|
-
const marginValue = calculateShapeHeight(barSpacing) * 1.5 + shapeMargin$1
|
|
15444
|
+
const marginValue = calculateShapeHeight(barSpacing) * 1.5 + shapeMargin$1 + barGap(barSpacing);
|
|
15441
15445
|
const positions = this._private__getMarkerPositions();
|
|
15442
15446
|
this._private__autoScaleMargins = {
|
|
15443
15447
|
above: calculateAdjustedMargin(marginValue, positions.aboveBar, positions.inBar),
|
|
@@ -17940,10 +17944,13 @@ function applyHeikinAshi(series, chart, options = {}) {
|
|
|
17940
17944
|
const blankSource = (blank) => {
|
|
17941
17945
|
if (blank && restoreSourcePaint === null) {
|
|
17942
17946
|
restoreSourcePaint = hideSeriesPaint(series);
|
|
17947
|
+
// Under the blank source, so what hangs off it draws over the candles.
|
|
17948
|
+
haSeries.setSeriesOrder(series.seriesOrder());
|
|
17943
17949
|
}
|
|
17944
17950
|
else if (!blank && restoreSourcePaint !== null) {
|
|
17945
17951
|
restoreSourcePaint();
|
|
17946
17952
|
restoreSourcePaint = null;
|
|
17953
|
+
haSeries.setSeriesOrder(series.seriesOrder() + 1);
|
|
17947
17954
|
}
|
|
17948
17955
|
};
|
|
17949
17956
|
const runtime = bindIndicator({
|
|
@@ -17972,8 +17979,9 @@ function applyHeikinAshi(series, chart, options = {}) {
|
|
|
17972
17979
|
blankSource(current.hideSource === true);
|
|
17973
17980
|
},
|
|
17974
17981
|
});
|
|
17975
|
-
|
|
17976
|
-
|
|
17982
|
+
// Returned as a literal: a local annotation would let the property renamer mangle `series`.
|
|
17983
|
+
return {
|
|
17984
|
+
series: haSeries,
|
|
17977
17985
|
options: runtime.options,
|
|
17978
17986
|
applyOptions: runtime.applyOptions,
|
|
17979
17987
|
recalculate: runtime.recalculate,
|
|
@@ -17989,7 +17997,6 @@ function applyHeikinAshi(series, chart, options = {}) {
|
|
|
17989
17997
|
}
|
|
17990
17998
|
},
|
|
17991
17999
|
};
|
|
17992
|
-
return handle;
|
|
17993
18000
|
}
|
|
17994
18001
|
|
|
17995
18002
|
/**
|
|
@@ -21641,6 +21648,13 @@ class DrawingToolBase {
|
|
|
21641
21648
|
series() {
|
|
21642
21649
|
return this._series;
|
|
21643
21650
|
}
|
|
21651
|
+
/**
|
|
21652
|
+
* Box the selection toolbar anchors to, in pane pixels. Null falls back to
|
|
21653
|
+
* the serialized points, which cannot place a line across the whole pane.
|
|
21654
|
+
*/
|
|
21655
|
+
selectionBox() {
|
|
21656
|
+
return null;
|
|
21657
|
+
}
|
|
21644
21658
|
getState() {
|
|
21645
21659
|
return this._state;
|
|
21646
21660
|
}
|
|
@@ -22317,6 +22331,53 @@ function createTrendLineTool(context, options) {
|
|
|
22317
22331
|
return new TrendLineTool(context, options);
|
|
22318
22332
|
}
|
|
22319
22333
|
|
|
22334
|
+
const END_HANDLE_MARGIN = 10;
|
|
22335
|
+
/**
|
|
22336
|
+
* Hands the next `clicks` clicks on the chart to `onClick`, past the last bar
|
|
22337
|
+
* too. A press that grabbed another drawing does not count.
|
|
22338
|
+
*/
|
|
22339
|
+
function placeByClicks(chart, series, clicks, onClick) {
|
|
22340
|
+
let placed = 0;
|
|
22341
|
+
let handler = null;
|
|
22342
|
+
const stop = () => {
|
|
22343
|
+
if (handler !== null) {
|
|
22344
|
+
chart.unsubscribeClick(handler);
|
|
22345
|
+
handler = null;
|
|
22346
|
+
}
|
|
22347
|
+
};
|
|
22348
|
+
handler = (param) => {
|
|
22349
|
+
if (!param.point || consumeInputClaim(chart)) {
|
|
22350
|
+
return;
|
|
22351
|
+
}
|
|
22352
|
+
const price = series.coordinateToPrice(param.point.y);
|
|
22353
|
+
const time = timeFromCoordinate(chart, series, param.point.x);
|
|
22354
|
+
if (price === null || time === null) {
|
|
22355
|
+
return;
|
|
22356
|
+
}
|
|
22357
|
+
placed++;
|
|
22358
|
+
if (placed >= clicks) {
|
|
22359
|
+
stop();
|
|
22360
|
+
}
|
|
22361
|
+
onClick({ _internal_time: time, _internal_price: price, _internal_x: param.point.x, _internal_y: param.point.y }, placed - 1);
|
|
22362
|
+
};
|
|
22363
|
+
chart.subscribeClick(handler);
|
|
22364
|
+
return {
|
|
22365
|
+
_internal_pending: () => handler !== null,
|
|
22366
|
+
_internal_stop: stop,
|
|
22367
|
+
};
|
|
22368
|
+
}
|
|
22369
|
+
/** A fifth of the pane, and never less than a bar. */
|
|
22370
|
+
function defaultWidth(chart) {
|
|
22371
|
+
const timeScale = chart.timeScale();
|
|
22372
|
+
return Math.max(timeScale.width() / 5, timeScale.options().barSpacing);
|
|
22373
|
+
}
|
|
22374
|
+
/** Kept inside the pane: past it, the handles on the end hide under the price axis. */
|
|
22375
|
+
function placedEndX(chart, x) {
|
|
22376
|
+
const timeScale = chart.timeScale();
|
|
22377
|
+
const onScreen = Math.min(x + defaultWidth(chart), timeScale.width() - END_HANDLE_MARGIN);
|
|
22378
|
+
return Math.max(onScreen, x + timeScale.options().barSpacing);
|
|
22379
|
+
}
|
|
22380
|
+
|
|
22320
22381
|
class HorizontalLinePaneRenderer {
|
|
22321
22382
|
constructor(tool) {
|
|
22322
22383
|
this._private__tool = tool;
|
|
@@ -22357,6 +22418,7 @@ class HorizontalLineTool extends DrawingToolBase {
|
|
|
22357
22418
|
this._private__isDragging = false;
|
|
22358
22419
|
this._private__grab = null;
|
|
22359
22420
|
this._private__moveStartPrice = 0;
|
|
22421
|
+
this._private__placement = null;
|
|
22360
22422
|
this._private__hLineOptions = {
|
|
22361
22423
|
lineColor: '#2962ff',
|
|
22362
22424
|
lineWidth: 2,
|
|
@@ -22369,6 +22431,26 @@ class HorizontalLineTool extends DrawingToolBase {
|
|
|
22369
22431
|
};
|
|
22370
22432
|
this._registerOptions(this._private__hLineOptions);
|
|
22371
22433
|
this._private__createPrimitive();
|
|
22434
|
+
if (this._private__hLineOptions.interactive) {
|
|
22435
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
22436
|
+
}
|
|
22437
|
+
}
|
|
22438
|
+
_private__placeAt(point) {
|
|
22439
|
+
this._private__hLineOptions.price = point._internal_price;
|
|
22440
|
+
if (this._private__hLineOptions.startTime !== undefined) {
|
|
22441
|
+
this._private__hLineOptions.startTime = point._internal_time;
|
|
22442
|
+
}
|
|
22443
|
+
this._private__requestUpdate();
|
|
22444
|
+
}
|
|
22445
|
+
isComplete() {
|
|
22446
|
+
return !this._private__placement?._internal_pending();
|
|
22447
|
+
}
|
|
22448
|
+
selectionBox() {
|
|
22449
|
+
const y = this._private__hLineOptions.price === undefined ? null : this._series.priceToCoordinate(this._private__hLineOptions.price);
|
|
22450
|
+
if (y === null) {
|
|
22451
|
+
return null;
|
|
22452
|
+
}
|
|
22453
|
+
return { left: this._private__startX(), right: this._chart.timeScale().width(), top: y, bottom: y };
|
|
22372
22454
|
}
|
|
22373
22455
|
_private__createPrimitive() {
|
|
22374
22456
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -22406,7 +22488,7 @@ class HorizontalLineTool extends DrawingToolBase {
|
|
|
22406
22488
|
return coordinateFromTime(this._chart, this._series, this._private__hLineOptions.startTime) ?? 0;
|
|
22407
22489
|
}
|
|
22408
22490
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
22409
|
-
if (this._private__hLineOptions.price === undefined)
|
|
22491
|
+
if (!this.isComplete() || this._private__hLineOptions.price === undefined)
|
|
22410
22492
|
return;
|
|
22411
22493
|
const y = (this._series.priceToCoordinate(this._private__hLineOptions.price) ?? 0) * verticalPixelRatio;
|
|
22412
22494
|
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
@@ -22500,7 +22582,7 @@ class HorizontalLineTool extends DrawingToolBase {
|
|
|
22500
22582
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
22501
22583
|
}
|
|
22502
22584
|
hitTest(x, y) {
|
|
22503
|
-
if (this._private__hLineOptions.price === undefined) {
|
|
22585
|
+
if (!this.isComplete() || this._private__hLineOptions.price === undefined) {
|
|
22504
22586
|
return false;
|
|
22505
22587
|
}
|
|
22506
22588
|
const lineY = this._series.priceToCoordinate(this._private__hLineOptions.price) ?? 0;
|
|
@@ -22575,6 +22657,7 @@ class HorizontalLineTool extends DrawingToolBase {
|
|
|
22575
22657
|
this._private__requestUpdate();
|
|
22576
22658
|
}
|
|
22577
22659
|
remove() {
|
|
22660
|
+
this._private__placement?._internal_stop();
|
|
22578
22661
|
if (this._private__primitive) {
|
|
22579
22662
|
this._series.detachPrimitive(this._private__primitive);
|
|
22580
22663
|
this._private__primitive = null;
|
|
@@ -22634,6 +22717,7 @@ class CrossLineTool extends DrawingToolBase {
|
|
|
22634
22717
|
this._private__grab = null;
|
|
22635
22718
|
this._private__moveStartTime = 0;
|
|
22636
22719
|
this._private__moveStartPrice = 0;
|
|
22720
|
+
this._private__placement = null;
|
|
22637
22721
|
this._private__crossOptions = {
|
|
22638
22722
|
lineColor: '#787b86',
|
|
22639
22723
|
lineWidth: 1,
|
|
@@ -22643,6 +22727,16 @@ class CrossLineTool extends DrawingToolBase {
|
|
|
22643
22727
|
};
|
|
22644
22728
|
this._registerOptions(this._private__crossOptions);
|
|
22645
22729
|
this._private__createPrimitive();
|
|
22730
|
+
if (this._private__crossOptions.interactive) {
|
|
22731
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
22732
|
+
this._private__crossOptions.time = point._internal_time;
|
|
22733
|
+
this._private__crossOptions.price = point._internal_price;
|
|
22734
|
+
this._private__requestUpdate();
|
|
22735
|
+
});
|
|
22736
|
+
}
|
|
22737
|
+
}
|
|
22738
|
+
isComplete() {
|
|
22739
|
+
return !this._private__placement?._internal_pending();
|
|
22646
22740
|
}
|
|
22647
22741
|
_private__createPrimitive() {
|
|
22648
22742
|
this._private__paneView = new CrossLinePaneView(this);
|
|
@@ -22670,7 +22764,7 @@ class CrossLineTool extends DrawingToolBase {
|
|
|
22670
22764
|
this._private__requestUpdate();
|
|
22671
22765
|
}
|
|
22672
22766
|
_private__coordinates() {
|
|
22673
|
-
if (this._private__crossOptions.time === undefined || this._private__crossOptions.price === undefined) {
|
|
22767
|
+
if (!this.isComplete() || this._private__crossOptions.time === undefined || this._private__crossOptions.price === undefined) {
|
|
22674
22768
|
return null;
|
|
22675
22769
|
}
|
|
22676
22770
|
const x = coordinateFromTime(this._chart, this._series, this._private__crossOptions.time);
|
|
@@ -22793,6 +22887,7 @@ class CrossLineTool extends DrawingToolBase {
|
|
|
22793
22887
|
return this._private__isHovered;
|
|
22794
22888
|
}
|
|
22795
22889
|
remove() {
|
|
22890
|
+
this._private__placement?._internal_stop();
|
|
22796
22891
|
if (this._private__primitive) {
|
|
22797
22892
|
try {
|
|
22798
22893
|
this._series.detachPrimitive(this._private__primitive);
|
|
@@ -24215,6 +24310,7 @@ class VerticalLineTool extends DrawingToolBase {
|
|
|
24215
24310
|
this._private__isDragging = false;
|
|
24216
24311
|
this._private__grab = null;
|
|
24217
24312
|
this._private__moveStartTime = 0;
|
|
24313
|
+
this._private__placement = null;
|
|
24218
24314
|
this._private__vLineOptions = {
|
|
24219
24315
|
lineColor: '#787b86',
|
|
24220
24316
|
lineWidth: 1,
|
|
@@ -24226,6 +24322,29 @@ class VerticalLineTool extends DrawingToolBase {
|
|
|
24226
24322
|
};
|
|
24227
24323
|
this._registerOptions(this._private__vLineOptions);
|
|
24228
24324
|
this._private__createPrimitive();
|
|
24325
|
+
if (this._private__vLineOptions.interactive) {
|
|
24326
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
24327
|
+
this._private__vLineOptions.time = point._internal_time;
|
|
24328
|
+
this._private__requestUpdate();
|
|
24329
|
+
});
|
|
24330
|
+
}
|
|
24331
|
+
}
|
|
24332
|
+
isComplete() {
|
|
24333
|
+
return !this._private__placement?._internal_pending();
|
|
24334
|
+
}
|
|
24335
|
+
selectionBox() {
|
|
24336
|
+
const x = coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time);
|
|
24337
|
+
if (x === null) {
|
|
24338
|
+
return null;
|
|
24339
|
+
}
|
|
24340
|
+
let middle;
|
|
24341
|
+
try {
|
|
24342
|
+
middle = this._series.getPane().getHeight() / 2;
|
|
24343
|
+
}
|
|
24344
|
+
catch (error) {
|
|
24345
|
+
return null;
|
|
24346
|
+
}
|
|
24347
|
+
return { left: x, right: x, top: middle, bottom: middle };
|
|
24229
24348
|
}
|
|
24230
24349
|
_private__createPrimitive() {
|
|
24231
24350
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -24256,7 +24375,7 @@ class VerticalLineTool extends DrawingToolBase {
|
|
|
24256
24375
|
return new VerticalLinePaneView(this);
|
|
24257
24376
|
}
|
|
24258
24377
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
24259
|
-
if (this._private__vLineOptions.time === undefined)
|
|
24378
|
+
if (!this.isComplete() || this._private__vLineOptions.time === undefined)
|
|
24260
24379
|
return;
|
|
24261
24380
|
const x = (coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time) ?? 0) * horizontalPixelRatio;
|
|
24262
24381
|
const chartHeight = this._chart.chartElement().clientHeight * verticalPixelRatio;
|
|
@@ -24343,7 +24462,7 @@ class VerticalLineTool extends DrawingToolBase {
|
|
|
24343
24462
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
24344
24463
|
}
|
|
24345
24464
|
hitTest(x, y) {
|
|
24346
|
-
if (this._private__vLineOptions.time === undefined) {
|
|
24465
|
+
if (!this.isComplete() || this._private__vLineOptions.time === undefined) {
|
|
24347
24466
|
return false;
|
|
24348
24467
|
}
|
|
24349
24468
|
const lineX = coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time) ?? 0;
|
|
@@ -24413,6 +24532,7 @@ class VerticalLineTool extends DrawingToolBase {
|
|
|
24413
24532
|
this._private__requestUpdate();
|
|
24414
24533
|
}
|
|
24415
24534
|
remove() {
|
|
24535
|
+
this._private__placement?._internal_stop();
|
|
24416
24536
|
if (this._private__primitive) {
|
|
24417
24537
|
this._series.detachPrimitive(this._private__primitive);
|
|
24418
24538
|
this._private__primitive = null;
|
|
@@ -25134,6 +25254,7 @@ class FibonacciExtensionTool extends DrawingToolBase {
|
|
|
25134
25254
|
this._private__isHovered = false;
|
|
25135
25255
|
this._private__isDragging = false;
|
|
25136
25256
|
this._private__dragTarget = null;
|
|
25257
|
+
this._private__placement = null;
|
|
25137
25258
|
this._private__fibOptions = {
|
|
25138
25259
|
levels: [
|
|
25139
25260
|
{ level: 0, color: '#787B86', label: '0%' },
|
|
@@ -25149,6 +25270,20 @@ class FibonacciExtensionTool extends DrawingToolBase {
|
|
|
25149
25270
|
...options,
|
|
25150
25271
|
};
|
|
25151
25272
|
this._private__createPrimitive();
|
|
25273
|
+
if (this._private__fibOptions.interactive) {
|
|
25274
|
+
this._private__placement = placeByClicks(this._chart, this._series, 3, (point, index) => {
|
|
25275
|
+
const placed = { time: point._internal_time, price: point._internal_price };
|
|
25276
|
+
if (index === 0) {
|
|
25277
|
+
this.setPoint1(placed);
|
|
25278
|
+
}
|
|
25279
|
+
else if (index === 1) {
|
|
25280
|
+
this.setPoint2(placed);
|
|
25281
|
+
}
|
|
25282
|
+
else {
|
|
25283
|
+
this.setPoint3(placed);
|
|
25284
|
+
}
|
|
25285
|
+
});
|
|
25286
|
+
}
|
|
25152
25287
|
}
|
|
25153
25288
|
_private__createPrimitive() {
|
|
25154
25289
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -25206,7 +25341,7 @@ class FibonacciExtensionTool extends DrawingToolBase {
|
|
|
25206
25341
|
this._private__requestUpdate();
|
|
25207
25342
|
}
|
|
25208
25343
|
isComplete() {
|
|
25209
|
-
return !!(this._private__fibOptions.point1 && this._private__fibOptions.point2 && this._private__fibOptions.point3);
|
|
25344
|
+
return !this._private__placement?._internal_pending() && !!(this._private__fibOptions.point1 && this._private__fibOptions.point2 && this._private__fibOptions.point3);
|
|
25210
25345
|
}
|
|
25211
25346
|
setColor(color) {
|
|
25212
25347
|
this._private__fibOptions.lineColor = color;
|
|
@@ -25501,6 +25636,7 @@ class FibonacciExtensionTool extends DrawingToolBase {
|
|
|
25501
25636
|
this._private__requestUpdate();
|
|
25502
25637
|
}
|
|
25503
25638
|
remove() {
|
|
25639
|
+
this._private__placement?._internal_stop();
|
|
25504
25640
|
if (this._private__primitive) {
|
|
25505
25641
|
this._series.detachPrimitive(this._private__primitive);
|
|
25506
25642
|
this._private__primitive = null;
|
|
@@ -28066,6 +28202,7 @@ class TextTool extends DrawingToolBase {
|
|
|
28066
28202
|
this._private__moveStart = null;
|
|
28067
28203
|
this._private__isEditing = false;
|
|
28068
28204
|
this._private__clickOutsideHandler = null;
|
|
28205
|
+
this._private__placement = null;
|
|
28069
28206
|
this._private__textOptions = {
|
|
28070
28207
|
text: 'Double-click to edit',
|
|
28071
28208
|
fontSize: 14,
|
|
@@ -28086,6 +28223,14 @@ class TextTool extends DrawingToolBase {
|
|
|
28086
28223
|
this._registerOptions(this._private__textOptions);
|
|
28087
28224
|
this._private__createPrimitive();
|
|
28088
28225
|
this._private__setupClickOutsideHandler();
|
|
28226
|
+
if (this._private__textOptions.interactive) {
|
|
28227
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
28228
|
+
this.setPosition(point._internal_time, point._internal_price);
|
|
28229
|
+
if (this._private__textOptions.onComplete) {
|
|
28230
|
+
this._private__textOptions.onComplete();
|
|
28231
|
+
}
|
|
28232
|
+
});
|
|
28233
|
+
}
|
|
28089
28234
|
}
|
|
28090
28235
|
_private__setupClickOutsideHandler() {
|
|
28091
28236
|
// Set up click handler to finish editing when clicking outside
|
|
@@ -28171,7 +28316,7 @@ class TextTool extends DrawingToolBase {
|
|
|
28171
28316
|
this._private__requestUpdate();
|
|
28172
28317
|
}
|
|
28173
28318
|
isComplete() {
|
|
28174
|
-
return !!(this._private__textOptions.time && this._private__textOptions.price !== undefined);
|
|
28319
|
+
return !this._private__placement?._internal_pending() && !!(this._private__textOptions.time && this._private__textOptions.price !== undefined);
|
|
28175
28320
|
}
|
|
28176
28321
|
setColor(color) {
|
|
28177
28322
|
this._private__textOptions.textColor = color;
|
|
@@ -28454,6 +28599,7 @@ class TextTool extends DrawingToolBase {
|
|
|
28454
28599
|
};
|
|
28455
28600
|
}
|
|
28456
28601
|
remove() {
|
|
28602
|
+
this._private__placement?._internal_stop();
|
|
28457
28603
|
// Clean up click handler
|
|
28458
28604
|
if (this._private__clickOutsideHandler) {
|
|
28459
28605
|
this._chart.unsubscribeClick(this._private__clickOutsideHandler);
|
|
@@ -29312,6 +29458,7 @@ class PositionTool extends DrawingToolBase {
|
|
|
29312
29458
|
this._private__paneView = null;
|
|
29313
29459
|
this._private__isSelected = false;
|
|
29314
29460
|
this._private__isHovered = false;
|
|
29461
|
+
this._private__placement = null;
|
|
29315
29462
|
this._private__isDragging = false;
|
|
29316
29463
|
this._private__dragTarget = null;
|
|
29317
29464
|
this._private__grab = null;
|
|
@@ -29334,6 +29481,32 @@ class PositionTool extends DrawingToolBase {
|
|
|
29334
29481
|
// Create primitive and setup
|
|
29335
29482
|
this._private__createPrimitive();
|
|
29336
29483
|
this._private__updateMetrics();
|
|
29484
|
+
if (this._private__positionOptions.interactive) {
|
|
29485
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
29486
|
+
}
|
|
29487
|
+
}
|
|
29488
|
+
_private__placeAt(point) {
|
|
29489
|
+
const options = this._private__positionOptions;
|
|
29490
|
+
const shift = point._internal_price - options.entryPrice;
|
|
29491
|
+
options.entryPrice = point._internal_price;
|
|
29492
|
+
options.entryTime = point._internal_time;
|
|
29493
|
+
if (options.stopLoss !== undefined) {
|
|
29494
|
+
options.stopLoss += shift;
|
|
29495
|
+
}
|
|
29496
|
+
if (options.takeProfit !== undefined) {
|
|
29497
|
+
options.takeProfit += shift;
|
|
29498
|
+
}
|
|
29499
|
+
options.endTime = timeFromCoordinate(this._chart, this._series, placedEndX(this._chart, point._internal_x)) ?? undefined;
|
|
29500
|
+
this._private__updateMetrics();
|
|
29501
|
+
this._private__requestUpdate();
|
|
29502
|
+
}
|
|
29503
|
+
isComplete() {
|
|
29504
|
+
return !this._private__placement?._internal_pending();
|
|
29505
|
+
}
|
|
29506
|
+
_private__span() {
|
|
29507
|
+
const entryX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.entryTime) ?? 0;
|
|
29508
|
+
const endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? entryX + defaultWidth(this._chart);
|
|
29509
|
+
return { _internal_entryX: entryX, _internal_endX: endX };
|
|
29337
29510
|
}
|
|
29338
29511
|
_private__createPrimitive() {
|
|
29339
29512
|
// Create and cache the paneView once
|
|
@@ -29365,6 +29538,9 @@ class PositionTool extends DrawingToolBase {
|
|
|
29365
29538
|
return new PositionPaneView(this);
|
|
29366
29539
|
}
|
|
29367
29540
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
29541
|
+
if (!this.isComplete()) {
|
|
29542
|
+
return;
|
|
29543
|
+
}
|
|
29368
29544
|
// Draw profit rectangle (green)
|
|
29369
29545
|
if (this._private__profitRect && this._private__positionOptions.takeProfit) {
|
|
29370
29546
|
const timeScale = this._chart.timeScale();
|
|
@@ -29398,16 +29574,9 @@ class PositionTool extends DrawingToolBase {
|
|
|
29398
29574
|
}
|
|
29399
29575
|
}
|
|
29400
29576
|
_private__drawRectangle(ctx, rect, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29401
|
-
const
|
|
29402
|
-
|
|
29403
|
-
|
|
29404
|
-
if (this._private__positionOptions.endTime) {
|
|
29405
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29406
|
-
}
|
|
29407
|
-
else {
|
|
29408
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29409
|
-
endX = chartWidth;
|
|
29410
|
-
}
|
|
29577
|
+
const span = this._private__span();
|
|
29578
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29579
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29411
29580
|
const y1 = (this._series.priceToCoordinate(rect._internal_price1) ?? 0) * verticalPixelRatio;
|
|
29412
29581
|
const y2 = (this._series.priceToCoordinate(rect._internal_price2) ?? 0) * verticalPixelRatio;
|
|
29413
29582
|
// Draw filled rectangle with semi-transparent fill
|
|
@@ -29422,16 +29591,10 @@ class PositionTool extends DrawingToolBase {
|
|
|
29422
29591
|
ctx.stroke();
|
|
29423
29592
|
}
|
|
29424
29593
|
_private__drawEntryLine(ctx, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29425
|
-
const
|
|
29594
|
+
const span = this._private__span();
|
|
29595
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29596
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29426
29597
|
const entryY = (this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0) * verticalPixelRatio;
|
|
29427
|
-
let endX;
|
|
29428
|
-
if (this._private__positionOptions.endTime) {
|
|
29429
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29430
|
-
}
|
|
29431
|
-
else {
|
|
29432
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29433
|
-
endX = chartWidth;
|
|
29434
|
-
}
|
|
29435
29598
|
// Draw horizontal entry line (divider)
|
|
29436
29599
|
const lineColor = this._private__positionOptions.entryLineColor;
|
|
29437
29600
|
ctx.strokeStyle = lineColor;
|
|
@@ -29545,9 +29708,11 @@ class PositionTool extends DrawingToolBase {
|
|
|
29545
29708
|
const padding = 6 * horizontalPixelRatio;
|
|
29546
29709
|
const labelWidth = textMetrics.width + padding * 2;
|
|
29547
29710
|
const labelHeight = 20 * horizontalPixelRatio;
|
|
29548
|
-
//
|
|
29711
|
+
// Outside the box, so a label wider than it does not cover the handles on its edge
|
|
29712
|
+
const entryY = (this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0) * verticalPixelRatio;
|
|
29713
|
+
const gap = 3 * verticalPixelRatio;
|
|
29549
29714
|
const labelX = entryX + 8 * horizontalPixelRatio;
|
|
29550
|
-
const labelY = y - labelHeight
|
|
29715
|
+
const labelY = y <= entryY ? y - labelHeight - gap : y + gap;
|
|
29551
29716
|
// Draw label background
|
|
29552
29717
|
ctx.fillStyle = rect._internal_color;
|
|
29553
29718
|
ctx.fillRect(labelX, labelY, labelWidth, labelHeight);
|
|
@@ -29555,10 +29720,12 @@ class PositionTool extends DrawingToolBase {
|
|
|
29555
29720
|
ctx.fillStyle = '#ffffff';
|
|
29556
29721
|
ctx.textAlign = 'left';
|
|
29557
29722
|
ctx.textBaseline = 'middle';
|
|
29558
|
-
ctx.fillText(labelText, labelX + padding,
|
|
29723
|
+
ctx.fillText(labelText, labelX + padding, labelY + labelHeight / 2);
|
|
29559
29724
|
}
|
|
29560
29725
|
_private__drawEndpoint(ctx, price, color, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29561
|
-
const
|
|
29726
|
+
const span = this._private__span();
|
|
29727
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29728
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29562
29729
|
const y = (this._series.priceToCoordinate(price) ?? 0) * verticalPixelRatio;
|
|
29563
29730
|
// Draw circle endpoint at entry
|
|
29564
29731
|
const circleColor = color;
|
|
@@ -29570,14 +29737,6 @@ class PositionTool extends DrawingToolBase {
|
|
|
29570
29737
|
ctx.fill();
|
|
29571
29738
|
ctx.stroke();
|
|
29572
29739
|
// Draw square endpoint at the right edge
|
|
29573
|
-
let endX;
|
|
29574
|
-
if (this._private__positionOptions.endTime) {
|
|
29575
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29576
|
-
}
|
|
29577
|
-
else {
|
|
29578
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29579
|
-
endX = chartWidth - 10 * horizontalPixelRatio;
|
|
29580
|
-
}
|
|
29581
29740
|
const size = 8 * horizontalPixelRatio;
|
|
29582
29741
|
const squareColor = color;
|
|
29583
29742
|
ctx.fillStyle = squareColor;
|
|
@@ -29698,18 +29857,12 @@ class PositionTool extends DrawingToolBase {
|
|
|
29698
29857
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
29699
29858
|
}
|
|
29700
29859
|
hitTest(x, y) {
|
|
29701
|
-
if (!this._private__positionOptions.stopLoss && !this._private__positionOptions.takeProfit) {
|
|
29860
|
+
if (!this.isComplete() || (!this._private__positionOptions.stopLoss && !this._private__positionOptions.takeProfit)) {
|
|
29702
29861
|
return false;
|
|
29703
29862
|
}
|
|
29704
|
-
const
|
|
29705
|
-
|
|
29706
|
-
|
|
29707
|
-
endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0;
|
|
29708
|
-
}
|
|
29709
|
-
else {
|
|
29710
|
-
const chartWidth = this._chart.chartElement().clientWidth;
|
|
29711
|
-
endX = chartWidth;
|
|
29712
|
-
}
|
|
29863
|
+
const { _internal_entryX: entryX, _internal_endX: endX } = this._private__span();
|
|
29864
|
+
const left = Math.min(entryX, endX);
|
|
29865
|
+
const right = Math.max(entryX, endX);
|
|
29713
29866
|
// Check if inside the entire Position Tool area (rectangles)
|
|
29714
29867
|
if (this._private__positionOptions.takeProfit && this._private__positionOptions.stopLoss) {
|
|
29715
29868
|
const tpY = this._series.priceToCoordinate(this._private__positionOptions.takeProfit) ?? 0;
|
|
@@ -29717,7 +29870,7 @@ class PositionTool extends DrawingToolBase {
|
|
|
29717
29870
|
const minY = Math.min(tpY, slY);
|
|
29718
29871
|
const maxY = Math.max(tpY, slY);
|
|
29719
29872
|
// Check if inside the rectangle bounds (entire tool area)
|
|
29720
|
-
if (x >=
|
|
29873
|
+
if (x >= left && x <= right && y >= minY && y <= maxY) {
|
|
29721
29874
|
return true;
|
|
29722
29875
|
}
|
|
29723
29876
|
// Also check entry line area
|
|
@@ -29729,15 +29882,12 @@ class PositionTool extends DrawingToolBase {
|
|
|
29729
29882
|
return false;
|
|
29730
29883
|
}
|
|
29731
29884
|
hitTestEndpoint(x, y) {
|
|
29732
|
-
|
|
29733
|
-
|
|
29734
|
-
if (this._private__positionOptions.endTime) {
|
|
29735
|
-
endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0;
|
|
29736
|
-
}
|
|
29737
|
-
else {
|
|
29738
|
-
const chartWidth = this._chart.chartElement().clientWidth;
|
|
29739
|
-
endX = chartWidth;
|
|
29885
|
+
if (!this.isComplete()) {
|
|
29886
|
+
return null;
|
|
29740
29887
|
}
|
|
29888
|
+
const { _internal_entryX: entryX, _internal_endX: endX } = this._private__span();
|
|
29889
|
+
const left = Math.min(entryX, endX);
|
|
29890
|
+
const right = Math.max(entryX, endX);
|
|
29741
29891
|
const tolerance = 10;
|
|
29742
29892
|
// Check TP left endpoint (circle)
|
|
29743
29893
|
if (this._private__positionOptions.takeProfit) {
|
|
@@ -29774,7 +29924,7 @@ class PositionTool extends DrawingToolBase {
|
|
|
29774
29924
|
// Check entry line (middle divider line) - higher priority than 'move'
|
|
29775
29925
|
const entryY = this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0;
|
|
29776
29926
|
const lineTolerance = 8;
|
|
29777
|
-
if (x >=
|
|
29927
|
+
if (x >= left && x <= right && Math.abs(y - entryY) <= lineTolerance) {
|
|
29778
29928
|
return 'entry';
|
|
29779
29929
|
}
|
|
29780
29930
|
// Check if clicking on the body (rectangles) for moving entire tool
|
|
@@ -29784,7 +29934,7 @@ class PositionTool extends DrawingToolBase {
|
|
|
29784
29934
|
const minY = Math.min(tpY, slY);
|
|
29785
29935
|
const maxY = Math.max(tpY, slY);
|
|
29786
29936
|
// Check if inside the rectangle bounds
|
|
29787
|
-
if (x >=
|
|
29937
|
+
if (x >= left && x <= right && y >= minY && y <= maxY) {
|
|
29788
29938
|
return 'move';
|
|
29789
29939
|
}
|
|
29790
29940
|
}
|
|
@@ -29884,6 +30034,7 @@ class PositionTool extends DrawingToolBase {
|
|
|
29884
30034
|
this._private__requestUpdate();
|
|
29885
30035
|
}
|
|
29886
30036
|
remove() {
|
|
30037
|
+
this._private__placement?._internal_stop();
|
|
29887
30038
|
if (this._private__primitive) {
|
|
29888
30039
|
this._series.detachPrimitive(this._private__primitive);
|
|
29889
30040
|
this._private__primitive = null;
|
|
@@ -29930,6 +30081,7 @@ class GanttPaneView {
|
|
|
29930
30081
|
}
|
|
29931
30082
|
}
|
|
29932
30083
|
|
|
30084
|
+
const TOP_PADDING = 50;
|
|
29933
30085
|
class GanttTool extends DrawingToolBase {
|
|
29934
30086
|
constructor(context, options) {
|
|
29935
30087
|
super(context, 'gantt', options);
|
|
@@ -29943,6 +30095,7 @@ class GanttTool extends DrawingToolBase {
|
|
|
29943
30095
|
this._private__grab = null;
|
|
29944
30096
|
this._private__moveStart = null;
|
|
29945
30097
|
this._private__hoveredSegmentIndex = -1;
|
|
30098
|
+
this._private__placement = null;
|
|
29946
30099
|
this._private__ganttOptions = {
|
|
29947
30100
|
segments: [],
|
|
29948
30101
|
rowHeight: 40,
|
|
@@ -29955,6 +30108,43 @@ class GanttTool extends DrawingToolBase {
|
|
|
29955
30108
|
};
|
|
29956
30109
|
this._registerOptions(this._private__ganttOptions);
|
|
29957
30110
|
this._private__createPrimitive();
|
|
30111
|
+
if (this._private__ganttOptions.interactive) {
|
|
30112
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
30113
|
+
}
|
|
30114
|
+
}
|
|
30115
|
+
_private__placeAt(point) {
|
|
30116
|
+
const segments = this._private__ganttOptions.segments ?? [];
|
|
30117
|
+
const endTime = timeFromCoordinate(this._chart, this._series, placedEndX(this._chart, point._internal_x)) ?? point._internal_time;
|
|
30118
|
+
const rowPitch = this._private__ganttOptions.rowHeight + this._private__ganttOptions.rowSpacing;
|
|
30119
|
+
const row = Math.max(0, Math.floor((point._internal_y - TOP_PADDING) / rowPitch));
|
|
30120
|
+
const shift = segments.length > 0 ? row - segments[0].level : 0;
|
|
30121
|
+
for (const segment of segments) {
|
|
30122
|
+
segment.startTime = point._internal_time;
|
|
30123
|
+
segment.endTime = endTime;
|
|
30124
|
+
segment.level = Math.max(0, segment.level + shift);
|
|
30125
|
+
}
|
|
30126
|
+
this._private__requestUpdate();
|
|
30127
|
+
}
|
|
30128
|
+
isComplete() {
|
|
30129
|
+
return !this._private__placement?._internal_pending();
|
|
30130
|
+
}
|
|
30131
|
+
selectionBox() {
|
|
30132
|
+
const segments = this._private__ganttOptions.segments ?? [];
|
|
30133
|
+
if (segments.length === 0) {
|
|
30134
|
+
return null;
|
|
30135
|
+
}
|
|
30136
|
+
const rowHeight = this._private__ganttOptions.rowHeight;
|
|
30137
|
+
const pitch = rowHeight + this._private__ganttOptions.rowSpacing;
|
|
30138
|
+
// Typed as the public shape: an inferred one gets its keys renamed by the build
|
|
30139
|
+
const box = { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity };
|
|
30140
|
+
for (const segment of segments) {
|
|
30141
|
+
const top = TOP_PADDING + segment.level * pitch;
|
|
30142
|
+
box.left = Math.min(box.left, coordinateFromTime(this._chart, this._series, segment.startTime) ?? 0);
|
|
30143
|
+
box.right = Math.max(box.right, coordinateFromTime(this._chart, this._series, segment.endTime) ?? 0);
|
|
30144
|
+
box.top = Math.min(box.top, top);
|
|
30145
|
+
box.bottom = Math.max(box.bottom, top + rowHeight);
|
|
30146
|
+
}
|
|
30147
|
+
return box;
|
|
29958
30148
|
}
|
|
29959
30149
|
_private__createPrimitive() {
|
|
29960
30150
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -29985,11 +30175,10 @@ class GanttTool extends DrawingToolBase {
|
|
|
29985
30175
|
return new GanttPaneView(this);
|
|
29986
30176
|
}
|
|
29987
30177
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
29988
|
-
if (!this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0)
|
|
30178
|
+
if (!this.isComplete() || !this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0)
|
|
29989
30179
|
return;
|
|
29990
30180
|
// Position gantt at top of chart with padding
|
|
29991
|
-
const
|
|
29992
|
-
const baseY = topPadding * verticalPixelRatio;
|
|
30181
|
+
const baseY = TOP_PADDING * verticalPixelRatio;
|
|
29993
30182
|
const rowHeight = this._private__ganttOptions.rowHeight * verticalPixelRatio;
|
|
29994
30183
|
const rowSpacing = this._private__ganttOptions.rowSpacing * verticalPixelRatio;
|
|
29995
30184
|
// Draw grid lines if enabled
|
|
@@ -30168,11 +30357,10 @@ class GanttTool extends DrawingToolBase {
|
|
|
30168
30357
|
this._private__moveStart = null;
|
|
30169
30358
|
}
|
|
30170
30359
|
hitTest(x, y) {
|
|
30171
|
-
if (!this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0) {
|
|
30360
|
+
if (!this.isComplete() || !this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0) {
|
|
30172
30361
|
return false;
|
|
30173
30362
|
}
|
|
30174
|
-
const
|
|
30175
|
-
const baseY = topPadding;
|
|
30363
|
+
const baseY = TOP_PADDING;
|
|
30176
30364
|
const rowHeight = this._private__ganttOptions.rowHeight;
|
|
30177
30365
|
const rowSpacing = this._private__ganttOptions.rowSpacing;
|
|
30178
30366
|
// Check each segment
|
|
@@ -30226,6 +30414,7 @@ class GanttTool extends DrawingToolBase {
|
|
|
30226
30414
|
this._private__requestUpdate();
|
|
30227
30415
|
}
|
|
30228
30416
|
remove() {
|
|
30417
|
+
this._private__placement?._internal_stop();
|
|
30229
30418
|
if (this._private__primitive) {
|
|
30230
30419
|
this._series.detachPrimitive(this._private__primitive);
|
|
30231
30420
|
this._private__primitive = null;
|
|
@@ -30361,6 +30550,7 @@ class DrawingToolsManager {
|
|
|
30361
30550
|
}
|
|
30362
30551
|
this._private__completionCheck = setTimeout(() => {
|
|
30363
30552
|
this._private__completionCheck = null;
|
|
30553
|
+
const completed = [];
|
|
30364
30554
|
for (const id of Array.from(this._private__pendingToolIds)) {
|
|
30365
30555
|
const tool = this._private__tools.get(id);
|
|
30366
30556
|
if (!tool) {
|
|
@@ -30369,9 +30559,15 @@ class DrawingToolsManager {
|
|
|
30369
30559
|
}
|
|
30370
30560
|
if (tool.isComplete()) {
|
|
30371
30561
|
this._private__pendingToolIds.delete(id);
|
|
30372
|
-
|
|
30562
|
+
completed.push(id);
|
|
30373
30563
|
}
|
|
30374
30564
|
}
|
|
30565
|
+
if (completed.length > 0) {
|
|
30566
|
+
this.recordChange();
|
|
30567
|
+
}
|
|
30568
|
+
for (const id of completed) {
|
|
30569
|
+
this._private__drawingCompleted._internal_fire(id);
|
|
30570
|
+
}
|
|
30375
30571
|
}, 0);
|
|
30376
30572
|
}
|
|
30377
30573
|
/**
|
|
@@ -30431,12 +30627,16 @@ class DrawingToolsManager {
|
|
|
30431
30627
|
if (this._private__restoring) {
|
|
30432
30628
|
return;
|
|
30433
30629
|
}
|
|
30630
|
+
const next = this.serializeAll();
|
|
30631
|
+
if (JSON.stringify(next) === JSON.stringify(this._private__committed)) {
|
|
30632
|
+
return;
|
|
30633
|
+
}
|
|
30434
30634
|
this._private__past.push(this._private__committed);
|
|
30435
30635
|
if (this._private__past.length > UNDO_HISTORY_LIMIT) {
|
|
30436
30636
|
this._private__past.shift();
|
|
30437
30637
|
}
|
|
30438
30638
|
this._private__future = [];
|
|
30439
|
-
this._private__committed =
|
|
30639
|
+
this._private__committed = next;
|
|
30440
30640
|
}
|
|
30441
30641
|
canUndo() {
|
|
30442
30642
|
return this._private__past.length > 0;
|
|
@@ -30492,11 +30692,25 @@ class DrawingToolsManager {
|
|
|
30492
30692
|
const tool = this._private__tools.get(this._private__selectedToolId);
|
|
30493
30693
|
return tool ? this._private__boundsOf(tool) : null;
|
|
30494
30694
|
}
|
|
30695
|
+
/** Relative to the chart element; the tool's box is relative to its pane. */
|
|
30696
|
+
_private__boundsOf(tool) {
|
|
30697
|
+
const box = tool.selectionBox() ?? this._private__boxFromPoints(tool);
|
|
30698
|
+
if (box === null) {
|
|
30699
|
+
return null;
|
|
30700
|
+
}
|
|
30701
|
+
const offset = this._private__paneOffsetOf(tool);
|
|
30702
|
+
return {
|
|
30703
|
+
left: box.left + offset._internal_x,
|
|
30704
|
+
right: box.right + offset._internal_x,
|
|
30705
|
+
top: box.top + offset._internal_y,
|
|
30706
|
+
bottom: box.bottom + offset._internal_y,
|
|
30707
|
+
};
|
|
30708
|
+
}
|
|
30495
30709
|
/**
|
|
30496
30710
|
* Bounds come from the tool's own serialized points, so this works for every
|
|
30497
30711
|
* tool without each one having to report a box.
|
|
30498
30712
|
*/
|
|
30499
|
-
|
|
30713
|
+
_private__boxFromPoints(tool) {
|
|
30500
30714
|
const series = tool.series();
|
|
30501
30715
|
const points = tool.serialize().points;
|
|
30502
30716
|
let left = Number.POSITIVE_INFINITY;
|
|
@@ -30519,13 +30733,7 @@ class DrawingToolsManager {
|
|
|
30519
30733
|
if (!found) {
|
|
30520
30734
|
return null;
|
|
30521
30735
|
}
|
|
30522
|
-
|
|
30523
|
-
return {
|
|
30524
|
-
left: left + offset._internal_x,
|
|
30525
|
-
right: right + offset._internal_x,
|
|
30526
|
-
top: top + offset._internal_y,
|
|
30527
|
-
bottom: bottom + offset._internal_y,
|
|
30528
|
-
};
|
|
30736
|
+
return { left, top, right, bottom };
|
|
30529
30737
|
}
|
|
30530
30738
|
/** Panes below the first one are offset inside the chart element. */
|
|
30531
30739
|
_private__paneOffsetOf(tool) {
|
|
@@ -30609,7 +30817,10 @@ class DrawingToolsManager {
|
|
|
30609
30817
|
serializeAll() {
|
|
30610
30818
|
const result = [];
|
|
30611
30819
|
for (const tool of this._private__tools.values()) {
|
|
30612
|
-
|
|
30820
|
+
// Not drawn yet: undo would bring it back as a finished drawing
|
|
30821
|
+
if (tool.isComplete()) {
|
|
30822
|
+
result.push(tool.serialize());
|
|
30823
|
+
}
|
|
30613
30824
|
}
|
|
30614
30825
|
return result;
|
|
30615
30826
|
}
|
|
@@ -31234,7 +31445,7 @@ const customSeriesDefaultOptions = {
|
|
|
31234
31445
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
31235
31446
|
*/
|
|
31236
31447
|
function version() {
|
|
31237
|
-
return "2.3.
|
|
31448
|
+
return "2.3.15";
|
|
31238
31449
|
}
|
|
31239
31450
|
|
|
31240
31451
|
export { areaSeries as AreaSeries, ArrowTool, barSeries as BarSeries, baselineSeries as BaselineSeries, BrushTool, candlestickSeries as CandlestickSeries, CircleTool, ColorType, CrossLineTool, CrosshairMode, DEFAULT_SESSIONS, DraggablePriceLine, DrawingToolsManager, EXTENDED_FIBONACCI_RATIOS, FibonacciCalculator, FibonacciExtensionTool, FibonacciFanTool, FibonacciTool, GanttTool, histogramSeries as HistogramSeries, HorizontalLineTool, InteractiveLineManager, LastPriceAnimationMode, lineSeries as LineSeries, LineStyle, LineType, MismatchDirection, ParallelChannelTool, PitchforkTool, PolygonTool, PositionCalculator, PositionLine, PositionMarkersManager, PositionTool, PriceLineSource, PriceScaleMode, RectangleTool, RulerCalculator, RulerTool, STANDARD_FIBONACCI_RATIOS, TextTool, TickMarkType, TrackingModeExitMode, TradingSessionsIndicator, TrendLineTool, VerticalLineTool, VolumeProfileIndicator, applyADX, applyATR, applyBollingerBands, applyCCI, applyDonchianChannels, applyEMA, applyHeikinAshi, applyIchimoku, applyKeltnerChannels, applyMACD, applyMFI, applyOBV, applyParabolicSAR, applyPivotPoints, applyRSI, applySMA, applyStochastic, applySuperTrend, applyVWAP, applyVolume, applyWMA, applyWilliamsR, calculateHeikinAshi, calculatePipConfig, coordinateFromTime, createArrowTool, createBrushTool, createChart, createChartEx, createCircleTool, createCrossLineTool, createFibonacciExtensionTool, createFibonacciFanTool, createFibonacciTool, createGanttTool, createHorizontalLineTool, createImageWatermark, createInteractiveLineManager, createOptionsChart, createParallelChannelTool, createPitchforkTool, createPolygonTool, createPositionLine, createPositionMarkers, createPositionTool, createRectangleTool, createRulerTool, createSeriesMarkers, createTextTool, createTextWatermark, createTradingLine, createTradingSessionsIndicator, createTrendLineTool, createUpDownMarkers, createVerticalLineTool, createVolumeProfileIndicator, createYieldCurveChart, customSeriesDefaultOptions, defaultHorzScaleBehavior, getPipConfig, hideSeriesPaint, isBusinessDay, isUTCTimestamp, setSeriesVolumes, setVolumeProfileData, timeFromCoordinate, version };
|