@pipsend/charts 2.3.12 → 2.3.13
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 +134 -36
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +134 -36
- package/dist/pipsend-charts.standalone.development.mjs +134 -36
- package/dist/pipsend-charts.standalone.production.js +2 -2
- package/dist/pipsend-charts.standalone.production.mjs +2 -2
- package/dist/typings.d.ts +19 -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.13-dev+202609280001
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -14677,6 +14677,8 @@
|
|
|
14677
14677
|
return size(originalSize, 0.7);
|
|
14678
14678
|
case 'tag':
|
|
14679
14679
|
return size(originalSize, 1);
|
|
14680
|
+
case 'xcross':
|
|
14681
|
+
return size(originalSize, 0.7);
|
|
14680
14682
|
}
|
|
14681
14683
|
}
|
|
14682
14684
|
function calculateShapeHeight(barSpacing) {
|
|
@@ -14877,6 +14879,27 @@
|
|
|
14877
14879
|
y >= textY - halfHeight && y <= textY + halfHeight;
|
|
14878
14880
|
}
|
|
14879
14881
|
|
|
14882
|
+
function drawXCross(ctx, coords, size) {
|
|
14883
|
+
const crossSize = shapeSize('xcross', size);
|
|
14884
|
+
const halfSize = ((crossSize - 1) / 2) * coords._internal_pixelRatio;
|
|
14885
|
+
ctx.save();
|
|
14886
|
+
ctx.strokeStyle = ctx.fillStyle;
|
|
14887
|
+
ctx.lineWidth = Math.max(1, Math.round(1.5 * coords._internal_pixelRatio));
|
|
14888
|
+
ctx.lineCap = 'round';
|
|
14889
|
+
ctx.beginPath();
|
|
14890
|
+
ctx.moveTo(coords._internal_x - halfSize, coords._internal_y - halfSize);
|
|
14891
|
+
ctx.lineTo(coords._internal_x + halfSize, coords._internal_y + halfSize);
|
|
14892
|
+
ctx.moveTo(coords._internal_x + halfSize, coords._internal_y - halfSize);
|
|
14893
|
+
ctx.lineTo(coords._internal_x - halfSize, coords._internal_y + halfSize);
|
|
14894
|
+
ctx.stroke();
|
|
14895
|
+
ctx.restore();
|
|
14896
|
+
}
|
|
14897
|
+
function hitTestXCross(centerX, centerY, size, x, y) {
|
|
14898
|
+
const crossSize = shapeSize('xcross', size);
|
|
14899
|
+
const tolerance = 2 + crossSize / 2;
|
|
14900
|
+
return Math.abs(x - centerX) <= tolerance && Math.abs(y - centerY) <= tolerance;
|
|
14901
|
+
}
|
|
14902
|
+
|
|
14880
14903
|
class SeriesMarkersRenderer {
|
|
14881
14904
|
constructor() {
|
|
14882
14905
|
this._private__data = null;
|
|
@@ -15020,6 +15043,9 @@
|
|
|
15020
15043
|
case 'square':
|
|
15021
15044
|
drawSquare(ctx, coordinates, item._internal_size);
|
|
15022
15045
|
return;
|
|
15046
|
+
case 'xcross':
|
|
15047
|
+
drawXCross(ctx, coordinates, item._internal_size);
|
|
15048
|
+
return;
|
|
15023
15049
|
case 'tag':
|
|
15024
15050
|
// Handled by drawTagItem, which needs both pixel ratios and the text.
|
|
15025
15051
|
return;
|
|
@@ -15048,6 +15074,8 @@
|
|
|
15048
15074
|
return hitTestCircle(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15049
15075
|
case 'square':
|
|
15050
15076
|
return hitTestSquare(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15077
|
+
case 'xcross':
|
|
15078
|
+
return hitTestXCross(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15051
15079
|
case 'tag':
|
|
15052
15080
|
return false;
|
|
15053
15081
|
}
|
|
@@ -26127,17 +26155,19 @@
|
|
|
26127
26155
|
// Draw border
|
|
26128
26156
|
const borderColor = this._private__rectOptions.borderColor;
|
|
26129
26157
|
const borderWidth = this._private__isSelected ? this._private__rectOptions.borderWidth + 1 : this._private__rectOptions.borderWidth;
|
|
26130
|
-
|
|
26131
|
-
|
|
26132
|
-
|
|
26133
|
-
|
|
26134
|
-
|
|
26135
|
-
|
|
26136
|
-
|
|
26137
|
-
|
|
26158
|
+
if (borderWidth > 0) {
|
|
26159
|
+
ctx.strokeStyle = borderColor;
|
|
26160
|
+
ctx.lineWidth = borderWidth * horizontalPixelRatio;
|
|
26161
|
+
// Set border style
|
|
26162
|
+
if (this._private__rectOptions.borderStyle === 'dashed') {
|
|
26163
|
+
ctx.setLineDash([10 * horizontalPixelRatio, 5 * horizontalPixelRatio]);
|
|
26164
|
+
}
|
|
26165
|
+
else if (this._private__rectOptions.borderStyle === 'dotted') {
|
|
26166
|
+
ctx.setLineDash([2 * horizontalPixelRatio, 3 * horizontalPixelRatio]);
|
|
26167
|
+
}
|
|
26168
|
+
ctx.strokeRect(minX, minY, width, height);
|
|
26169
|
+
ctx.setLineDash([]);
|
|
26138
26170
|
}
|
|
26139
|
-
ctx.strokeRect(minX, minY, width, height);
|
|
26140
|
-
ctx.setLineDash([]);
|
|
26141
26171
|
// Draw corner handles if selected
|
|
26142
26172
|
if ((this._private__isSelected || this._private__isHovered) && !this._private__isDrawing && !this.isLocked()) {
|
|
26143
26173
|
this._private__drawCornerHandles(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, borderColor);
|
|
@@ -26165,17 +26195,20 @@
|
|
|
26165
26195
|
}
|
|
26166
26196
|
_private__drawLabel(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, verticalPixelRatio, color) {
|
|
26167
26197
|
const padding = 6 * horizontalPixelRatio;
|
|
26168
|
-
const fontSize = 12 * horizontalPixelRatio;
|
|
26198
|
+
const fontSize = (this._private__rectOptions.labelFontSize ?? 12) * horizontalPixelRatio;
|
|
26169
26199
|
ctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
26170
26200
|
const textMetrics = ctx.measureText(this._private__rectOptions.labelText);
|
|
26171
26201
|
const textWidth = textMetrics.width;
|
|
26172
26202
|
const textHeight = fontSize;
|
|
26203
|
+
const middleY = (minY + maxY) / 2 - textHeight / 2 - padding;
|
|
26204
|
+
// A box extended far past the pane keeps right-hand and centred labels on screen.
|
|
26205
|
+
const visibleMaxX = Math.min(maxX, ctx.canvas.width);
|
|
26173
26206
|
// Calculate label position based on labelPosition option
|
|
26174
26207
|
let labelX = minX + padding;
|
|
26175
26208
|
let labelY = minY + padding;
|
|
26176
26209
|
switch (this._private__rectOptions.labelPosition) {
|
|
26177
26210
|
case 'top-right':
|
|
26178
|
-
labelX =
|
|
26211
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26179
26212
|
labelY = minY + padding;
|
|
26180
26213
|
break;
|
|
26181
26214
|
case 'bottom-left':
|
|
@@ -26183,19 +26216,27 @@
|
|
|
26183
26216
|
labelY = maxY - textHeight - padding * 2;
|
|
26184
26217
|
break;
|
|
26185
26218
|
case 'bottom-right':
|
|
26186
|
-
labelX =
|
|
26219
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26187
26220
|
labelY = maxY - textHeight - padding * 2;
|
|
26188
26221
|
break;
|
|
26189
26222
|
case 'center':
|
|
26190
|
-
labelX = (minX +
|
|
26191
|
-
labelY =
|
|
26223
|
+
labelX = (Math.max(minX, 0) + visibleMaxX) / 2 - textWidth / 2 - padding;
|
|
26224
|
+
labelY = middleY;
|
|
26225
|
+
break;
|
|
26226
|
+
case 'left':
|
|
26227
|
+
labelX = minX + padding;
|
|
26228
|
+
labelY = middleY;
|
|
26229
|
+
break;
|
|
26230
|
+
case 'right':
|
|
26231
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26232
|
+
labelY = middleY;
|
|
26192
26233
|
break;
|
|
26193
26234
|
}
|
|
26194
26235
|
// Draw background
|
|
26195
|
-
ctx.fillStyle = color;
|
|
26236
|
+
ctx.fillStyle = this._private__rectOptions.labelBackgroundColor ?? color;
|
|
26196
26237
|
ctx.fillRect(labelX, labelY, textWidth + padding * 2, textHeight + padding * 2);
|
|
26197
26238
|
// Draw text
|
|
26198
|
-
ctx.fillStyle = '#ffffff';
|
|
26239
|
+
ctx.fillStyle = this._private__rectOptions.labelColor ?? '#ffffff';
|
|
26199
26240
|
ctx.textBaseline = 'top';
|
|
26200
26241
|
ctx.fillText(this._private__rectOptions.labelText, labelX + padding, labelY + padding);
|
|
26201
26242
|
}
|
|
@@ -26433,6 +26474,9 @@
|
|
|
26433
26474
|
showLabel: this._private__rectOptions.showLabel,
|
|
26434
26475
|
labelText: this._private__rectOptions.labelText,
|
|
26435
26476
|
labelPosition: this._private__rectOptions.labelPosition,
|
|
26477
|
+
labelColor: this._private__rectOptions.labelColor,
|
|
26478
|
+
labelBackgroundColor: this._private__rectOptions.labelBackgroundColor,
|
|
26479
|
+
labelFontSize: this._private__rectOptions.labelFontSize,
|
|
26436
26480
|
},
|
|
26437
26481
|
};
|
|
26438
26482
|
}
|
|
@@ -28037,6 +28081,9 @@
|
|
|
28037
28081
|
borderWidth: 1,
|
|
28038
28082
|
textAlign: 'left',
|
|
28039
28083
|
maxWidth: 200,
|
|
28084
|
+
anchor: 'top-left',
|
|
28085
|
+
pointer: false,
|
|
28086
|
+
borderRadius: 0,
|
|
28040
28087
|
...options,
|
|
28041
28088
|
};
|
|
28042
28089
|
this._registerOptions(this._private__textOptions);
|
|
@@ -28188,18 +28235,59 @@
|
|
|
28188
28235
|
const py = this._series.priceToCoordinate(price) ?? 0;
|
|
28189
28236
|
// Calculate text box dimensions
|
|
28190
28237
|
const fontSize = this._private__textOptions.fontSize || 14;
|
|
28191
|
-
const padding = this._private__textOptions.padding
|
|
28238
|
+
const padding = this._private__textOptions.padding ?? 8;
|
|
28192
28239
|
const text = this._private__textOptions.text || '';
|
|
28193
28240
|
// Rough estimate of text width (will be more accurate in canvas)
|
|
28194
28241
|
const charWidth = fontSize * 0.6;
|
|
28195
28242
|
const textWidth = Math.min(text.length * charWidth, this._private__textOptions.maxWidth || 200);
|
|
28196
|
-
const
|
|
28197
|
-
|
|
28198
|
-
const
|
|
28199
|
-
const
|
|
28200
|
-
const
|
|
28201
|
-
const
|
|
28202
|
-
return x >= left && x <= right && y >=
|
|
28243
|
+
const boxWidth = textWidth + padding * 2;
|
|
28244
|
+
const boxHeight = fontSize + padding * 2;
|
|
28245
|
+
const tail = this._private__tailSize(boxHeight);
|
|
28246
|
+
const box = this._private__boxOrigin(px, py, boxWidth, boxHeight, tail);
|
|
28247
|
+
const left = box._internal_left - (this._private__textOptions.anchor === 'left' ? tail : 0);
|
|
28248
|
+
const right = box._internal_left + boxWidth + (this._private__textOptions.anchor === 'right' ? tail : 0);
|
|
28249
|
+
return x >= left && x <= right && y >= box._internal_top && y <= box._internal_top + boxHeight;
|
|
28250
|
+
}
|
|
28251
|
+
_private__tailSize(boxHeight) {
|
|
28252
|
+
const anchor = this._private__textOptions.anchor;
|
|
28253
|
+
return this._private__textOptions.pointer && (anchor === 'left' || anchor === 'right') ? Math.round(boxHeight * 0.35) : 0;
|
|
28254
|
+
}
|
|
28255
|
+
_private__boxOrigin(x, y, width, height, tail) {
|
|
28256
|
+
switch (this._private__textOptions.anchor) {
|
|
28257
|
+
case 'left':
|
|
28258
|
+
return { _internal_left: x + tail, _internal_top: y - height / 2 };
|
|
28259
|
+
case 'right':
|
|
28260
|
+
return { _internal_left: x - tail - width, _internal_top: y - height / 2 };
|
|
28261
|
+
case 'center':
|
|
28262
|
+
return { _internal_left: x - width / 2, _internal_top: y - height / 2 };
|
|
28263
|
+
default:
|
|
28264
|
+
return { _internal_left: x, _internal_top: y };
|
|
28265
|
+
}
|
|
28266
|
+
}
|
|
28267
|
+
// eslint-disable-next-line max-params
|
|
28268
|
+
_private__traceBox(ctx, left, top, width, height, tail, anchorX, anchorY, radius) {
|
|
28269
|
+
const r = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
28270
|
+
ctx.beginPath();
|
|
28271
|
+
ctx.moveTo(left + r, top);
|
|
28272
|
+
ctx.lineTo(left + width - r, top);
|
|
28273
|
+
ctx.arcTo(left + width, top, left + width, top + r, r);
|
|
28274
|
+
if (tail > 0 && this._private__textOptions.anchor === 'right') {
|
|
28275
|
+
ctx.lineTo(left + width, anchorY - tail);
|
|
28276
|
+
ctx.lineTo(anchorX, anchorY);
|
|
28277
|
+
ctx.lineTo(left + width, anchorY + tail);
|
|
28278
|
+
}
|
|
28279
|
+
ctx.lineTo(left + width, top + height - r);
|
|
28280
|
+
ctx.arcTo(left + width, top + height, left + width - r, top + height, r);
|
|
28281
|
+
ctx.lineTo(left + r, top + height);
|
|
28282
|
+
ctx.arcTo(left, top + height, left, top + height - r, r);
|
|
28283
|
+
if (tail > 0 && this._private__textOptions.anchor === 'left') {
|
|
28284
|
+
ctx.lineTo(left, anchorY + tail);
|
|
28285
|
+
ctx.lineTo(anchorX, anchorY);
|
|
28286
|
+
ctx.lineTo(left, anchorY - tail);
|
|
28287
|
+
}
|
|
28288
|
+
ctx.lineTo(left, top + r);
|
|
28289
|
+
ctx.arcTo(left, top, left + r, top, r);
|
|
28290
|
+
ctx.closePath();
|
|
28203
28291
|
}
|
|
28204
28292
|
hitTestEndpoint(x, y) {
|
|
28205
28293
|
if (!this.isComplete())
|
|
@@ -28251,7 +28339,7 @@
|
|
|
28251
28339
|
const x = (coordinateFromTime(this._chart, this._series, time) ?? 0) * horizontalPixelRatio;
|
|
28252
28340
|
const y = (this._series.priceToCoordinate(price) ?? 0) * verticalPixelRatio;
|
|
28253
28341
|
const fontSize = (this._private__textOptions.fontSize || 14) * horizontalPixelRatio;
|
|
28254
|
-
const padding = (this._private__textOptions.padding
|
|
28342
|
+
const padding = (this._private__textOptions.padding ?? 8) * horizontalPixelRatio;
|
|
28255
28343
|
const maxWidth = (this._private__textOptions.maxWidth || 200) * horizontalPixelRatio;
|
|
28256
28344
|
// Set font
|
|
28257
28345
|
ctx.font = `${fontSize}px ${this._private__textOptions.fontFamily || 'Arial'}`;
|
|
@@ -28283,32 +28371,39 @@
|
|
|
28283
28371
|
const boxWidth = maxLineWidth + padding * 2;
|
|
28284
28372
|
const lineHeight = fontSize * 1.2;
|
|
28285
28373
|
const boxHeight = lines.length * lineHeight + padding * 2;
|
|
28374
|
+
const tail = this._private__tailSize(boxHeight);
|
|
28375
|
+
const { _internal_left: left, _internal_top: top } = this._private__boxOrigin(x, y, boxWidth, boxHeight, tail);
|
|
28376
|
+
const radius = (this._private__textOptions.borderRadius ?? 0) * horizontalPixelRatio;
|
|
28286
28377
|
// Draw background
|
|
28287
|
-
const bgOpacity = this._private__textOptions.backgroundOpacity
|
|
28378
|
+
const bgOpacity = this._private__textOptions.backgroundOpacity ?? 0.8;
|
|
28288
28379
|
const bgColor = this._private__textOptions.backgroundColor || '#2962FF';
|
|
28289
|
-
|
|
28290
|
-
|
|
28380
|
+
if (bgOpacity > 0) {
|
|
28381
|
+
ctx.fillStyle = this._private__hexToRgba(bgColor, bgOpacity);
|
|
28382
|
+
this._private__traceBox(ctx, left, top, boxWidth, boxHeight, tail, x, y, radius);
|
|
28383
|
+
ctx.fill();
|
|
28384
|
+
}
|
|
28291
28385
|
// Draw border
|
|
28292
28386
|
if (this._private__isSelected || this._private__isHovered) {
|
|
28293
28387
|
ctx.strokeStyle = this._private__textOptions.borderColor ?? '#FFFFFF';
|
|
28294
28388
|
ctx.lineWidth = (this._private__textOptions.borderWidth || 1) * horizontalPixelRatio * (this._private__isSelected ? 2 : 1);
|
|
28295
|
-
|
|
28389
|
+
this._private__traceBox(ctx, left, top, boxWidth, boxHeight, tail, x, y, radius);
|
|
28390
|
+
ctx.stroke();
|
|
28296
28391
|
}
|
|
28297
28392
|
// Draw text
|
|
28298
28393
|
ctx.fillStyle = this._private__textOptions.textColor || '#FFFFFF';
|
|
28299
28394
|
for (let i = 0; i < lines.length; i++) {
|
|
28300
28395
|
const line = lines[i];
|
|
28301
|
-
let textX =
|
|
28396
|
+
let textX = left + padding;
|
|
28302
28397
|
// Handle text alignment
|
|
28303
28398
|
if (this._private__textOptions.textAlign === 'center') {
|
|
28304
28399
|
const metrics = ctx.measureText(line);
|
|
28305
|
-
textX =
|
|
28400
|
+
textX = left + (boxWidth - metrics.width) / 2;
|
|
28306
28401
|
}
|
|
28307
28402
|
else if (this._private__textOptions.textAlign === 'right') {
|
|
28308
28403
|
const metrics = ctx.measureText(line);
|
|
28309
|
-
textX =
|
|
28404
|
+
textX = left + boxWidth - metrics.width - padding;
|
|
28310
28405
|
}
|
|
28311
|
-
const textY =
|
|
28406
|
+
const textY = top + padding + i * lineHeight;
|
|
28312
28407
|
ctx.fillText(line, textX, textY);
|
|
28313
28408
|
}
|
|
28314
28409
|
// Draw anchor point if selected
|
|
@@ -28352,6 +28447,9 @@
|
|
|
28352
28447
|
borderWidth: this._private__textOptions.borderWidth,
|
|
28353
28448
|
textAlign: this._private__textOptions.textAlign,
|
|
28354
28449
|
maxWidth: this._private__textOptions.maxWidth,
|
|
28450
|
+
anchor: this._private__textOptions.anchor,
|
|
28451
|
+
pointer: this._private__textOptions.pointer,
|
|
28452
|
+
borderRadius: this._private__textOptions.borderRadius,
|
|
28355
28453
|
},
|
|
28356
28454
|
extra: {
|
|
28357
28455
|
text: this._private__textOptions.text,
|
|
@@ -31139,7 +31237,7 @@
|
|
|
31139
31237
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
31140
31238
|
*/
|
|
31141
31239
|
function version() {
|
|
31142
|
-
return "2.3.
|
|
31240
|
+
return "2.3.13-dev+202609280001";
|
|
31143
31241
|
}
|
|
31144
31242
|
|
|
31145
31243
|
var PipsendChartsModule = /*#__PURE__*/Object.freeze({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v2.3.
|
|
3
|
+
* Pipsend Charts v2.3.13-dev+202609280001
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -14674,6 +14674,8 @@ function shapeSize(shape, originalSize) {
|
|
|
14674
14674
|
return size(originalSize, 0.7);
|
|
14675
14675
|
case 'tag':
|
|
14676
14676
|
return size(originalSize, 1);
|
|
14677
|
+
case 'xcross':
|
|
14678
|
+
return size(originalSize, 0.7);
|
|
14677
14679
|
}
|
|
14678
14680
|
}
|
|
14679
14681
|
function calculateShapeHeight(barSpacing) {
|
|
@@ -14874,6 +14876,27 @@ function hitTestText(textX, textY, textWidth, textHeight, x, y) {
|
|
|
14874
14876
|
y >= textY - halfHeight && y <= textY + halfHeight;
|
|
14875
14877
|
}
|
|
14876
14878
|
|
|
14879
|
+
function drawXCross(ctx, coords, size) {
|
|
14880
|
+
const crossSize = shapeSize('xcross', size);
|
|
14881
|
+
const halfSize = ((crossSize - 1) / 2) * coords._internal_pixelRatio;
|
|
14882
|
+
ctx.save();
|
|
14883
|
+
ctx.strokeStyle = ctx.fillStyle;
|
|
14884
|
+
ctx.lineWidth = Math.max(1, Math.round(1.5 * coords._internal_pixelRatio));
|
|
14885
|
+
ctx.lineCap = 'round';
|
|
14886
|
+
ctx.beginPath();
|
|
14887
|
+
ctx.moveTo(coords._internal_x - halfSize, coords._internal_y - halfSize);
|
|
14888
|
+
ctx.lineTo(coords._internal_x + halfSize, coords._internal_y + halfSize);
|
|
14889
|
+
ctx.moveTo(coords._internal_x + halfSize, coords._internal_y - halfSize);
|
|
14890
|
+
ctx.lineTo(coords._internal_x - halfSize, coords._internal_y + halfSize);
|
|
14891
|
+
ctx.stroke();
|
|
14892
|
+
ctx.restore();
|
|
14893
|
+
}
|
|
14894
|
+
function hitTestXCross(centerX, centerY, size, x, y) {
|
|
14895
|
+
const crossSize = shapeSize('xcross', size);
|
|
14896
|
+
const tolerance = 2 + crossSize / 2;
|
|
14897
|
+
return Math.abs(x - centerX) <= tolerance && Math.abs(y - centerY) <= tolerance;
|
|
14898
|
+
}
|
|
14899
|
+
|
|
14877
14900
|
class SeriesMarkersRenderer {
|
|
14878
14901
|
constructor() {
|
|
14879
14902
|
this._private__data = null;
|
|
@@ -15017,6 +15040,9 @@ function drawShape(item, ctx, coordinates) {
|
|
|
15017
15040
|
case 'square':
|
|
15018
15041
|
drawSquare(ctx, coordinates, item._internal_size);
|
|
15019
15042
|
return;
|
|
15043
|
+
case 'xcross':
|
|
15044
|
+
drawXCross(ctx, coordinates, item._internal_size);
|
|
15045
|
+
return;
|
|
15020
15046
|
case 'tag':
|
|
15021
15047
|
// Handled by drawTagItem, which needs both pixel ratios and the text.
|
|
15022
15048
|
return;
|
|
@@ -15045,6 +15071,8 @@ function hitTestShape(item, x, y) {
|
|
|
15045
15071
|
return hitTestCircle(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15046
15072
|
case 'square':
|
|
15047
15073
|
return hitTestSquare(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15074
|
+
case 'xcross':
|
|
15075
|
+
return hitTestXCross(item._internal_x, item._internal_y, item._internal_size, x, y);
|
|
15048
15076
|
case 'tag':
|
|
15049
15077
|
return false;
|
|
15050
15078
|
}
|
|
@@ -26124,17 +26152,19 @@ class RectangleTool extends DrawingToolBase {
|
|
|
26124
26152
|
// Draw border
|
|
26125
26153
|
const borderColor = this._private__rectOptions.borderColor;
|
|
26126
26154
|
const borderWidth = this._private__isSelected ? this._private__rectOptions.borderWidth + 1 : this._private__rectOptions.borderWidth;
|
|
26127
|
-
|
|
26128
|
-
|
|
26129
|
-
|
|
26130
|
-
|
|
26131
|
-
|
|
26132
|
-
|
|
26133
|
-
|
|
26134
|
-
|
|
26155
|
+
if (borderWidth > 0) {
|
|
26156
|
+
ctx.strokeStyle = borderColor;
|
|
26157
|
+
ctx.lineWidth = borderWidth * horizontalPixelRatio;
|
|
26158
|
+
// Set border style
|
|
26159
|
+
if (this._private__rectOptions.borderStyle === 'dashed') {
|
|
26160
|
+
ctx.setLineDash([10 * horizontalPixelRatio, 5 * horizontalPixelRatio]);
|
|
26161
|
+
}
|
|
26162
|
+
else if (this._private__rectOptions.borderStyle === 'dotted') {
|
|
26163
|
+
ctx.setLineDash([2 * horizontalPixelRatio, 3 * horizontalPixelRatio]);
|
|
26164
|
+
}
|
|
26165
|
+
ctx.strokeRect(minX, minY, width, height);
|
|
26166
|
+
ctx.setLineDash([]);
|
|
26135
26167
|
}
|
|
26136
|
-
ctx.strokeRect(minX, minY, width, height);
|
|
26137
|
-
ctx.setLineDash([]);
|
|
26138
26168
|
// Draw corner handles if selected
|
|
26139
26169
|
if ((this._private__isSelected || this._private__isHovered) && !this._private__isDrawing && !this.isLocked()) {
|
|
26140
26170
|
this._private__drawCornerHandles(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, borderColor);
|
|
@@ -26162,17 +26192,20 @@ class RectangleTool extends DrawingToolBase {
|
|
|
26162
26192
|
}
|
|
26163
26193
|
_private__drawLabel(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, verticalPixelRatio, color) {
|
|
26164
26194
|
const padding = 6 * horizontalPixelRatio;
|
|
26165
|
-
const fontSize = 12 * horizontalPixelRatio;
|
|
26195
|
+
const fontSize = (this._private__rectOptions.labelFontSize ?? 12) * horizontalPixelRatio;
|
|
26166
26196
|
ctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
26167
26197
|
const textMetrics = ctx.measureText(this._private__rectOptions.labelText);
|
|
26168
26198
|
const textWidth = textMetrics.width;
|
|
26169
26199
|
const textHeight = fontSize;
|
|
26200
|
+
const middleY = (minY + maxY) / 2 - textHeight / 2 - padding;
|
|
26201
|
+
// A box extended far past the pane keeps right-hand and centred labels on screen.
|
|
26202
|
+
const visibleMaxX = Math.min(maxX, ctx.canvas.width);
|
|
26170
26203
|
// Calculate label position based on labelPosition option
|
|
26171
26204
|
let labelX = minX + padding;
|
|
26172
26205
|
let labelY = minY + padding;
|
|
26173
26206
|
switch (this._private__rectOptions.labelPosition) {
|
|
26174
26207
|
case 'top-right':
|
|
26175
|
-
labelX =
|
|
26208
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26176
26209
|
labelY = minY + padding;
|
|
26177
26210
|
break;
|
|
26178
26211
|
case 'bottom-left':
|
|
@@ -26180,19 +26213,27 @@ class RectangleTool extends DrawingToolBase {
|
|
|
26180
26213
|
labelY = maxY - textHeight - padding * 2;
|
|
26181
26214
|
break;
|
|
26182
26215
|
case 'bottom-right':
|
|
26183
|
-
labelX =
|
|
26216
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26184
26217
|
labelY = maxY - textHeight - padding * 2;
|
|
26185
26218
|
break;
|
|
26186
26219
|
case 'center':
|
|
26187
|
-
labelX = (minX +
|
|
26188
|
-
labelY =
|
|
26220
|
+
labelX = (Math.max(minX, 0) + visibleMaxX) / 2 - textWidth / 2 - padding;
|
|
26221
|
+
labelY = middleY;
|
|
26222
|
+
break;
|
|
26223
|
+
case 'left':
|
|
26224
|
+
labelX = minX + padding;
|
|
26225
|
+
labelY = middleY;
|
|
26226
|
+
break;
|
|
26227
|
+
case 'right':
|
|
26228
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26229
|
+
labelY = middleY;
|
|
26189
26230
|
break;
|
|
26190
26231
|
}
|
|
26191
26232
|
// Draw background
|
|
26192
|
-
ctx.fillStyle = color;
|
|
26233
|
+
ctx.fillStyle = this._private__rectOptions.labelBackgroundColor ?? color;
|
|
26193
26234
|
ctx.fillRect(labelX, labelY, textWidth + padding * 2, textHeight + padding * 2);
|
|
26194
26235
|
// Draw text
|
|
26195
|
-
ctx.fillStyle = '#ffffff';
|
|
26236
|
+
ctx.fillStyle = this._private__rectOptions.labelColor ?? '#ffffff';
|
|
26196
26237
|
ctx.textBaseline = 'top';
|
|
26197
26238
|
ctx.fillText(this._private__rectOptions.labelText, labelX + padding, labelY + padding);
|
|
26198
26239
|
}
|
|
@@ -26430,6 +26471,9 @@ class RectangleTool extends DrawingToolBase {
|
|
|
26430
26471
|
showLabel: this._private__rectOptions.showLabel,
|
|
26431
26472
|
labelText: this._private__rectOptions.labelText,
|
|
26432
26473
|
labelPosition: this._private__rectOptions.labelPosition,
|
|
26474
|
+
labelColor: this._private__rectOptions.labelColor,
|
|
26475
|
+
labelBackgroundColor: this._private__rectOptions.labelBackgroundColor,
|
|
26476
|
+
labelFontSize: this._private__rectOptions.labelFontSize,
|
|
26433
26477
|
},
|
|
26434
26478
|
};
|
|
26435
26479
|
}
|
|
@@ -28034,6 +28078,9 @@ class TextTool extends DrawingToolBase {
|
|
|
28034
28078
|
borderWidth: 1,
|
|
28035
28079
|
textAlign: 'left',
|
|
28036
28080
|
maxWidth: 200,
|
|
28081
|
+
anchor: 'top-left',
|
|
28082
|
+
pointer: false,
|
|
28083
|
+
borderRadius: 0,
|
|
28037
28084
|
...options,
|
|
28038
28085
|
};
|
|
28039
28086
|
this._registerOptions(this._private__textOptions);
|
|
@@ -28185,18 +28232,59 @@ class TextTool extends DrawingToolBase {
|
|
|
28185
28232
|
const py = this._series.priceToCoordinate(price) ?? 0;
|
|
28186
28233
|
// Calculate text box dimensions
|
|
28187
28234
|
const fontSize = this._private__textOptions.fontSize || 14;
|
|
28188
|
-
const padding = this._private__textOptions.padding
|
|
28235
|
+
const padding = this._private__textOptions.padding ?? 8;
|
|
28189
28236
|
const text = this._private__textOptions.text || '';
|
|
28190
28237
|
// Rough estimate of text width (will be more accurate in canvas)
|
|
28191
28238
|
const charWidth = fontSize * 0.6;
|
|
28192
28239
|
const textWidth = Math.min(text.length * charWidth, this._private__textOptions.maxWidth || 200);
|
|
28193
|
-
const
|
|
28194
|
-
|
|
28195
|
-
const
|
|
28196
|
-
const
|
|
28197
|
-
const
|
|
28198
|
-
const
|
|
28199
|
-
return x >= left && x <= right && y >=
|
|
28240
|
+
const boxWidth = textWidth + padding * 2;
|
|
28241
|
+
const boxHeight = fontSize + padding * 2;
|
|
28242
|
+
const tail = this._private__tailSize(boxHeight);
|
|
28243
|
+
const box = this._private__boxOrigin(px, py, boxWidth, boxHeight, tail);
|
|
28244
|
+
const left = box._internal_left - (this._private__textOptions.anchor === 'left' ? tail : 0);
|
|
28245
|
+
const right = box._internal_left + boxWidth + (this._private__textOptions.anchor === 'right' ? tail : 0);
|
|
28246
|
+
return x >= left && x <= right && y >= box._internal_top && y <= box._internal_top + boxHeight;
|
|
28247
|
+
}
|
|
28248
|
+
_private__tailSize(boxHeight) {
|
|
28249
|
+
const anchor = this._private__textOptions.anchor;
|
|
28250
|
+
return this._private__textOptions.pointer && (anchor === 'left' || anchor === 'right') ? Math.round(boxHeight * 0.35) : 0;
|
|
28251
|
+
}
|
|
28252
|
+
_private__boxOrigin(x, y, width, height, tail) {
|
|
28253
|
+
switch (this._private__textOptions.anchor) {
|
|
28254
|
+
case 'left':
|
|
28255
|
+
return { _internal_left: x + tail, _internal_top: y - height / 2 };
|
|
28256
|
+
case 'right':
|
|
28257
|
+
return { _internal_left: x - tail - width, _internal_top: y - height / 2 };
|
|
28258
|
+
case 'center':
|
|
28259
|
+
return { _internal_left: x - width / 2, _internal_top: y - height / 2 };
|
|
28260
|
+
default:
|
|
28261
|
+
return { _internal_left: x, _internal_top: y };
|
|
28262
|
+
}
|
|
28263
|
+
}
|
|
28264
|
+
// eslint-disable-next-line max-params
|
|
28265
|
+
_private__traceBox(ctx, left, top, width, height, tail, anchorX, anchorY, radius) {
|
|
28266
|
+
const r = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
28267
|
+
ctx.beginPath();
|
|
28268
|
+
ctx.moveTo(left + r, top);
|
|
28269
|
+
ctx.lineTo(left + width - r, top);
|
|
28270
|
+
ctx.arcTo(left + width, top, left + width, top + r, r);
|
|
28271
|
+
if (tail > 0 && this._private__textOptions.anchor === 'right') {
|
|
28272
|
+
ctx.lineTo(left + width, anchorY - tail);
|
|
28273
|
+
ctx.lineTo(anchorX, anchorY);
|
|
28274
|
+
ctx.lineTo(left + width, anchorY + tail);
|
|
28275
|
+
}
|
|
28276
|
+
ctx.lineTo(left + width, top + height - r);
|
|
28277
|
+
ctx.arcTo(left + width, top + height, left + width - r, top + height, r);
|
|
28278
|
+
ctx.lineTo(left + r, top + height);
|
|
28279
|
+
ctx.arcTo(left, top + height, left, top + height - r, r);
|
|
28280
|
+
if (tail > 0 && this._private__textOptions.anchor === 'left') {
|
|
28281
|
+
ctx.lineTo(left, anchorY + tail);
|
|
28282
|
+
ctx.lineTo(anchorX, anchorY);
|
|
28283
|
+
ctx.lineTo(left, anchorY - tail);
|
|
28284
|
+
}
|
|
28285
|
+
ctx.lineTo(left, top + r);
|
|
28286
|
+
ctx.arcTo(left, top, left + r, top, r);
|
|
28287
|
+
ctx.closePath();
|
|
28200
28288
|
}
|
|
28201
28289
|
hitTestEndpoint(x, y) {
|
|
28202
28290
|
if (!this.isComplete())
|
|
@@ -28248,7 +28336,7 @@ class TextTool extends DrawingToolBase {
|
|
|
28248
28336
|
const x = (coordinateFromTime(this._chart, this._series, time) ?? 0) * horizontalPixelRatio;
|
|
28249
28337
|
const y = (this._series.priceToCoordinate(price) ?? 0) * verticalPixelRatio;
|
|
28250
28338
|
const fontSize = (this._private__textOptions.fontSize || 14) * horizontalPixelRatio;
|
|
28251
|
-
const padding = (this._private__textOptions.padding
|
|
28339
|
+
const padding = (this._private__textOptions.padding ?? 8) * horizontalPixelRatio;
|
|
28252
28340
|
const maxWidth = (this._private__textOptions.maxWidth || 200) * horizontalPixelRatio;
|
|
28253
28341
|
// Set font
|
|
28254
28342
|
ctx.font = `${fontSize}px ${this._private__textOptions.fontFamily || 'Arial'}`;
|
|
@@ -28280,32 +28368,39 @@ class TextTool extends DrawingToolBase {
|
|
|
28280
28368
|
const boxWidth = maxLineWidth + padding * 2;
|
|
28281
28369
|
const lineHeight = fontSize * 1.2;
|
|
28282
28370
|
const boxHeight = lines.length * lineHeight + padding * 2;
|
|
28371
|
+
const tail = this._private__tailSize(boxHeight);
|
|
28372
|
+
const { _internal_left: left, _internal_top: top } = this._private__boxOrigin(x, y, boxWidth, boxHeight, tail);
|
|
28373
|
+
const radius = (this._private__textOptions.borderRadius ?? 0) * horizontalPixelRatio;
|
|
28283
28374
|
// Draw background
|
|
28284
|
-
const bgOpacity = this._private__textOptions.backgroundOpacity
|
|
28375
|
+
const bgOpacity = this._private__textOptions.backgroundOpacity ?? 0.8;
|
|
28285
28376
|
const bgColor = this._private__textOptions.backgroundColor || '#2962FF';
|
|
28286
|
-
|
|
28287
|
-
|
|
28377
|
+
if (bgOpacity > 0) {
|
|
28378
|
+
ctx.fillStyle = this._private__hexToRgba(bgColor, bgOpacity);
|
|
28379
|
+
this._private__traceBox(ctx, left, top, boxWidth, boxHeight, tail, x, y, radius);
|
|
28380
|
+
ctx.fill();
|
|
28381
|
+
}
|
|
28288
28382
|
// Draw border
|
|
28289
28383
|
if (this._private__isSelected || this._private__isHovered) {
|
|
28290
28384
|
ctx.strokeStyle = this._private__textOptions.borderColor ?? '#FFFFFF';
|
|
28291
28385
|
ctx.lineWidth = (this._private__textOptions.borderWidth || 1) * horizontalPixelRatio * (this._private__isSelected ? 2 : 1);
|
|
28292
|
-
|
|
28386
|
+
this._private__traceBox(ctx, left, top, boxWidth, boxHeight, tail, x, y, radius);
|
|
28387
|
+
ctx.stroke();
|
|
28293
28388
|
}
|
|
28294
28389
|
// Draw text
|
|
28295
28390
|
ctx.fillStyle = this._private__textOptions.textColor || '#FFFFFF';
|
|
28296
28391
|
for (let i = 0; i < lines.length; i++) {
|
|
28297
28392
|
const line = lines[i];
|
|
28298
|
-
let textX =
|
|
28393
|
+
let textX = left + padding;
|
|
28299
28394
|
// Handle text alignment
|
|
28300
28395
|
if (this._private__textOptions.textAlign === 'center') {
|
|
28301
28396
|
const metrics = ctx.measureText(line);
|
|
28302
|
-
textX =
|
|
28397
|
+
textX = left + (boxWidth - metrics.width) / 2;
|
|
28303
28398
|
}
|
|
28304
28399
|
else if (this._private__textOptions.textAlign === 'right') {
|
|
28305
28400
|
const metrics = ctx.measureText(line);
|
|
28306
|
-
textX =
|
|
28401
|
+
textX = left + boxWidth - metrics.width - padding;
|
|
28307
28402
|
}
|
|
28308
|
-
const textY =
|
|
28403
|
+
const textY = top + padding + i * lineHeight;
|
|
28309
28404
|
ctx.fillText(line, textX, textY);
|
|
28310
28405
|
}
|
|
28311
28406
|
// Draw anchor point if selected
|
|
@@ -28349,6 +28444,9 @@ class TextTool extends DrawingToolBase {
|
|
|
28349
28444
|
borderWidth: this._private__textOptions.borderWidth,
|
|
28350
28445
|
textAlign: this._private__textOptions.textAlign,
|
|
28351
28446
|
maxWidth: this._private__textOptions.maxWidth,
|
|
28447
|
+
anchor: this._private__textOptions.anchor,
|
|
28448
|
+
pointer: this._private__textOptions.pointer,
|
|
28449
|
+
borderRadius: this._private__textOptions.borderRadius,
|
|
28352
28450
|
},
|
|
28353
28451
|
extra: {
|
|
28354
28452
|
text: this._private__textOptions.text,
|
|
@@ -31136,7 +31234,7 @@ const customSeriesDefaultOptions = {
|
|
|
31136
31234
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
31137
31235
|
*/
|
|
31138
31236
|
function version() {
|
|
31139
|
-
return "2.3.
|
|
31237
|
+
return "2.3.13-dev+202609280001";
|
|
31140
31238
|
}
|
|
31141
31239
|
|
|
31142
31240
|
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 };
|