@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)
|
|
@@ -14687,6 +14687,9 @@
|
|
|
14687
14687
|
function shapeMargin(barSpacing) {
|
|
14688
14688
|
return Math.max(size(barSpacing, 0.1), 3 /* Constants.MinShapeMargin */);
|
|
14689
14689
|
}
|
|
14690
|
+
function barGap(barSpacing) {
|
|
14691
|
+
return Math.max(shapeMargin(barSpacing), 10 /* Constants.MinBarGap */);
|
|
14692
|
+
}
|
|
14690
14693
|
function calculateAdjustedMargin(margin, hasSide, hasInBar) {
|
|
14691
14694
|
if (hasSide) {
|
|
14692
14695
|
return margin;
|
|
@@ -15313,17 +15316,18 @@
|
|
|
15313
15316
|
}
|
|
15314
15317
|
let prevTimeIndex = NaN;
|
|
15315
15318
|
const shapeMargin$1 = shapeMargin(timeScale.options().barSpacing);
|
|
15319
|
+
const barGap$1 = barGap(timeScale.options().barSpacing);
|
|
15316
15320
|
const offsets = {
|
|
15317
|
-
_internal_aboveBar:
|
|
15318
|
-
_internal_belowBar:
|
|
15321
|
+
_internal_aboveBar: barGap$1,
|
|
15322
|
+
_internal_belowBar: barGap$1,
|
|
15319
15323
|
};
|
|
15320
15324
|
this._private__data._internal_visibleRange = visibleTimedValues(this._private__data._internal_items, visibleBarsRange, true);
|
|
15321
15325
|
for (let index = this._private__data._internal_visibleRange.from; index < this._private__data._internal_visibleRange.to; index++) {
|
|
15322
15326
|
const marker = seriesMarkers[index];
|
|
15323
15327
|
if (marker.time !== prevTimeIndex) {
|
|
15324
15328
|
// new bar, reset stack counter
|
|
15325
|
-
offsets._internal_aboveBar =
|
|
15326
|
-
offsets._internal_belowBar =
|
|
15329
|
+
offsets._internal_aboveBar = barGap$1;
|
|
15330
|
+
offsets._internal_belowBar = barGap$1;
|
|
15327
15331
|
prevTimeIndex = marker.time;
|
|
15328
15332
|
}
|
|
15329
15333
|
const rendererItem = this._private__data._internal_items[index];
|
|
@@ -15440,7 +15444,7 @@
|
|
|
15440
15444
|
this._private__cachedBarSpacing = barSpacing;
|
|
15441
15445
|
if (this._private__markers.length > 0) {
|
|
15442
15446
|
const shapeMargin$1 = shapeMargin(barSpacing);
|
|
15443
|
-
const marginValue = calculateShapeHeight(barSpacing) * 1.5 + shapeMargin$1
|
|
15447
|
+
const marginValue = calculateShapeHeight(barSpacing) * 1.5 + shapeMargin$1 + barGap(barSpacing);
|
|
15444
15448
|
const positions = this._private__getMarkerPositions();
|
|
15445
15449
|
this._private__autoScaleMargins = {
|
|
15446
15450
|
above: calculateAdjustedMargin(marginValue, positions.aboveBar, positions.inBar),
|
|
@@ -17943,10 +17947,13 @@
|
|
|
17943
17947
|
const blankSource = (blank) => {
|
|
17944
17948
|
if (blank && restoreSourcePaint === null) {
|
|
17945
17949
|
restoreSourcePaint = hideSeriesPaint(series);
|
|
17950
|
+
// Under the blank source, so what hangs off it draws over the candles.
|
|
17951
|
+
haSeries.setSeriesOrder(series.seriesOrder());
|
|
17946
17952
|
}
|
|
17947
17953
|
else if (!blank && restoreSourcePaint !== null) {
|
|
17948
17954
|
restoreSourcePaint();
|
|
17949
17955
|
restoreSourcePaint = null;
|
|
17956
|
+
haSeries.setSeriesOrder(series.seriesOrder() + 1);
|
|
17950
17957
|
}
|
|
17951
17958
|
};
|
|
17952
17959
|
const runtime = bindIndicator({
|
|
@@ -17975,8 +17982,9 @@
|
|
|
17975
17982
|
blankSource(current.hideSource === true);
|
|
17976
17983
|
},
|
|
17977
17984
|
});
|
|
17978
|
-
|
|
17979
|
-
|
|
17985
|
+
// Returned as a literal: a local annotation would let the property renamer mangle `series`.
|
|
17986
|
+
return {
|
|
17987
|
+
series: haSeries,
|
|
17980
17988
|
options: runtime.options,
|
|
17981
17989
|
applyOptions: runtime.applyOptions,
|
|
17982
17990
|
recalculate: runtime.recalculate,
|
|
@@ -17992,7 +18000,6 @@
|
|
|
17992
18000
|
}
|
|
17993
18001
|
},
|
|
17994
18002
|
};
|
|
17995
|
-
return handle;
|
|
17996
18003
|
}
|
|
17997
18004
|
|
|
17998
18005
|
/**
|
|
@@ -21644,6 +21651,13 @@
|
|
|
21644
21651
|
series() {
|
|
21645
21652
|
return this._series;
|
|
21646
21653
|
}
|
|
21654
|
+
/**
|
|
21655
|
+
* Box the selection toolbar anchors to, in pane pixels. Null falls back to
|
|
21656
|
+
* the serialized points, which cannot place a line across the whole pane.
|
|
21657
|
+
*/
|
|
21658
|
+
selectionBox() {
|
|
21659
|
+
return null;
|
|
21660
|
+
}
|
|
21647
21661
|
getState() {
|
|
21648
21662
|
return this._state;
|
|
21649
21663
|
}
|
|
@@ -22320,6 +22334,53 @@
|
|
|
22320
22334
|
return new TrendLineTool(context, options);
|
|
22321
22335
|
}
|
|
22322
22336
|
|
|
22337
|
+
const END_HANDLE_MARGIN = 10;
|
|
22338
|
+
/**
|
|
22339
|
+
* Hands the next `clicks` clicks on the chart to `onClick`, past the last bar
|
|
22340
|
+
* too. A press that grabbed another drawing does not count.
|
|
22341
|
+
*/
|
|
22342
|
+
function placeByClicks(chart, series, clicks, onClick) {
|
|
22343
|
+
let placed = 0;
|
|
22344
|
+
let handler = null;
|
|
22345
|
+
const stop = () => {
|
|
22346
|
+
if (handler !== null) {
|
|
22347
|
+
chart.unsubscribeClick(handler);
|
|
22348
|
+
handler = null;
|
|
22349
|
+
}
|
|
22350
|
+
};
|
|
22351
|
+
handler = (param) => {
|
|
22352
|
+
if (!param.point || consumeInputClaim(chart)) {
|
|
22353
|
+
return;
|
|
22354
|
+
}
|
|
22355
|
+
const price = series.coordinateToPrice(param.point.y);
|
|
22356
|
+
const time = timeFromCoordinate(chart, series, param.point.x);
|
|
22357
|
+
if (price === null || time === null) {
|
|
22358
|
+
return;
|
|
22359
|
+
}
|
|
22360
|
+
placed++;
|
|
22361
|
+
if (placed >= clicks) {
|
|
22362
|
+
stop();
|
|
22363
|
+
}
|
|
22364
|
+
onClick({ _internal_time: time, _internal_price: price, _internal_x: param.point.x, _internal_y: param.point.y }, placed - 1);
|
|
22365
|
+
};
|
|
22366
|
+
chart.subscribeClick(handler);
|
|
22367
|
+
return {
|
|
22368
|
+
_internal_pending: () => handler !== null,
|
|
22369
|
+
_internal_stop: stop,
|
|
22370
|
+
};
|
|
22371
|
+
}
|
|
22372
|
+
/** A fifth of the pane, and never less than a bar. */
|
|
22373
|
+
function defaultWidth(chart) {
|
|
22374
|
+
const timeScale = chart.timeScale();
|
|
22375
|
+
return Math.max(timeScale.width() / 5, timeScale.options().barSpacing);
|
|
22376
|
+
}
|
|
22377
|
+
/** Kept inside the pane: past it, the handles on the end hide under the price axis. */
|
|
22378
|
+
function placedEndX(chart, x) {
|
|
22379
|
+
const timeScale = chart.timeScale();
|
|
22380
|
+
const onScreen = Math.min(x + defaultWidth(chart), timeScale.width() - END_HANDLE_MARGIN);
|
|
22381
|
+
return Math.max(onScreen, x + timeScale.options().barSpacing);
|
|
22382
|
+
}
|
|
22383
|
+
|
|
22323
22384
|
class HorizontalLinePaneRenderer {
|
|
22324
22385
|
constructor(tool) {
|
|
22325
22386
|
this._private__tool = tool;
|
|
@@ -22360,6 +22421,7 @@
|
|
|
22360
22421
|
this._private__isDragging = false;
|
|
22361
22422
|
this._private__grab = null;
|
|
22362
22423
|
this._private__moveStartPrice = 0;
|
|
22424
|
+
this._private__placement = null;
|
|
22363
22425
|
this._private__hLineOptions = {
|
|
22364
22426
|
lineColor: '#2962ff',
|
|
22365
22427
|
lineWidth: 2,
|
|
@@ -22372,6 +22434,26 @@
|
|
|
22372
22434
|
};
|
|
22373
22435
|
this._registerOptions(this._private__hLineOptions);
|
|
22374
22436
|
this._private__createPrimitive();
|
|
22437
|
+
if (this._private__hLineOptions.interactive) {
|
|
22438
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
22439
|
+
}
|
|
22440
|
+
}
|
|
22441
|
+
_private__placeAt(point) {
|
|
22442
|
+
this._private__hLineOptions.price = point._internal_price;
|
|
22443
|
+
if (this._private__hLineOptions.startTime !== undefined) {
|
|
22444
|
+
this._private__hLineOptions.startTime = point._internal_time;
|
|
22445
|
+
}
|
|
22446
|
+
this._private__requestUpdate();
|
|
22447
|
+
}
|
|
22448
|
+
isComplete() {
|
|
22449
|
+
return !this._private__placement?._internal_pending();
|
|
22450
|
+
}
|
|
22451
|
+
selectionBox() {
|
|
22452
|
+
const y = this._private__hLineOptions.price === undefined ? null : this._series.priceToCoordinate(this._private__hLineOptions.price);
|
|
22453
|
+
if (y === null) {
|
|
22454
|
+
return null;
|
|
22455
|
+
}
|
|
22456
|
+
return { left: this._private__startX(), right: this._chart.timeScale().width(), top: y, bottom: y };
|
|
22375
22457
|
}
|
|
22376
22458
|
_private__createPrimitive() {
|
|
22377
22459
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -22409,7 +22491,7 @@
|
|
|
22409
22491
|
return coordinateFromTime(this._chart, this._series, this._private__hLineOptions.startTime) ?? 0;
|
|
22410
22492
|
}
|
|
22411
22493
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
22412
|
-
if (this._private__hLineOptions.price === undefined)
|
|
22494
|
+
if (!this.isComplete() || this._private__hLineOptions.price === undefined)
|
|
22413
22495
|
return;
|
|
22414
22496
|
const y = (this._series.priceToCoordinate(this._private__hLineOptions.price) ?? 0) * verticalPixelRatio;
|
|
22415
22497
|
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
@@ -22503,7 +22585,7 @@
|
|
|
22503
22585
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
22504
22586
|
}
|
|
22505
22587
|
hitTest(x, y) {
|
|
22506
|
-
if (this._private__hLineOptions.price === undefined) {
|
|
22588
|
+
if (!this.isComplete() || this._private__hLineOptions.price === undefined) {
|
|
22507
22589
|
return false;
|
|
22508
22590
|
}
|
|
22509
22591
|
const lineY = this._series.priceToCoordinate(this._private__hLineOptions.price) ?? 0;
|
|
@@ -22578,6 +22660,7 @@
|
|
|
22578
22660
|
this._private__requestUpdate();
|
|
22579
22661
|
}
|
|
22580
22662
|
remove() {
|
|
22663
|
+
this._private__placement?._internal_stop();
|
|
22581
22664
|
if (this._private__primitive) {
|
|
22582
22665
|
this._series.detachPrimitive(this._private__primitive);
|
|
22583
22666
|
this._private__primitive = null;
|
|
@@ -22637,6 +22720,7 @@
|
|
|
22637
22720
|
this._private__grab = null;
|
|
22638
22721
|
this._private__moveStartTime = 0;
|
|
22639
22722
|
this._private__moveStartPrice = 0;
|
|
22723
|
+
this._private__placement = null;
|
|
22640
22724
|
this._private__crossOptions = {
|
|
22641
22725
|
lineColor: '#787b86',
|
|
22642
22726
|
lineWidth: 1,
|
|
@@ -22646,6 +22730,16 @@
|
|
|
22646
22730
|
};
|
|
22647
22731
|
this._registerOptions(this._private__crossOptions);
|
|
22648
22732
|
this._private__createPrimitive();
|
|
22733
|
+
if (this._private__crossOptions.interactive) {
|
|
22734
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
22735
|
+
this._private__crossOptions.time = point._internal_time;
|
|
22736
|
+
this._private__crossOptions.price = point._internal_price;
|
|
22737
|
+
this._private__requestUpdate();
|
|
22738
|
+
});
|
|
22739
|
+
}
|
|
22740
|
+
}
|
|
22741
|
+
isComplete() {
|
|
22742
|
+
return !this._private__placement?._internal_pending();
|
|
22649
22743
|
}
|
|
22650
22744
|
_private__createPrimitive() {
|
|
22651
22745
|
this._private__paneView = new CrossLinePaneView(this);
|
|
@@ -22673,7 +22767,7 @@
|
|
|
22673
22767
|
this._private__requestUpdate();
|
|
22674
22768
|
}
|
|
22675
22769
|
_private__coordinates() {
|
|
22676
|
-
if (this._private__crossOptions.time === undefined || this._private__crossOptions.price === undefined) {
|
|
22770
|
+
if (!this.isComplete() || this._private__crossOptions.time === undefined || this._private__crossOptions.price === undefined) {
|
|
22677
22771
|
return null;
|
|
22678
22772
|
}
|
|
22679
22773
|
const x = coordinateFromTime(this._chart, this._series, this._private__crossOptions.time);
|
|
@@ -22796,6 +22890,7 @@
|
|
|
22796
22890
|
return this._private__isHovered;
|
|
22797
22891
|
}
|
|
22798
22892
|
remove() {
|
|
22893
|
+
this._private__placement?._internal_stop();
|
|
22799
22894
|
if (this._private__primitive) {
|
|
22800
22895
|
try {
|
|
22801
22896
|
this._series.detachPrimitive(this._private__primitive);
|
|
@@ -24218,6 +24313,7 @@
|
|
|
24218
24313
|
this._private__isDragging = false;
|
|
24219
24314
|
this._private__grab = null;
|
|
24220
24315
|
this._private__moveStartTime = 0;
|
|
24316
|
+
this._private__placement = null;
|
|
24221
24317
|
this._private__vLineOptions = {
|
|
24222
24318
|
lineColor: '#787b86',
|
|
24223
24319
|
lineWidth: 1,
|
|
@@ -24229,6 +24325,29 @@
|
|
|
24229
24325
|
};
|
|
24230
24326
|
this._registerOptions(this._private__vLineOptions);
|
|
24231
24327
|
this._private__createPrimitive();
|
|
24328
|
+
if (this._private__vLineOptions.interactive) {
|
|
24329
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
24330
|
+
this._private__vLineOptions.time = point._internal_time;
|
|
24331
|
+
this._private__requestUpdate();
|
|
24332
|
+
});
|
|
24333
|
+
}
|
|
24334
|
+
}
|
|
24335
|
+
isComplete() {
|
|
24336
|
+
return !this._private__placement?._internal_pending();
|
|
24337
|
+
}
|
|
24338
|
+
selectionBox() {
|
|
24339
|
+
const x = coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time);
|
|
24340
|
+
if (x === null) {
|
|
24341
|
+
return null;
|
|
24342
|
+
}
|
|
24343
|
+
let middle;
|
|
24344
|
+
try {
|
|
24345
|
+
middle = this._series.getPane().getHeight() / 2;
|
|
24346
|
+
}
|
|
24347
|
+
catch (error) {
|
|
24348
|
+
return null;
|
|
24349
|
+
}
|
|
24350
|
+
return { left: x, right: x, top: middle, bottom: middle };
|
|
24232
24351
|
}
|
|
24233
24352
|
_private__createPrimitive() {
|
|
24234
24353
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -24259,7 +24378,7 @@
|
|
|
24259
24378
|
return new VerticalLinePaneView(this);
|
|
24260
24379
|
}
|
|
24261
24380
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
24262
|
-
if (this._private__vLineOptions.time === undefined)
|
|
24381
|
+
if (!this.isComplete() || this._private__vLineOptions.time === undefined)
|
|
24263
24382
|
return;
|
|
24264
24383
|
const x = (coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time) ?? 0) * horizontalPixelRatio;
|
|
24265
24384
|
const chartHeight = this._chart.chartElement().clientHeight * verticalPixelRatio;
|
|
@@ -24346,7 +24465,7 @@
|
|
|
24346
24465
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
24347
24466
|
}
|
|
24348
24467
|
hitTest(x, y) {
|
|
24349
|
-
if (this._private__vLineOptions.time === undefined) {
|
|
24468
|
+
if (!this.isComplete() || this._private__vLineOptions.time === undefined) {
|
|
24350
24469
|
return false;
|
|
24351
24470
|
}
|
|
24352
24471
|
const lineX = coordinateFromTime(this._chart, this._series, this._private__vLineOptions.time) ?? 0;
|
|
@@ -24416,6 +24535,7 @@
|
|
|
24416
24535
|
this._private__requestUpdate();
|
|
24417
24536
|
}
|
|
24418
24537
|
remove() {
|
|
24538
|
+
this._private__placement?._internal_stop();
|
|
24419
24539
|
if (this._private__primitive) {
|
|
24420
24540
|
this._series.detachPrimitive(this._private__primitive);
|
|
24421
24541
|
this._private__primitive = null;
|
|
@@ -25137,6 +25257,7 @@
|
|
|
25137
25257
|
this._private__isHovered = false;
|
|
25138
25258
|
this._private__isDragging = false;
|
|
25139
25259
|
this._private__dragTarget = null;
|
|
25260
|
+
this._private__placement = null;
|
|
25140
25261
|
this._private__fibOptions = {
|
|
25141
25262
|
levels: [
|
|
25142
25263
|
{ level: 0, color: '#787B86', label: '0%' },
|
|
@@ -25152,6 +25273,20 @@
|
|
|
25152
25273
|
...options,
|
|
25153
25274
|
};
|
|
25154
25275
|
this._private__createPrimitive();
|
|
25276
|
+
if (this._private__fibOptions.interactive) {
|
|
25277
|
+
this._private__placement = placeByClicks(this._chart, this._series, 3, (point, index) => {
|
|
25278
|
+
const placed = { time: point._internal_time, price: point._internal_price };
|
|
25279
|
+
if (index === 0) {
|
|
25280
|
+
this.setPoint1(placed);
|
|
25281
|
+
}
|
|
25282
|
+
else if (index === 1) {
|
|
25283
|
+
this.setPoint2(placed);
|
|
25284
|
+
}
|
|
25285
|
+
else {
|
|
25286
|
+
this.setPoint3(placed);
|
|
25287
|
+
}
|
|
25288
|
+
});
|
|
25289
|
+
}
|
|
25155
25290
|
}
|
|
25156
25291
|
_private__createPrimitive() {
|
|
25157
25292
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -25209,7 +25344,7 @@
|
|
|
25209
25344
|
this._private__requestUpdate();
|
|
25210
25345
|
}
|
|
25211
25346
|
isComplete() {
|
|
25212
|
-
return !!(this._private__fibOptions.point1 && this._private__fibOptions.point2 && this._private__fibOptions.point3);
|
|
25347
|
+
return !this._private__placement?._internal_pending() && !!(this._private__fibOptions.point1 && this._private__fibOptions.point2 && this._private__fibOptions.point3);
|
|
25213
25348
|
}
|
|
25214
25349
|
setColor(color) {
|
|
25215
25350
|
this._private__fibOptions.lineColor = color;
|
|
@@ -25504,6 +25639,7 @@
|
|
|
25504
25639
|
this._private__requestUpdate();
|
|
25505
25640
|
}
|
|
25506
25641
|
remove() {
|
|
25642
|
+
this._private__placement?._internal_stop();
|
|
25507
25643
|
if (this._private__primitive) {
|
|
25508
25644
|
this._series.detachPrimitive(this._private__primitive);
|
|
25509
25645
|
this._private__primitive = null;
|
|
@@ -28069,6 +28205,7 @@
|
|
|
28069
28205
|
this._private__moveStart = null;
|
|
28070
28206
|
this._private__isEditing = false;
|
|
28071
28207
|
this._private__clickOutsideHandler = null;
|
|
28208
|
+
this._private__placement = null;
|
|
28072
28209
|
this._private__textOptions = {
|
|
28073
28210
|
text: 'Double-click to edit',
|
|
28074
28211
|
fontSize: 14,
|
|
@@ -28089,6 +28226,14 @@
|
|
|
28089
28226
|
this._registerOptions(this._private__textOptions);
|
|
28090
28227
|
this._private__createPrimitive();
|
|
28091
28228
|
this._private__setupClickOutsideHandler();
|
|
28229
|
+
if (this._private__textOptions.interactive) {
|
|
28230
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => {
|
|
28231
|
+
this.setPosition(point._internal_time, point._internal_price);
|
|
28232
|
+
if (this._private__textOptions.onComplete) {
|
|
28233
|
+
this._private__textOptions.onComplete();
|
|
28234
|
+
}
|
|
28235
|
+
});
|
|
28236
|
+
}
|
|
28092
28237
|
}
|
|
28093
28238
|
_private__setupClickOutsideHandler() {
|
|
28094
28239
|
// Set up click handler to finish editing when clicking outside
|
|
@@ -28174,7 +28319,7 @@
|
|
|
28174
28319
|
this._private__requestUpdate();
|
|
28175
28320
|
}
|
|
28176
28321
|
isComplete() {
|
|
28177
|
-
return !!(this._private__textOptions.time && this._private__textOptions.price !== undefined);
|
|
28322
|
+
return !this._private__placement?._internal_pending() && !!(this._private__textOptions.time && this._private__textOptions.price !== undefined);
|
|
28178
28323
|
}
|
|
28179
28324
|
setColor(color) {
|
|
28180
28325
|
this._private__textOptions.textColor = color;
|
|
@@ -28457,6 +28602,7 @@
|
|
|
28457
28602
|
};
|
|
28458
28603
|
}
|
|
28459
28604
|
remove() {
|
|
28605
|
+
this._private__placement?._internal_stop();
|
|
28460
28606
|
// Clean up click handler
|
|
28461
28607
|
if (this._private__clickOutsideHandler) {
|
|
28462
28608
|
this._chart.unsubscribeClick(this._private__clickOutsideHandler);
|
|
@@ -29315,6 +29461,7 @@
|
|
|
29315
29461
|
this._private__paneView = null;
|
|
29316
29462
|
this._private__isSelected = false;
|
|
29317
29463
|
this._private__isHovered = false;
|
|
29464
|
+
this._private__placement = null;
|
|
29318
29465
|
this._private__isDragging = false;
|
|
29319
29466
|
this._private__dragTarget = null;
|
|
29320
29467
|
this._private__grab = null;
|
|
@@ -29337,6 +29484,32 @@
|
|
|
29337
29484
|
// Create primitive and setup
|
|
29338
29485
|
this._private__createPrimitive();
|
|
29339
29486
|
this._private__updateMetrics();
|
|
29487
|
+
if (this._private__positionOptions.interactive) {
|
|
29488
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
29489
|
+
}
|
|
29490
|
+
}
|
|
29491
|
+
_private__placeAt(point) {
|
|
29492
|
+
const options = this._private__positionOptions;
|
|
29493
|
+
const shift = point._internal_price - options.entryPrice;
|
|
29494
|
+
options.entryPrice = point._internal_price;
|
|
29495
|
+
options.entryTime = point._internal_time;
|
|
29496
|
+
if (options.stopLoss !== undefined) {
|
|
29497
|
+
options.stopLoss += shift;
|
|
29498
|
+
}
|
|
29499
|
+
if (options.takeProfit !== undefined) {
|
|
29500
|
+
options.takeProfit += shift;
|
|
29501
|
+
}
|
|
29502
|
+
options.endTime = timeFromCoordinate(this._chart, this._series, placedEndX(this._chart, point._internal_x)) ?? undefined;
|
|
29503
|
+
this._private__updateMetrics();
|
|
29504
|
+
this._private__requestUpdate();
|
|
29505
|
+
}
|
|
29506
|
+
isComplete() {
|
|
29507
|
+
return !this._private__placement?._internal_pending();
|
|
29508
|
+
}
|
|
29509
|
+
_private__span() {
|
|
29510
|
+
const entryX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.entryTime) ?? 0;
|
|
29511
|
+
const endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? entryX + defaultWidth(this._chart);
|
|
29512
|
+
return { _internal_entryX: entryX, _internal_endX: endX };
|
|
29340
29513
|
}
|
|
29341
29514
|
_private__createPrimitive() {
|
|
29342
29515
|
// Create and cache the paneView once
|
|
@@ -29368,6 +29541,9 @@
|
|
|
29368
29541
|
return new PositionPaneView(this);
|
|
29369
29542
|
}
|
|
29370
29543
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
29544
|
+
if (!this.isComplete()) {
|
|
29545
|
+
return;
|
|
29546
|
+
}
|
|
29371
29547
|
// Draw profit rectangle (green)
|
|
29372
29548
|
if (this._private__profitRect && this._private__positionOptions.takeProfit) {
|
|
29373
29549
|
const timeScale = this._chart.timeScale();
|
|
@@ -29401,16 +29577,9 @@
|
|
|
29401
29577
|
}
|
|
29402
29578
|
}
|
|
29403
29579
|
_private__drawRectangle(ctx, rect, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29404
|
-
const
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
if (this._private__positionOptions.endTime) {
|
|
29408
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29409
|
-
}
|
|
29410
|
-
else {
|
|
29411
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29412
|
-
endX = chartWidth;
|
|
29413
|
-
}
|
|
29580
|
+
const span = this._private__span();
|
|
29581
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29582
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29414
29583
|
const y1 = (this._series.priceToCoordinate(rect._internal_price1) ?? 0) * verticalPixelRatio;
|
|
29415
29584
|
const y2 = (this._series.priceToCoordinate(rect._internal_price2) ?? 0) * verticalPixelRatio;
|
|
29416
29585
|
// Draw filled rectangle with semi-transparent fill
|
|
@@ -29425,16 +29594,10 @@
|
|
|
29425
29594
|
ctx.stroke();
|
|
29426
29595
|
}
|
|
29427
29596
|
_private__drawEntryLine(ctx, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29428
|
-
const
|
|
29597
|
+
const span = this._private__span();
|
|
29598
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29599
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29429
29600
|
const entryY = (this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0) * verticalPixelRatio;
|
|
29430
|
-
let endX;
|
|
29431
|
-
if (this._private__positionOptions.endTime) {
|
|
29432
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29433
|
-
}
|
|
29434
|
-
else {
|
|
29435
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29436
|
-
endX = chartWidth;
|
|
29437
|
-
}
|
|
29438
29601
|
// Draw horizontal entry line (divider)
|
|
29439
29602
|
const lineColor = this._private__positionOptions.entryLineColor;
|
|
29440
29603
|
ctx.strokeStyle = lineColor;
|
|
@@ -29548,9 +29711,11 @@
|
|
|
29548
29711
|
const padding = 6 * horizontalPixelRatio;
|
|
29549
29712
|
const labelWidth = textMetrics.width + padding * 2;
|
|
29550
29713
|
const labelHeight = 20 * horizontalPixelRatio;
|
|
29551
|
-
//
|
|
29714
|
+
// Outside the box, so a label wider than it does not cover the handles on its edge
|
|
29715
|
+
const entryY = (this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0) * verticalPixelRatio;
|
|
29716
|
+
const gap = 3 * verticalPixelRatio;
|
|
29552
29717
|
const labelX = entryX + 8 * horizontalPixelRatio;
|
|
29553
|
-
const labelY = y - labelHeight
|
|
29718
|
+
const labelY = y <= entryY ? y - labelHeight - gap : y + gap;
|
|
29554
29719
|
// Draw label background
|
|
29555
29720
|
ctx.fillStyle = rect._internal_color;
|
|
29556
29721
|
ctx.fillRect(labelX, labelY, labelWidth, labelHeight);
|
|
@@ -29558,10 +29723,12 @@
|
|
|
29558
29723
|
ctx.fillStyle = '#ffffff';
|
|
29559
29724
|
ctx.textAlign = 'left';
|
|
29560
29725
|
ctx.textBaseline = 'middle';
|
|
29561
|
-
ctx.fillText(labelText, labelX + padding,
|
|
29726
|
+
ctx.fillText(labelText, labelX + padding, labelY + labelHeight / 2);
|
|
29562
29727
|
}
|
|
29563
29728
|
_private__drawEndpoint(ctx, price, color, horizontalPixelRatio, verticalPixelRatio, timeScale) {
|
|
29564
|
-
const
|
|
29729
|
+
const span = this._private__span();
|
|
29730
|
+
const entryX = span._internal_entryX * horizontalPixelRatio;
|
|
29731
|
+
const endX = span._internal_endX * horizontalPixelRatio;
|
|
29565
29732
|
const y = (this._series.priceToCoordinate(price) ?? 0) * verticalPixelRatio;
|
|
29566
29733
|
// Draw circle endpoint at entry
|
|
29567
29734
|
const circleColor = color;
|
|
@@ -29573,14 +29740,6 @@
|
|
|
29573
29740
|
ctx.fill();
|
|
29574
29741
|
ctx.stroke();
|
|
29575
29742
|
// Draw square endpoint at the right edge
|
|
29576
|
-
let endX;
|
|
29577
|
-
if (this._private__positionOptions.endTime) {
|
|
29578
|
-
endX = (coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0) * horizontalPixelRatio;
|
|
29579
|
-
}
|
|
29580
|
-
else {
|
|
29581
|
-
const chartWidth = this._chart.chartElement().clientWidth * horizontalPixelRatio;
|
|
29582
|
-
endX = chartWidth - 10 * horizontalPixelRatio;
|
|
29583
|
-
}
|
|
29584
29743
|
const size = 8 * horizontalPixelRatio;
|
|
29585
29744
|
const squareColor = color;
|
|
29586
29745
|
ctx.fillStyle = squareColor;
|
|
@@ -29701,18 +29860,12 @@
|
|
|
29701
29860
|
return this.hitTest(x, y) ? toolHoveredItem(this.id, 'body', false) : null;
|
|
29702
29861
|
}
|
|
29703
29862
|
hitTest(x, y) {
|
|
29704
|
-
if (!this._private__positionOptions.stopLoss && !this._private__positionOptions.takeProfit) {
|
|
29863
|
+
if (!this.isComplete() || (!this._private__positionOptions.stopLoss && !this._private__positionOptions.takeProfit)) {
|
|
29705
29864
|
return false;
|
|
29706
29865
|
}
|
|
29707
|
-
const
|
|
29708
|
-
|
|
29709
|
-
|
|
29710
|
-
endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0;
|
|
29711
|
-
}
|
|
29712
|
-
else {
|
|
29713
|
-
const chartWidth = this._chart.chartElement().clientWidth;
|
|
29714
|
-
endX = chartWidth;
|
|
29715
|
-
}
|
|
29866
|
+
const { _internal_entryX: entryX, _internal_endX: endX } = this._private__span();
|
|
29867
|
+
const left = Math.min(entryX, endX);
|
|
29868
|
+
const right = Math.max(entryX, endX);
|
|
29716
29869
|
// Check if inside the entire Position Tool area (rectangles)
|
|
29717
29870
|
if (this._private__positionOptions.takeProfit && this._private__positionOptions.stopLoss) {
|
|
29718
29871
|
const tpY = this._series.priceToCoordinate(this._private__positionOptions.takeProfit) ?? 0;
|
|
@@ -29720,7 +29873,7 @@
|
|
|
29720
29873
|
const minY = Math.min(tpY, slY);
|
|
29721
29874
|
const maxY = Math.max(tpY, slY);
|
|
29722
29875
|
// Check if inside the rectangle bounds (entire tool area)
|
|
29723
|
-
if (x >=
|
|
29876
|
+
if (x >= left && x <= right && y >= minY && y <= maxY) {
|
|
29724
29877
|
return true;
|
|
29725
29878
|
}
|
|
29726
29879
|
// Also check entry line area
|
|
@@ -29732,15 +29885,12 @@
|
|
|
29732
29885
|
return false;
|
|
29733
29886
|
}
|
|
29734
29887
|
hitTestEndpoint(x, y) {
|
|
29735
|
-
|
|
29736
|
-
|
|
29737
|
-
if (this._private__positionOptions.endTime) {
|
|
29738
|
-
endX = coordinateFromTime(this._chart, this._series, this._private__positionOptions.endTime) ?? 0;
|
|
29739
|
-
}
|
|
29740
|
-
else {
|
|
29741
|
-
const chartWidth = this._chart.chartElement().clientWidth;
|
|
29742
|
-
endX = chartWidth;
|
|
29888
|
+
if (!this.isComplete()) {
|
|
29889
|
+
return null;
|
|
29743
29890
|
}
|
|
29891
|
+
const { _internal_entryX: entryX, _internal_endX: endX } = this._private__span();
|
|
29892
|
+
const left = Math.min(entryX, endX);
|
|
29893
|
+
const right = Math.max(entryX, endX);
|
|
29744
29894
|
const tolerance = 10;
|
|
29745
29895
|
// Check TP left endpoint (circle)
|
|
29746
29896
|
if (this._private__positionOptions.takeProfit) {
|
|
@@ -29777,7 +29927,7 @@
|
|
|
29777
29927
|
// Check entry line (middle divider line) - higher priority than 'move'
|
|
29778
29928
|
const entryY = this._series.priceToCoordinate(this._private__positionOptions.entryPrice) ?? 0;
|
|
29779
29929
|
const lineTolerance = 8;
|
|
29780
|
-
if (x >=
|
|
29930
|
+
if (x >= left && x <= right && Math.abs(y - entryY) <= lineTolerance) {
|
|
29781
29931
|
return 'entry';
|
|
29782
29932
|
}
|
|
29783
29933
|
// Check if clicking on the body (rectangles) for moving entire tool
|
|
@@ -29787,7 +29937,7 @@
|
|
|
29787
29937
|
const minY = Math.min(tpY, slY);
|
|
29788
29938
|
const maxY = Math.max(tpY, slY);
|
|
29789
29939
|
// Check if inside the rectangle bounds
|
|
29790
|
-
if (x >=
|
|
29940
|
+
if (x >= left && x <= right && y >= minY && y <= maxY) {
|
|
29791
29941
|
return 'move';
|
|
29792
29942
|
}
|
|
29793
29943
|
}
|
|
@@ -29887,6 +30037,7 @@
|
|
|
29887
30037
|
this._private__requestUpdate();
|
|
29888
30038
|
}
|
|
29889
30039
|
remove() {
|
|
30040
|
+
this._private__placement?._internal_stop();
|
|
29890
30041
|
if (this._private__primitive) {
|
|
29891
30042
|
this._series.detachPrimitive(this._private__primitive);
|
|
29892
30043
|
this._private__primitive = null;
|
|
@@ -29933,6 +30084,7 @@
|
|
|
29933
30084
|
}
|
|
29934
30085
|
}
|
|
29935
30086
|
|
|
30087
|
+
const TOP_PADDING = 50;
|
|
29936
30088
|
class GanttTool extends DrawingToolBase {
|
|
29937
30089
|
constructor(context, options) {
|
|
29938
30090
|
super(context, 'gantt', options);
|
|
@@ -29946,6 +30098,7 @@
|
|
|
29946
30098
|
this._private__grab = null;
|
|
29947
30099
|
this._private__moveStart = null;
|
|
29948
30100
|
this._private__hoveredSegmentIndex = -1;
|
|
30101
|
+
this._private__placement = null;
|
|
29949
30102
|
this._private__ganttOptions = {
|
|
29950
30103
|
segments: [],
|
|
29951
30104
|
rowHeight: 40,
|
|
@@ -29958,6 +30111,43 @@
|
|
|
29958
30111
|
};
|
|
29959
30112
|
this._registerOptions(this._private__ganttOptions);
|
|
29960
30113
|
this._private__createPrimitive();
|
|
30114
|
+
if (this._private__ganttOptions.interactive) {
|
|
30115
|
+
this._private__placement = placeByClicks(this._chart, this._series, 1, (point) => this._private__placeAt(point));
|
|
30116
|
+
}
|
|
30117
|
+
}
|
|
30118
|
+
_private__placeAt(point) {
|
|
30119
|
+
const segments = this._private__ganttOptions.segments ?? [];
|
|
30120
|
+
const endTime = timeFromCoordinate(this._chart, this._series, placedEndX(this._chart, point._internal_x)) ?? point._internal_time;
|
|
30121
|
+
const rowPitch = this._private__ganttOptions.rowHeight + this._private__ganttOptions.rowSpacing;
|
|
30122
|
+
const row = Math.max(0, Math.floor((point._internal_y - TOP_PADDING) / rowPitch));
|
|
30123
|
+
const shift = segments.length > 0 ? row - segments[0].level : 0;
|
|
30124
|
+
for (const segment of segments) {
|
|
30125
|
+
segment.startTime = point._internal_time;
|
|
30126
|
+
segment.endTime = endTime;
|
|
30127
|
+
segment.level = Math.max(0, segment.level + shift);
|
|
30128
|
+
}
|
|
30129
|
+
this._private__requestUpdate();
|
|
30130
|
+
}
|
|
30131
|
+
isComplete() {
|
|
30132
|
+
return !this._private__placement?._internal_pending();
|
|
30133
|
+
}
|
|
30134
|
+
selectionBox() {
|
|
30135
|
+
const segments = this._private__ganttOptions.segments ?? [];
|
|
30136
|
+
if (segments.length === 0) {
|
|
30137
|
+
return null;
|
|
30138
|
+
}
|
|
30139
|
+
const rowHeight = this._private__ganttOptions.rowHeight;
|
|
30140
|
+
const pitch = rowHeight + this._private__ganttOptions.rowSpacing;
|
|
30141
|
+
// Typed as the public shape: an inferred one gets its keys renamed by the build
|
|
30142
|
+
const box = { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity };
|
|
30143
|
+
for (const segment of segments) {
|
|
30144
|
+
const top = TOP_PADDING + segment.level * pitch;
|
|
30145
|
+
box.left = Math.min(box.left, coordinateFromTime(this._chart, this._series, segment.startTime) ?? 0);
|
|
30146
|
+
box.right = Math.max(box.right, coordinateFromTime(this._chart, this._series, segment.endTime) ?? 0);
|
|
30147
|
+
box.top = Math.min(box.top, top);
|
|
30148
|
+
box.bottom = Math.max(box.bottom, top + rowHeight);
|
|
30149
|
+
}
|
|
30150
|
+
return box;
|
|
29961
30151
|
}
|
|
29962
30152
|
_private__createPrimitive() {
|
|
29963
30153
|
this._private__paneView = this._private__createPaneView();
|
|
@@ -29988,11 +30178,10 @@
|
|
|
29988
30178
|
return new GanttPaneView(this);
|
|
29989
30179
|
}
|
|
29990
30180
|
drawToCanvas(ctx, horizontalPixelRatio, verticalPixelRatio) {
|
|
29991
|
-
if (!this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0)
|
|
30181
|
+
if (!this.isComplete() || !this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0)
|
|
29992
30182
|
return;
|
|
29993
30183
|
// Position gantt at top of chart with padding
|
|
29994
|
-
const
|
|
29995
|
-
const baseY = topPadding * verticalPixelRatio;
|
|
30184
|
+
const baseY = TOP_PADDING * verticalPixelRatio;
|
|
29996
30185
|
const rowHeight = this._private__ganttOptions.rowHeight * verticalPixelRatio;
|
|
29997
30186
|
const rowSpacing = this._private__ganttOptions.rowSpacing * verticalPixelRatio;
|
|
29998
30187
|
// Draw grid lines if enabled
|
|
@@ -30171,11 +30360,10 @@
|
|
|
30171
30360
|
this._private__moveStart = null;
|
|
30172
30361
|
}
|
|
30173
30362
|
hitTest(x, y) {
|
|
30174
|
-
if (!this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0) {
|
|
30363
|
+
if (!this.isComplete() || !this._private__ganttOptions.segments || this._private__ganttOptions.segments.length === 0) {
|
|
30175
30364
|
return false;
|
|
30176
30365
|
}
|
|
30177
|
-
const
|
|
30178
|
-
const baseY = topPadding;
|
|
30366
|
+
const baseY = TOP_PADDING;
|
|
30179
30367
|
const rowHeight = this._private__ganttOptions.rowHeight;
|
|
30180
30368
|
const rowSpacing = this._private__ganttOptions.rowSpacing;
|
|
30181
30369
|
// Check each segment
|
|
@@ -30229,6 +30417,7 @@
|
|
|
30229
30417
|
this._private__requestUpdate();
|
|
30230
30418
|
}
|
|
30231
30419
|
remove() {
|
|
30420
|
+
this._private__placement?._internal_stop();
|
|
30232
30421
|
if (this._private__primitive) {
|
|
30233
30422
|
this._series.detachPrimitive(this._private__primitive);
|
|
30234
30423
|
this._private__primitive = null;
|
|
@@ -30364,6 +30553,7 @@
|
|
|
30364
30553
|
}
|
|
30365
30554
|
this._private__completionCheck = setTimeout(() => {
|
|
30366
30555
|
this._private__completionCheck = null;
|
|
30556
|
+
const completed = [];
|
|
30367
30557
|
for (const id of Array.from(this._private__pendingToolIds)) {
|
|
30368
30558
|
const tool = this._private__tools.get(id);
|
|
30369
30559
|
if (!tool) {
|
|
@@ -30372,9 +30562,15 @@
|
|
|
30372
30562
|
}
|
|
30373
30563
|
if (tool.isComplete()) {
|
|
30374
30564
|
this._private__pendingToolIds.delete(id);
|
|
30375
|
-
|
|
30565
|
+
completed.push(id);
|
|
30376
30566
|
}
|
|
30377
30567
|
}
|
|
30568
|
+
if (completed.length > 0) {
|
|
30569
|
+
this.recordChange();
|
|
30570
|
+
}
|
|
30571
|
+
for (const id of completed) {
|
|
30572
|
+
this._private__drawingCompleted._internal_fire(id);
|
|
30573
|
+
}
|
|
30378
30574
|
}, 0);
|
|
30379
30575
|
}
|
|
30380
30576
|
/**
|
|
@@ -30434,12 +30630,16 @@
|
|
|
30434
30630
|
if (this._private__restoring) {
|
|
30435
30631
|
return;
|
|
30436
30632
|
}
|
|
30633
|
+
const next = this.serializeAll();
|
|
30634
|
+
if (JSON.stringify(next) === JSON.stringify(this._private__committed)) {
|
|
30635
|
+
return;
|
|
30636
|
+
}
|
|
30437
30637
|
this._private__past.push(this._private__committed);
|
|
30438
30638
|
if (this._private__past.length > UNDO_HISTORY_LIMIT) {
|
|
30439
30639
|
this._private__past.shift();
|
|
30440
30640
|
}
|
|
30441
30641
|
this._private__future = [];
|
|
30442
|
-
this._private__committed =
|
|
30642
|
+
this._private__committed = next;
|
|
30443
30643
|
}
|
|
30444
30644
|
canUndo() {
|
|
30445
30645
|
return this._private__past.length > 0;
|
|
@@ -30495,11 +30695,25 @@
|
|
|
30495
30695
|
const tool = this._private__tools.get(this._private__selectedToolId);
|
|
30496
30696
|
return tool ? this._private__boundsOf(tool) : null;
|
|
30497
30697
|
}
|
|
30698
|
+
/** Relative to the chart element; the tool's box is relative to its pane. */
|
|
30699
|
+
_private__boundsOf(tool) {
|
|
30700
|
+
const box = tool.selectionBox() ?? this._private__boxFromPoints(tool);
|
|
30701
|
+
if (box === null) {
|
|
30702
|
+
return null;
|
|
30703
|
+
}
|
|
30704
|
+
const offset = this._private__paneOffsetOf(tool);
|
|
30705
|
+
return {
|
|
30706
|
+
left: box.left + offset._internal_x,
|
|
30707
|
+
right: box.right + offset._internal_x,
|
|
30708
|
+
top: box.top + offset._internal_y,
|
|
30709
|
+
bottom: box.bottom + offset._internal_y,
|
|
30710
|
+
};
|
|
30711
|
+
}
|
|
30498
30712
|
/**
|
|
30499
30713
|
* Bounds come from the tool's own serialized points, so this works for every
|
|
30500
30714
|
* tool without each one having to report a box.
|
|
30501
30715
|
*/
|
|
30502
|
-
|
|
30716
|
+
_private__boxFromPoints(tool) {
|
|
30503
30717
|
const series = tool.series();
|
|
30504
30718
|
const points = tool.serialize().points;
|
|
30505
30719
|
let left = Number.POSITIVE_INFINITY;
|
|
@@ -30522,13 +30736,7 @@
|
|
|
30522
30736
|
if (!found) {
|
|
30523
30737
|
return null;
|
|
30524
30738
|
}
|
|
30525
|
-
|
|
30526
|
-
return {
|
|
30527
|
-
left: left + offset._internal_x,
|
|
30528
|
-
right: right + offset._internal_x,
|
|
30529
|
-
top: top + offset._internal_y,
|
|
30530
|
-
bottom: bottom + offset._internal_y,
|
|
30531
|
-
};
|
|
30739
|
+
return { left, top, right, bottom };
|
|
30532
30740
|
}
|
|
30533
30741
|
/** Panes below the first one are offset inside the chart element. */
|
|
30534
30742
|
_private__paneOffsetOf(tool) {
|
|
@@ -30612,7 +30820,10 @@
|
|
|
30612
30820
|
serializeAll() {
|
|
30613
30821
|
const result = [];
|
|
30614
30822
|
for (const tool of this._private__tools.values()) {
|
|
30615
|
-
|
|
30823
|
+
// Not drawn yet: undo would bring it back as a finished drawing
|
|
30824
|
+
if (tool.isComplete()) {
|
|
30825
|
+
result.push(tool.serialize());
|
|
30826
|
+
}
|
|
30616
30827
|
}
|
|
30617
30828
|
return result;
|
|
30618
30829
|
}
|
|
@@ -31237,7 +31448,7 @@
|
|
|
31237
31448
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
31238
31449
|
*/
|
|
31239
31450
|
function version() {
|
|
31240
|
-
return "2.3.
|
|
31451
|
+
return "2.3.15";
|
|
31241
31452
|
}
|
|
31242
31453
|
|
|
31243
31454
|
var PipsendChartsModule = /*#__PURE__*/Object.freeze({
|