@pipsend/charts 2.3.0 → 2.3.2
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 +243 -18
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +243 -18
- package/dist/pipsend-charts.standalone.development.mjs +243 -18
- package/dist/pipsend-charts.standalone.production.js +2 -2
- package/dist/pipsend-charts.standalone.production.mjs +2 -2
- package/dist/typings.d.ts +26 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v2.3.
|
|
3
|
+
* Pipsend Charts v2.3.2
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -19744,6 +19744,8 @@ class TradingLineController {
|
|
|
19744
19744
|
this._private__pointerId = null;
|
|
19745
19745
|
this._private__pressOrigin = null;
|
|
19746
19746
|
this._private__pressedLine = null;
|
|
19747
|
+
/** Distance from the pointer to the dragged line when the press landed. */
|
|
19748
|
+
this._private__grabOffset = 0;
|
|
19747
19749
|
/** Latest pointer position in pane coordinates, or null when off the panes. */
|
|
19748
19750
|
this._private__point = null;
|
|
19749
19751
|
this._private__paneIndex = undefined;
|
|
@@ -19821,6 +19823,7 @@ class TradingLineController {
|
|
|
19821
19823
|
this._private__pointerId = event.pointerId;
|
|
19822
19824
|
this._private__element.setPointerCapture(event.pointerId);
|
|
19823
19825
|
line.beginDrag();
|
|
19826
|
+
this._private__grabOffset = this._private__measureGrabOffset(line, event);
|
|
19824
19827
|
this._private__applyCursor();
|
|
19825
19828
|
event.preventDefault();
|
|
19826
19829
|
event.stopPropagation();
|
|
@@ -19855,6 +19858,7 @@ class TradingLineController {
|
|
|
19855
19858
|
Math.abs(event.clientY - origin._internal_y) > CLICK_TOLERANCE_PX);
|
|
19856
19859
|
if (dragged !== null) {
|
|
19857
19860
|
this._private__dragging = null;
|
|
19861
|
+
this._private__grabOffset = 0;
|
|
19858
19862
|
if (moved) {
|
|
19859
19863
|
dragged.commitDrag();
|
|
19860
19864
|
}
|
|
@@ -19882,6 +19886,7 @@ class TradingLineController {
|
|
|
19882
19886
|
}
|
|
19883
19887
|
const line = this._private__dragging;
|
|
19884
19888
|
this._private__dragging = null;
|
|
19889
|
+
this._private__grabOffset = 0;
|
|
19885
19890
|
this._private__releasePointer();
|
|
19886
19891
|
line.cancelDrag();
|
|
19887
19892
|
this._private__applyCursor();
|
|
@@ -19911,16 +19916,38 @@ class TradingLineController {
|
|
|
19911
19916
|
// as the pointer leaves the pane canvas — over the price axis, past the
|
|
19912
19917
|
// chart's edge — and a drag driven from it freezes there while the user
|
|
19913
19918
|
// is still moving.
|
|
19919
|
+
const paneY = this._private__paneY(line, event);
|
|
19920
|
+
return paneY === null ? null : line.priceAt(paneY - this._private__grabOffset);
|
|
19921
|
+
}
|
|
19922
|
+
/** The pointer's position inside the line's pane, in pane coordinates. */
|
|
19923
|
+
_private__paneY(line, event) {
|
|
19914
19924
|
const pane = this._private__chart.panes()[line.paneIndex()];
|
|
19915
19925
|
const paneElement = pane ? pane.getHTMLElement() : null;
|
|
19916
19926
|
if (paneElement) {
|
|
19917
|
-
return
|
|
19927
|
+
return event.clientY - paneElement.getBoundingClientRect().top;
|
|
19918
19928
|
}
|
|
19919
19929
|
if (this._private__point !== null && this._private__paneIndex === line.paneIndex()) {
|
|
19920
|
-
return
|
|
19930
|
+
return this._private__point._internal_y;
|
|
19921
19931
|
}
|
|
19922
19932
|
return null;
|
|
19923
19933
|
}
|
|
19934
|
+
/**
|
|
19935
|
+
* Keeps the grab point: a line picked up by the edge of its label moves with
|
|
19936
|
+
* the pointer rather than centring itself on it. Ignored past a sane
|
|
19937
|
+
* distance, so a bad reading cannot send the line off on the first move.
|
|
19938
|
+
*/
|
|
19939
|
+
_private__measureGrabOffset(line, event) {
|
|
19940
|
+
if (!line.dragAnchorY) {
|
|
19941
|
+
return 0;
|
|
19942
|
+
}
|
|
19943
|
+
const anchor = line.dragAnchorY();
|
|
19944
|
+
const paneY = this._private__paneY(line, event);
|
|
19945
|
+
if (anchor === null || paneY === null) {
|
|
19946
|
+
return 0;
|
|
19947
|
+
}
|
|
19948
|
+
const offset = paneY - anchor;
|
|
19949
|
+
return Math.abs(offset) > 40 /* Constants.MaxGrabOffsetPx */ ? 0 : offset;
|
|
19950
|
+
}
|
|
19924
19951
|
/**
|
|
19925
19952
|
* Hit ids are either a bare line id or `id#part`, which is how a line with
|
|
19926
19953
|
* several targets reports which one was hit.
|
|
@@ -20476,6 +20503,126 @@ function createInteractiveLineManager(chart, series) {
|
|
|
20476
20503
|
return new InteractiveLineManager(chart, series);
|
|
20477
20504
|
}
|
|
20478
20505
|
|
|
20506
|
+
/**
|
|
20507
|
+
* Fans out labels that land on top of each other.
|
|
20508
|
+
*
|
|
20509
|
+
* Every position line on a chart shares one of these. Two positions opened at
|
|
20510
|
+
* the same price draw their labels at the same coordinate, and the one behind
|
|
20511
|
+
* becomes unreachable — the engine resolves the hit to whichever primitive it
|
|
20512
|
+
* reaches first, and that is always the same one. Nudging each collision down
|
|
20513
|
+
* leaves every label a strip of its own to be grabbed by.
|
|
20514
|
+
*
|
|
20515
|
+
* The line itself never moves: it stays at the price it belongs to, and only
|
|
20516
|
+
* the label is offset.
|
|
20517
|
+
*/
|
|
20518
|
+
class PositionLineLabelLayout {
|
|
20519
|
+
constructor() {
|
|
20520
|
+
/** Registration order. It is what keeps the fan from reshuffling per frame. */
|
|
20521
|
+
this._private__order = [];
|
|
20522
|
+
this._private__claims = new Map();
|
|
20523
|
+
this._private__offsets = new Map();
|
|
20524
|
+
this._private__invalidated = true;
|
|
20525
|
+
}
|
|
20526
|
+
_internal_register(ownerId) {
|
|
20527
|
+
if (!this._private__claims.has(ownerId)) {
|
|
20528
|
+
this._private__order.push(ownerId);
|
|
20529
|
+
this._private__claims.set(ownerId, []);
|
|
20530
|
+
this._private__invalidated = true;
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20533
|
+
_internal_unregister(ownerId) {
|
|
20534
|
+
const index = this._private__order.indexOf(ownerId);
|
|
20535
|
+
if (index !== -1) {
|
|
20536
|
+
this._private__order.splice(index, 1);
|
|
20537
|
+
}
|
|
20538
|
+
this._private__claims.delete(ownerId);
|
|
20539
|
+
this._private__invalidated = true;
|
|
20540
|
+
}
|
|
20541
|
+
_internal_isEmpty() {
|
|
20542
|
+
return this._private__order.length === 0;
|
|
20543
|
+
}
|
|
20544
|
+
/**
|
|
20545
|
+
* Publishes where an owner's labels want to sit. Called while each line
|
|
20546
|
+
* rebuilds its renderer data, so a fan can be one frame behind while prices
|
|
20547
|
+
* move — which is invisible, and cheaper than forcing a second pass.
|
|
20548
|
+
*/
|
|
20549
|
+
_internal_setClaims(ownerId, claims) {
|
|
20550
|
+
this._private__claims.set(ownerId, claims);
|
|
20551
|
+
this._private__invalidated = true;
|
|
20552
|
+
}
|
|
20553
|
+
/** How far down a label has to move to clear the ones already placed. */
|
|
20554
|
+
_internal_offsetFor(ownerId, level) {
|
|
20555
|
+
if (this._private__invalidated) {
|
|
20556
|
+
this._private__recalculate();
|
|
20557
|
+
}
|
|
20558
|
+
return this._private__offsets.get(key(ownerId, level)) ?? 0;
|
|
20559
|
+
}
|
|
20560
|
+
_private__recalculate() {
|
|
20561
|
+
const offsets = new Map();
|
|
20562
|
+
const placed = [];
|
|
20563
|
+
for (const ownerId of this._private__order) {
|
|
20564
|
+
for (const claim of this._private__claims.get(ownerId) ?? []) {
|
|
20565
|
+
const gap = minGap(claim._internal_height);
|
|
20566
|
+
const maxOffset = claim._internal_height;
|
|
20567
|
+
// Moved down to the first coordinate that clears everything already
|
|
20568
|
+
// placed, and no further. Two levels whose own prices nearly part
|
|
20569
|
+
// them only need the few pixels they are short of — stepping by a
|
|
20570
|
+
// full gap each time is what made the fan look flung open.
|
|
20571
|
+
let y = claim._internal_y;
|
|
20572
|
+
for (const other of [...placed].sort(byY)) {
|
|
20573
|
+
if (Math.abs(y - other._internal_y) < gap) {
|
|
20574
|
+
y = other._internal_y + gap;
|
|
20575
|
+
}
|
|
20576
|
+
}
|
|
20577
|
+
let offset = y - claim._internal_y;
|
|
20578
|
+
if (offset > maxOffset) {
|
|
20579
|
+
// More labels than there is room to fan. The rest stack, which is
|
|
20580
|
+
// no worse than before and keeps the pile from running off.
|
|
20581
|
+
offset = 0;
|
|
20582
|
+
}
|
|
20583
|
+
placed.push({ _internal_y: claim._internal_y + offset, _internal_height: claim._internal_height });
|
|
20584
|
+
offsets.set(key(ownerId, claim._internal_level), offset);
|
|
20585
|
+
}
|
|
20586
|
+
}
|
|
20587
|
+
this._private__offsets = offsets;
|
|
20588
|
+
this._private__invalidated = false;
|
|
20589
|
+
}
|
|
20590
|
+
}
|
|
20591
|
+
function key(ownerId, level) {
|
|
20592
|
+
return `${ownerId}:${level}`;
|
|
20593
|
+
}
|
|
20594
|
+
/**
|
|
20595
|
+
* The strip a label keeps to itself. Comfortably clickable, and no wider —
|
|
20596
|
+
* every pixel here is a pixel the label sits away from its own line.
|
|
20597
|
+
*/
|
|
20598
|
+
function minGap(height) {
|
|
20599
|
+
return Math.max(9, Math.round(height * 0.4));
|
|
20600
|
+
}
|
|
20601
|
+
function byY(a, b) {
|
|
20602
|
+
return a._internal_y - b._internal_y;
|
|
20603
|
+
}
|
|
20604
|
+
const layouts = new WeakMap();
|
|
20605
|
+
/** The layout is shared by every position line on the same chart. */
|
|
20606
|
+
function acquireLabelLayout(chart, ownerId) {
|
|
20607
|
+
let layout = layouts.get(chart);
|
|
20608
|
+
if (!layout) {
|
|
20609
|
+
layout = new PositionLineLabelLayout();
|
|
20610
|
+
layouts.set(chart, layout);
|
|
20611
|
+
}
|
|
20612
|
+
layout._internal_register(ownerId);
|
|
20613
|
+
return layout;
|
|
20614
|
+
}
|
|
20615
|
+
function releaseLabelLayout(chart, ownerId) {
|
|
20616
|
+
const layout = layouts.get(chart);
|
|
20617
|
+
if (!layout) {
|
|
20618
|
+
return;
|
|
20619
|
+
}
|
|
20620
|
+
layout._internal_unregister(ownerId);
|
|
20621
|
+
if (layout._internal_isEmpty()) {
|
|
20622
|
+
layouts.delete(chart);
|
|
20623
|
+
}
|
|
20624
|
+
}
|
|
20625
|
+
|
|
20479
20626
|
const positionLineDefaultColors = {
|
|
20480
20627
|
entry: '#2962FF',
|
|
20481
20628
|
takeProfit: '#26A17B',
|
|
@@ -20508,12 +20655,12 @@ class PositionLineRenderer {
|
|
|
20508
20655
|
// line, so the narrowest target is tested first.
|
|
20509
20656
|
for (const layout of this._private__layouts) {
|
|
20510
20657
|
if (layout._internal_closable && x >= layout._internal_closeLeft && x <= layout._internal_closeRight &&
|
|
20511
|
-
Math.abs(y - layout.
|
|
20658
|
+
Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
|
|
20512
20659
|
return { _internal_level: layout._internal_level, _internal_part: 'close' };
|
|
20513
20660
|
}
|
|
20514
20661
|
}
|
|
20515
20662
|
for (const layout of this._private__layouts) {
|
|
20516
|
-
if (x >= layout._internal_pillLeft && x <= layout._internal_pillRight && Math.abs(y - layout.
|
|
20663
|
+
if (x >= layout._internal_pillLeft && x <= layout._internal_pillRight && Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
|
|
20517
20664
|
return { _internal_level: layout._internal_level, _internal_part: 'body' };
|
|
20518
20665
|
}
|
|
20519
20666
|
}
|
|
@@ -20563,7 +20710,8 @@ class PositionLineRenderer {
|
|
|
20563
20710
|
const pillWidth = badgeWidth + labelWidth + closeWidth;
|
|
20564
20711
|
const pillRight = Math.max(pillWidth, lineEnd - 8 /* Constants.LabelGap */);
|
|
20565
20712
|
const pillLeft = pillRight - pillWidth;
|
|
20566
|
-
const
|
|
20713
|
+
const labelY = level._internal_y + level._internal_labelOffsetY;
|
|
20714
|
+
const top = labelY - height / 2;
|
|
20567
20715
|
this._private__drawLineSegments(scope, level, pillLeft, pillRight, lineEnd);
|
|
20568
20716
|
this._private__drawPill(scope, data, level, { _internal_left: pillLeft, _internal_top: top, _internal_width: pillWidth, _internal_height: height });
|
|
20569
20717
|
let cellLeft = pillLeft;
|
|
@@ -20576,7 +20724,7 @@ class PositionLineRenderer {
|
|
|
20576
20724
|
ctx.scale(hpr, vpr);
|
|
20577
20725
|
ctx.textAlign = 'center';
|
|
20578
20726
|
ctx.fillStyle = data._internal_textColor ?? level._internal_color;
|
|
20579
|
-
ctx.fillText(level._internal_text, cellLeft + labelWidth / 2,
|
|
20727
|
+
ctx.fillText(level._internal_text, cellLeft + labelWidth / 2, labelY);
|
|
20580
20728
|
ctx.restore();
|
|
20581
20729
|
cellLeft += labelWidth;
|
|
20582
20730
|
if (level._internal_closable) {
|
|
@@ -20586,6 +20734,7 @@ class PositionLineRenderer {
|
|
|
20586
20734
|
return {
|
|
20587
20735
|
_internal_level: level._internal_level,
|
|
20588
20736
|
_internal_y: level._internal_y,
|
|
20737
|
+
_internal_labelY: labelY,
|
|
20589
20738
|
_internal_height: height,
|
|
20590
20739
|
_internal_pillLeft: pillLeft,
|
|
20591
20740
|
_internal_pillRight: pillRight,
|
|
@@ -20604,12 +20753,20 @@ class PositionLineRenderer {
|
|
|
20604
20753
|
ctx.lineWidth = lineWidth;
|
|
20605
20754
|
setLineStyle(ctx, level._internal_lineStyle);
|
|
20606
20755
|
ctx.beginPath();
|
|
20607
|
-
|
|
20608
|
-
|
|
20609
|
-
|
|
20610
|
-
ctx.moveTo(
|
|
20756
|
+
if (level._internal_labelOffsetY !== 0) {
|
|
20757
|
+
// The label has been fanned off its line, so breaking the line for it
|
|
20758
|
+
// would leave a gap with nothing in it.
|
|
20759
|
+
ctx.moveTo(0, y);
|
|
20611
20760
|
ctx.lineTo(Math.round(lineEnd * hpr), y);
|
|
20612
20761
|
}
|
|
20762
|
+
else {
|
|
20763
|
+
ctx.moveTo(0, y);
|
|
20764
|
+
ctx.lineTo(Math.round(Math.max(0, pillLeft - 8 /* Constants.LabelGap */) * hpr), y);
|
|
20765
|
+
if (lineEnd > pillRight + 8 /* Constants.LabelGap */) {
|
|
20766
|
+
ctx.moveTo(Math.round((pillRight + 8 /* Constants.LabelGap */) * hpr), y);
|
|
20767
|
+
ctx.lineTo(Math.round(lineEnd * hpr), y);
|
|
20768
|
+
}
|
|
20769
|
+
}
|
|
20613
20770
|
ctx.stroke();
|
|
20614
20771
|
ctx.restore();
|
|
20615
20772
|
}
|
|
@@ -20804,6 +20961,7 @@ class PositionLine {
|
|
|
20804
20961
|
this._private__theme = { ...positionLineThemeDefaults, ...options.theme };
|
|
20805
20962
|
this._private__paneViews = [this._private__paneView];
|
|
20806
20963
|
this._private__axisViews = positionLineLevels.map((level) => new PositionLineAxisView(() => this._private__axisLabel(level)));
|
|
20964
|
+
this._private__labelLayout = acquireLabelLayout(this._private__chart, this._private__id);
|
|
20807
20965
|
this._private__series.attachPrimitive(this);
|
|
20808
20966
|
acquireController(this._private__chart)?._internal_register(this);
|
|
20809
20967
|
}
|
|
@@ -20890,6 +21048,23 @@ class PositionLine {
|
|
|
20890
21048
|
const price = this._private__series.coordinateToPrice(paneY);
|
|
20891
21049
|
return price === null ? null : price;
|
|
20892
21050
|
}
|
|
21051
|
+
/**
|
|
21052
|
+
* Where the level being dragged actually sits. The controller measures the
|
|
21053
|
+
* pointer against it so the level moves by what the pointer moved, instead
|
|
21054
|
+
* of jumping to sit under it — which matters most when the label has been
|
|
21055
|
+
* fanned away from its own line.
|
|
21056
|
+
*/
|
|
21057
|
+
dragAnchorY() {
|
|
21058
|
+
if (this._private__dragLevel === null) {
|
|
21059
|
+
return null;
|
|
21060
|
+
}
|
|
21061
|
+
const price = this._private__levelOptions(this._private__dragLevel)?.price;
|
|
21062
|
+
if (price === undefined || !isFinite(price)) {
|
|
21063
|
+
return null;
|
|
21064
|
+
}
|
|
21065
|
+
const y = this._private__series.priceToCoordinate(price);
|
|
21066
|
+
return y === null ? null : y;
|
|
21067
|
+
}
|
|
20893
21068
|
beginDrag() {
|
|
20894
21069
|
this._private__dragLevel = this._private__hoveredLevel;
|
|
20895
21070
|
if (this._private__dragLevel === null) {
|
|
@@ -21038,6 +21213,7 @@ class PositionLine {
|
|
|
21038
21213
|
*/
|
|
21039
21214
|
remove() {
|
|
21040
21215
|
releaseController(this._private__chart, this);
|
|
21216
|
+
releaseLabelLayout(this._private__chart, this._private__id);
|
|
21041
21217
|
this._private__series.detachPrimitive(this);
|
|
21042
21218
|
}
|
|
21043
21219
|
requestUpdate() {
|
|
@@ -21083,7 +21259,11 @@ class PositionLine {
|
|
|
21083
21259
|
if (!this._private__attached || this._private__options.visible === false) {
|
|
21084
21260
|
return null;
|
|
21085
21261
|
}
|
|
21262
|
+
const layout = this._private__chart.options()['layout'];
|
|
21263
|
+
const fontSize = this._private__theme.fontSize ?? layout.fontSize;
|
|
21264
|
+
const labelHeight = fontSize + this._private__theme.paddingY * 2;
|
|
21086
21265
|
const levels = [];
|
|
21266
|
+
const claims = [];
|
|
21087
21267
|
for (const level of positionLineLevels) {
|
|
21088
21268
|
const options = this._private__levelOptions(level);
|
|
21089
21269
|
// A level added through a patch can be missing its price until the
|
|
@@ -21096,9 +21276,11 @@ class PositionLine {
|
|
|
21096
21276
|
continue;
|
|
21097
21277
|
}
|
|
21098
21278
|
const isEntry = level === 'entry';
|
|
21279
|
+
claims.push({ _internal_level: level, _internal_y: y, _internal_height: labelHeight });
|
|
21099
21280
|
levels.push({
|
|
21100
21281
|
_internal_level: level,
|
|
21101
21282
|
_internal_y: y,
|
|
21283
|
+
_internal_labelOffsetY: 0,
|
|
21102
21284
|
_internal_color: options.color ?? positionLineDefaultColors[level],
|
|
21103
21285
|
_internal_text: options.formatText ? options.formatText(options.price) : options.text ?? '',
|
|
21104
21286
|
_internal_badge: options.badge ?? '',
|
|
@@ -21110,10 +21292,15 @@ class PositionLine {
|
|
|
21110
21292
|
});
|
|
21111
21293
|
}
|
|
21112
21294
|
if (levels.length === 0) {
|
|
21295
|
+
this._private__labelLayout._internal_setClaims(this._private__id, []);
|
|
21113
21296
|
return null;
|
|
21114
21297
|
}
|
|
21115
|
-
|
|
21116
|
-
|
|
21298
|
+
// Published before the offsets are read so every line on the chart —
|
|
21299
|
+
// positions, pending orders, alerts — is fanned against the same set.
|
|
21300
|
+
this._private__labelLayout._internal_setClaims(this._private__id, claims);
|
|
21301
|
+
for (const level of levels) {
|
|
21302
|
+
level._internal_labelOffsetY = this._private__labelLayout._internal_offsetFor(this._private__id, level._internal_level);
|
|
21303
|
+
}
|
|
21117
21304
|
return {
|
|
21118
21305
|
_internal_levels: levels,
|
|
21119
21306
|
_internal_background: this._private__theme.background ?? resolveBackgroundColor(layout.background),
|
|
@@ -27396,7 +27583,7 @@ class BrushTool extends DrawingToolBase {
|
|
|
27396
27583
|
if (this._private__isOverAnotherDrawing()) {
|
|
27397
27584
|
return;
|
|
27398
27585
|
}
|
|
27399
|
-
const point = this._private__toPanePoint(event);
|
|
27586
|
+
const point = this._private__toPanePoint(event, false);
|
|
27400
27587
|
if (point === null) {
|
|
27401
27588
|
return;
|
|
27402
27589
|
}
|
|
@@ -27415,7 +27602,7 @@ class BrushTool extends DrawingToolBase {
|
|
|
27415
27602
|
if (!this._private__isDrawing) {
|
|
27416
27603
|
return;
|
|
27417
27604
|
}
|
|
27418
|
-
const point = this._private__toPanePoint(event);
|
|
27605
|
+
const point = this._private__toPanePoint(event, true);
|
|
27419
27606
|
if (point === null) {
|
|
27420
27607
|
return;
|
|
27421
27608
|
}
|
|
@@ -27486,13 +27673,51 @@ class BrushTool extends DrawingToolBase {
|
|
|
27486
27673
|
}
|
|
27487
27674
|
this._private__pointerId = null;
|
|
27488
27675
|
}
|
|
27489
|
-
|
|
27676
|
+
/**
|
|
27677
|
+
* Where a press lands relative to the drawing area, or null if it lands
|
|
27678
|
+
* outside it. `clamp` pins the point to the edge instead, for a stroke that
|
|
27679
|
+
* is already under way.
|
|
27680
|
+
*/
|
|
27681
|
+
_private__toPanePoint(event, clamp) {
|
|
27682
|
+
const area = this._private__drawArea();
|
|
27683
|
+
if (area === null) {
|
|
27684
|
+
return null;
|
|
27685
|
+
}
|
|
27686
|
+
const x = event.clientX - area._internal_left;
|
|
27687
|
+
const y = event.clientY - area._internal_top;
|
|
27688
|
+
if (clamp) {
|
|
27689
|
+
return {
|
|
27690
|
+
_internal_x: Math.max(0, Math.min(area._internal_width, x)),
|
|
27691
|
+
_internal_y: Math.max(0, Math.min(area._internal_height, y)),
|
|
27692
|
+
};
|
|
27693
|
+
}
|
|
27694
|
+
if (x < 0 || x > area._internal_width || y < 0 || y > area._internal_height) {
|
|
27695
|
+
return null;
|
|
27696
|
+
}
|
|
27697
|
+
return { _internal_x: x, _internal_y: y };
|
|
27698
|
+
}
|
|
27699
|
+
/**
|
|
27700
|
+
* The pane's element is the whole row, price axis cells included, so its
|
|
27701
|
+
* bounds are not the drawing area's. Taking them for it is what let a press
|
|
27702
|
+
* on an axis start a stroke — and be swallowed, leaving the chart unable to
|
|
27703
|
+
* be stretched while the brush was armed.
|
|
27704
|
+
*/
|
|
27705
|
+
_private__drawArea() {
|
|
27490
27706
|
const paneElement = this._private__paneElement();
|
|
27491
27707
|
if (paneElement === null) {
|
|
27492
27708
|
return null;
|
|
27493
27709
|
}
|
|
27494
27710
|
const rect = paneElement.getBoundingClientRect();
|
|
27495
|
-
|
|
27711
|
+
let left = 0;
|
|
27712
|
+
let width = rect.width;
|
|
27713
|
+
// The time scale measures the drawing area; the left axis, when shown, is
|
|
27714
|
+
// what stands between it and the row's edge.
|
|
27715
|
+
const paneWidth = this._chart.timeScale().width();
|
|
27716
|
+
if (paneWidth > 0) {
|
|
27717
|
+
left = this._chart.priceScale('left').width();
|
|
27718
|
+
width = paneWidth;
|
|
27719
|
+
}
|
|
27720
|
+
return { _internal_left: rect.left + left, _internal_top: rect.top, _internal_width: width, _internal_height: rect.height };
|
|
27496
27721
|
}
|
|
27497
27722
|
_private__paneElement() {
|
|
27498
27723
|
try {
|
|
@@ -30851,7 +31076,7 @@ const customSeriesDefaultOptions = {
|
|
|
30851
31076
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
30852
31077
|
*/
|
|
30853
31078
|
function version() {
|
|
30854
|
-
return "2.3.
|
|
31079
|
+
return "2.3.2";
|
|
30855
31080
|
}
|
|
30856
31081
|
|
|
30857
31082
|
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 };
|