@pipsend/charts 2.3.11 → 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 +143 -38
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +143 -38
- package/dist/pipsend-charts.standalone.development.mjs +143 -38
- 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
|
}
|
|
@@ -19705,6 +19733,12 @@
|
|
|
19705
19733
|
}
|
|
19706
19734
|
|
|
19707
19735
|
const CLICK_TOLERANCE_PX = 4;
|
|
19736
|
+
/**
|
|
19737
|
+
* A fingertip never holds still: every tap travels further than a pointer
|
|
19738
|
+
* does, and judging it by the mouse's few pixels turned each one into a tiny
|
|
19739
|
+
* drag, so the tap never arrived.
|
|
19740
|
+
*/
|
|
19741
|
+
const TOUCH_CLICK_TOLERANCE_PX = 12;
|
|
19708
19742
|
/**
|
|
19709
19743
|
* Single input owner for every trading line on a chart.
|
|
19710
19744
|
*
|
|
@@ -19845,9 +19879,10 @@
|
|
|
19845
19879
|
this._private__releasePointer();
|
|
19846
19880
|
this._private__pressedLine = null;
|
|
19847
19881
|
this._private__pressOrigin = null;
|
|
19882
|
+
const tolerance = wasTouch ? TOUCH_CLICK_TOLERANCE_PX : CLICK_TOLERANCE_PX;
|
|
19848
19883
|
const moved = origin !== null &&
|
|
19849
|
-
(Math.abs(event.clientX - origin._internal_x) >
|
|
19850
|
-
Math.abs(event.clientY - origin._internal_y) >
|
|
19884
|
+
(Math.abs(event.clientX - origin._internal_x) > tolerance ||
|
|
19885
|
+
Math.abs(event.clientY - origin._internal_y) > tolerance);
|
|
19851
19886
|
if (dragged !== null) {
|
|
19852
19887
|
this._private__dragging = null;
|
|
19853
19888
|
this._private__grabOffset = 0;
|
|
@@ -26120,17 +26155,19 @@
|
|
|
26120
26155
|
// Draw border
|
|
26121
26156
|
const borderColor = this._private__rectOptions.borderColor;
|
|
26122
26157
|
const borderWidth = this._private__isSelected ? this._private__rectOptions.borderWidth + 1 : this._private__rectOptions.borderWidth;
|
|
26123
|
-
|
|
26124
|
-
|
|
26125
|
-
|
|
26126
|
-
|
|
26127
|
-
|
|
26128
|
-
|
|
26129
|
-
|
|
26130
|
-
|
|
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([]);
|
|
26131
26170
|
}
|
|
26132
|
-
ctx.strokeRect(minX, minY, width, height);
|
|
26133
|
-
ctx.setLineDash([]);
|
|
26134
26171
|
// Draw corner handles if selected
|
|
26135
26172
|
if ((this._private__isSelected || this._private__isHovered) && !this._private__isDrawing && !this.isLocked()) {
|
|
26136
26173
|
this._private__drawCornerHandles(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, borderColor);
|
|
@@ -26158,17 +26195,20 @@
|
|
|
26158
26195
|
}
|
|
26159
26196
|
_private__drawLabel(ctx, minX, minY, maxX, maxY, horizontalPixelRatio, verticalPixelRatio, color) {
|
|
26160
26197
|
const padding = 6 * horizontalPixelRatio;
|
|
26161
|
-
const fontSize = 12 * horizontalPixelRatio;
|
|
26198
|
+
const fontSize = (this._private__rectOptions.labelFontSize ?? 12) * horizontalPixelRatio;
|
|
26162
26199
|
ctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
26163
26200
|
const textMetrics = ctx.measureText(this._private__rectOptions.labelText);
|
|
26164
26201
|
const textWidth = textMetrics.width;
|
|
26165
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);
|
|
26166
26206
|
// Calculate label position based on labelPosition option
|
|
26167
26207
|
let labelX = minX + padding;
|
|
26168
26208
|
let labelY = minY + padding;
|
|
26169
26209
|
switch (this._private__rectOptions.labelPosition) {
|
|
26170
26210
|
case 'top-right':
|
|
26171
|
-
labelX =
|
|
26211
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26172
26212
|
labelY = minY + padding;
|
|
26173
26213
|
break;
|
|
26174
26214
|
case 'bottom-left':
|
|
@@ -26176,19 +26216,27 @@
|
|
|
26176
26216
|
labelY = maxY - textHeight - padding * 2;
|
|
26177
26217
|
break;
|
|
26178
26218
|
case 'bottom-right':
|
|
26179
|
-
labelX =
|
|
26219
|
+
labelX = visibleMaxX - textWidth - padding * 2;
|
|
26180
26220
|
labelY = maxY - textHeight - padding * 2;
|
|
26181
26221
|
break;
|
|
26182
26222
|
case 'center':
|
|
26183
|
-
labelX = (minX +
|
|
26184
|
-
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;
|
|
26185
26233
|
break;
|
|
26186
26234
|
}
|
|
26187
26235
|
// Draw background
|
|
26188
|
-
ctx.fillStyle = color;
|
|
26236
|
+
ctx.fillStyle = this._private__rectOptions.labelBackgroundColor ?? color;
|
|
26189
26237
|
ctx.fillRect(labelX, labelY, textWidth + padding * 2, textHeight + padding * 2);
|
|
26190
26238
|
// Draw text
|
|
26191
|
-
ctx.fillStyle = '#ffffff';
|
|
26239
|
+
ctx.fillStyle = this._private__rectOptions.labelColor ?? '#ffffff';
|
|
26192
26240
|
ctx.textBaseline = 'top';
|
|
26193
26241
|
ctx.fillText(this._private__rectOptions.labelText, labelX + padding, labelY + padding);
|
|
26194
26242
|
}
|
|
@@ -26426,6 +26474,9 @@
|
|
|
26426
26474
|
showLabel: this._private__rectOptions.showLabel,
|
|
26427
26475
|
labelText: this._private__rectOptions.labelText,
|
|
26428
26476
|
labelPosition: this._private__rectOptions.labelPosition,
|
|
26477
|
+
labelColor: this._private__rectOptions.labelColor,
|
|
26478
|
+
labelBackgroundColor: this._private__rectOptions.labelBackgroundColor,
|
|
26479
|
+
labelFontSize: this._private__rectOptions.labelFontSize,
|
|
26429
26480
|
},
|
|
26430
26481
|
};
|
|
26431
26482
|
}
|
|
@@ -28030,6 +28081,9 @@
|
|
|
28030
28081
|
borderWidth: 1,
|
|
28031
28082
|
textAlign: 'left',
|
|
28032
28083
|
maxWidth: 200,
|
|
28084
|
+
anchor: 'top-left',
|
|
28085
|
+
pointer: false,
|
|
28086
|
+
borderRadius: 0,
|
|
28033
28087
|
...options,
|
|
28034
28088
|
};
|
|
28035
28089
|
this._registerOptions(this._private__textOptions);
|
|
@@ -28181,18 +28235,59 @@
|
|
|
28181
28235
|
const py = this._series.priceToCoordinate(price) ?? 0;
|
|
28182
28236
|
// Calculate text box dimensions
|
|
28183
28237
|
const fontSize = this._private__textOptions.fontSize || 14;
|
|
28184
|
-
const padding = this._private__textOptions.padding
|
|
28238
|
+
const padding = this._private__textOptions.padding ?? 8;
|
|
28185
28239
|
const text = this._private__textOptions.text || '';
|
|
28186
28240
|
// Rough estimate of text width (will be more accurate in canvas)
|
|
28187
28241
|
const charWidth = fontSize * 0.6;
|
|
28188
28242
|
const textWidth = Math.min(text.length * charWidth, this._private__textOptions.maxWidth || 200);
|
|
28189
|
-
const
|
|
28190
|
-
|
|
28191
|
-
const
|
|
28192
|
-
const
|
|
28193
|
-
const
|
|
28194
|
-
const
|
|
28195
|
-
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();
|
|
28196
28291
|
}
|
|
28197
28292
|
hitTestEndpoint(x, y) {
|
|
28198
28293
|
if (!this.isComplete())
|
|
@@ -28244,7 +28339,7 @@
|
|
|
28244
28339
|
const x = (coordinateFromTime(this._chart, this._series, time) ?? 0) * horizontalPixelRatio;
|
|
28245
28340
|
const y = (this._series.priceToCoordinate(price) ?? 0) * verticalPixelRatio;
|
|
28246
28341
|
const fontSize = (this._private__textOptions.fontSize || 14) * horizontalPixelRatio;
|
|
28247
|
-
const padding = (this._private__textOptions.padding
|
|
28342
|
+
const padding = (this._private__textOptions.padding ?? 8) * horizontalPixelRatio;
|
|
28248
28343
|
const maxWidth = (this._private__textOptions.maxWidth || 200) * horizontalPixelRatio;
|
|
28249
28344
|
// Set font
|
|
28250
28345
|
ctx.font = `${fontSize}px ${this._private__textOptions.fontFamily || 'Arial'}`;
|
|
@@ -28276,32 +28371,39 @@
|
|
|
28276
28371
|
const boxWidth = maxLineWidth + padding * 2;
|
|
28277
28372
|
const lineHeight = fontSize * 1.2;
|
|
28278
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;
|
|
28279
28377
|
// Draw background
|
|
28280
|
-
const bgOpacity = this._private__textOptions.backgroundOpacity
|
|
28378
|
+
const bgOpacity = this._private__textOptions.backgroundOpacity ?? 0.8;
|
|
28281
28379
|
const bgColor = this._private__textOptions.backgroundColor || '#2962FF';
|
|
28282
|
-
|
|
28283
|
-
|
|
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
|
+
}
|
|
28284
28385
|
// Draw border
|
|
28285
28386
|
if (this._private__isSelected || this._private__isHovered) {
|
|
28286
28387
|
ctx.strokeStyle = this._private__textOptions.borderColor ?? '#FFFFFF';
|
|
28287
28388
|
ctx.lineWidth = (this._private__textOptions.borderWidth || 1) * horizontalPixelRatio * (this._private__isSelected ? 2 : 1);
|
|
28288
|
-
|
|
28389
|
+
this._private__traceBox(ctx, left, top, boxWidth, boxHeight, tail, x, y, radius);
|
|
28390
|
+
ctx.stroke();
|
|
28289
28391
|
}
|
|
28290
28392
|
// Draw text
|
|
28291
28393
|
ctx.fillStyle = this._private__textOptions.textColor || '#FFFFFF';
|
|
28292
28394
|
for (let i = 0; i < lines.length; i++) {
|
|
28293
28395
|
const line = lines[i];
|
|
28294
|
-
let textX =
|
|
28396
|
+
let textX = left + padding;
|
|
28295
28397
|
// Handle text alignment
|
|
28296
28398
|
if (this._private__textOptions.textAlign === 'center') {
|
|
28297
28399
|
const metrics = ctx.measureText(line);
|
|
28298
|
-
textX =
|
|
28400
|
+
textX = left + (boxWidth - metrics.width) / 2;
|
|
28299
28401
|
}
|
|
28300
28402
|
else if (this._private__textOptions.textAlign === 'right') {
|
|
28301
28403
|
const metrics = ctx.measureText(line);
|
|
28302
|
-
textX =
|
|
28404
|
+
textX = left + boxWidth - metrics.width - padding;
|
|
28303
28405
|
}
|
|
28304
|
-
const textY =
|
|
28406
|
+
const textY = top + padding + i * lineHeight;
|
|
28305
28407
|
ctx.fillText(line, textX, textY);
|
|
28306
28408
|
}
|
|
28307
28409
|
// Draw anchor point if selected
|
|
@@ -28345,6 +28447,9 @@
|
|
|
28345
28447
|
borderWidth: this._private__textOptions.borderWidth,
|
|
28346
28448
|
textAlign: this._private__textOptions.textAlign,
|
|
28347
28449
|
maxWidth: this._private__textOptions.maxWidth,
|
|
28450
|
+
anchor: this._private__textOptions.anchor,
|
|
28451
|
+
pointer: this._private__textOptions.pointer,
|
|
28452
|
+
borderRadius: this._private__textOptions.borderRadius,
|
|
28348
28453
|
},
|
|
28349
28454
|
extra: {
|
|
28350
28455
|
text: this._private__textOptions.text,
|
|
@@ -31132,7 +31237,7 @@
|
|
|
31132
31237
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
31133
31238
|
*/
|
|
31134
31239
|
function version() {
|
|
31135
|
-
return "2.3.
|
|
31240
|
+
return "2.3.13-dev+202609280001";
|
|
31136
31241
|
}
|
|
31137
31242
|
|
|
31138
31243
|
var PipsendChartsModule = /*#__PURE__*/Object.freeze({
|