hyperprop-charting-library 0.1.147 → 0.1.149
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/hyperprop-charting-library.cjs +165 -92
- package/dist/hyperprop-charting-library.d.ts +8 -0
- package/dist/hyperprop-charting-library.js +165 -92
- package/dist/index.cjs +165 -92
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +165 -92
- package/docs/API.md +43 -0
- package/package.json +1 -1
|
@@ -4261,6 +4261,8 @@ function createChart(element, options = {}) {
|
|
|
4261
4261
|
let paneButtonRegions = [];
|
|
4262
4262
|
let hoveredPaneId = null;
|
|
4263
4263
|
let hoveredPaneButton = null;
|
|
4264
|
+
let legendRowRegions = [];
|
|
4265
|
+
let hoveredLegendId = null;
|
|
4264
4266
|
let paneDividerDrag = null;
|
|
4265
4267
|
let indicatorPaneActionHandler = null;
|
|
4266
4268
|
let indicatorPaneHeightChangeHandler = null;
|
|
@@ -4268,6 +4270,7 @@ function createChart(element, options = {}) {
|
|
|
4268
4270
|
let actionDragState = null;
|
|
4269
4271
|
let pointerDownInfo = null;
|
|
4270
4272
|
let crosshairPoint = null;
|
|
4273
|
+
let externalCrosshair = null;
|
|
4271
4274
|
let doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
4272
4275
|
let doubleClickAction = mergedOptions.doubleClickAction;
|
|
4273
4276
|
setIndicatorLiveThrottleMs(mergedOptions.indicatorUpdate?.liveThrottleMs ?? 80);
|
|
@@ -5557,6 +5560,85 @@ function createChart(element, options = {}) {
|
|
|
5557
5560
|
ctx.closePath();
|
|
5558
5561
|
ctx.stroke();
|
|
5559
5562
|
};
|
|
5563
|
+
const INDICATOR_CONTROL_SIZE = 16;
|
|
5564
|
+
const INDICATOR_CONTROL_GAP = 4;
|
|
5565
|
+
const LEGEND_CONTROLS_WIDTH = (INDICATOR_CONTROL_SIZE + INDICATOR_CONTROL_GAP) * 4 + 8;
|
|
5566
|
+
const drawIndicatorControls = (indicatorId, indicatorType, indicatorVisible, startX, centerY) => {
|
|
5567
|
+
const labels = resolvedLabels;
|
|
5568
|
+
const actionList = [
|
|
5569
|
+
"visibility",
|
|
5570
|
+
"settings",
|
|
5571
|
+
"source",
|
|
5572
|
+
"remove"
|
|
5573
|
+
];
|
|
5574
|
+
let buttonX = startX;
|
|
5575
|
+
for (const action of actionList) {
|
|
5576
|
+
const buttonY = centerY - INDICATOR_CONTROL_SIZE / 2;
|
|
5577
|
+
const hovered = hoveredPaneButton?.id === indicatorId && hoveredPaneButton.action === action;
|
|
5578
|
+
const iconColor = labels.indicatorTextColor;
|
|
5579
|
+
ctx.save();
|
|
5580
|
+
ctx.fillStyle = hovered ? "rgba(148,163,184,0.30)" : "rgba(148,163,184,0.12)";
|
|
5581
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), INDICATOR_CONTROL_SIZE, INDICATOR_CONTROL_SIZE, 4);
|
|
5582
|
+
ctx.strokeStyle = iconColor;
|
|
5583
|
+
ctx.fillStyle = iconColor;
|
|
5584
|
+
ctx.globalAlpha = hovered ? 1 : 0.75;
|
|
5585
|
+
ctx.lineWidth = 1.2;
|
|
5586
|
+
ctx.setLineDash([]);
|
|
5587
|
+
const cx = buttonX + INDICATOR_CONTROL_SIZE / 2;
|
|
5588
|
+
const cy = centerY;
|
|
5589
|
+
if (action === "visibility") {
|
|
5590
|
+
ctx.beginPath();
|
|
5591
|
+
ctx.ellipse(cx, cy, 4.6, 3, 0, 0, Math.PI * 2);
|
|
5592
|
+
ctx.stroke();
|
|
5593
|
+
ctx.beginPath();
|
|
5594
|
+
ctx.arc(cx, cy, 1.3, 0, Math.PI * 2);
|
|
5595
|
+
ctx.fill();
|
|
5596
|
+
if (!indicatorVisible) {
|
|
5597
|
+
ctx.beginPath();
|
|
5598
|
+
ctx.moveTo(cx - 5.2, cy + 4.6);
|
|
5599
|
+
ctx.lineTo(cx + 5.2, cy - 4.6);
|
|
5600
|
+
ctx.stroke();
|
|
5601
|
+
}
|
|
5602
|
+
} else if (action === "settings") {
|
|
5603
|
+
ctx.beginPath();
|
|
5604
|
+
ctx.arc(cx, cy, 3.4, 0, Math.PI * 2);
|
|
5605
|
+
ctx.stroke();
|
|
5606
|
+
for (let toothIndex = 0; toothIndex < 8; toothIndex += 1) {
|
|
5607
|
+
const angle = Math.PI / 4 * toothIndex;
|
|
5608
|
+
ctx.beginPath();
|
|
5609
|
+
ctx.moveTo(cx + Math.cos(angle) * 3.4, cy + Math.sin(angle) * 3.4);
|
|
5610
|
+
ctx.lineTo(cx + Math.cos(angle) * 5.2, cy + Math.sin(angle) * 5.2);
|
|
5611
|
+
ctx.stroke();
|
|
5612
|
+
}
|
|
5613
|
+
ctx.beginPath();
|
|
5614
|
+
ctx.arc(cx, cy, 1.1, 0, Math.PI * 2);
|
|
5615
|
+
ctx.fill();
|
|
5616
|
+
} else if (action === "source") {
|
|
5617
|
+
const prevSourceFont = ctx.font;
|
|
5618
|
+
ctx.font = `bold 9px ${mergedOptions.fontFamily}`;
|
|
5619
|
+
drawText("{}", cx, cy + 0.5, "center", "middle", iconColor);
|
|
5620
|
+
ctx.font = prevSourceFont;
|
|
5621
|
+
} else {
|
|
5622
|
+
ctx.beginPath();
|
|
5623
|
+
ctx.moveTo(cx - 3.4, cy - 3.4);
|
|
5624
|
+
ctx.lineTo(cx + 3.4, cy + 3.4);
|
|
5625
|
+
ctx.moveTo(cx + 3.4, cy - 3.4);
|
|
5626
|
+
ctx.lineTo(cx - 3.4, cy + 3.4);
|
|
5627
|
+
ctx.stroke();
|
|
5628
|
+
}
|
|
5629
|
+
ctx.restore();
|
|
5630
|
+
paneButtonRegions.push({
|
|
5631
|
+
id: indicatorId,
|
|
5632
|
+
type: indicatorType,
|
|
5633
|
+
action,
|
|
5634
|
+
x: buttonX,
|
|
5635
|
+
y: buttonY,
|
|
5636
|
+
width: INDICATOR_CONTROL_SIZE,
|
|
5637
|
+
height: INDICATOR_CONTROL_SIZE
|
|
5638
|
+
});
|
|
5639
|
+
buttonX += INDICATOR_CONTROL_SIZE + INDICATOR_CONTROL_GAP;
|
|
5640
|
+
}
|
|
5641
|
+
};
|
|
5560
5642
|
const drawMarkBadge = (x, y, radius, color, shape, label, textColor) => {
|
|
5561
5643
|
ctx.save();
|
|
5562
5644
|
ctx.fillStyle = color;
|
|
@@ -5637,6 +5719,8 @@ function createChart(element, options = {}) {
|
|
|
5637
5719
|
orderDragRegions = [];
|
|
5638
5720
|
alertRegions = [];
|
|
5639
5721
|
markRegions = [];
|
|
5722
|
+
paneButtonRegions = [];
|
|
5723
|
+
legendRowRegions = [];
|
|
5640
5724
|
crosshairPriceActionRegion = null;
|
|
5641
5725
|
const pixelRatio = getPixelRatio();
|
|
5642
5726
|
canvas.style.width = `${width}px`;
|
|
@@ -7725,87 +7809,10 @@ function createChart(element, options = {}) {
|
|
|
7725
7809
|
}
|
|
7726
7810
|
paneLayoutFullChartHeight = fullChartHeight;
|
|
7727
7811
|
paneLayoutInfos = [];
|
|
7728
|
-
paneButtonRegions = [];
|
|
7729
7812
|
if (activeSeparateIndicators.length > 0) {
|
|
7730
7813
|
const xFromIndex = (index) => chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
7731
7814
|
let paneTopCursor = chartBottom + paneGap;
|
|
7732
|
-
const
|
|
7733
|
-
const paneButtonGap = 4;
|
|
7734
|
-
const drawPaneButtons = (indicatorId, indicatorType, indicatorVisible, startX, centerY) => {
|
|
7735
|
-
const actionList = [
|
|
7736
|
-
"visibility",
|
|
7737
|
-
"settings",
|
|
7738
|
-
"source",
|
|
7739
|
-
"remove"
|
|
7740
|
-
];
|
|
7741
|
-
let buttonX = startX;
|
|
7742
|
-
for (const action of actionList) {
|
|
7743
|
-
const buttonY = centerY - paneButtonSize / 2;
|
|
7744
|
-
const hovered = hoveredPaneButton?.id === indicatorId && hoveredPaneButton.action === action;
|
|
7745
|
-
const iconColor = labels.indicatorTextColor;
|
|
7746
|
-
ctx.save();
|
|
7747
|
-
ctx.fillStyle = hovered ? "rgba(148,163,184,0.30)" : "rgba(148,163,184,0.12)";
|
|
7748
|
-
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), paneButtonSize, paneButtonSize, 4);
|
|
7749
|
-
ctx.strokeStyle = iconColor;
|
|
7750
|
-
ctx.fillStyle = iconColor;
|
|
7751
|
-
ctx.globalAlpha = hovered ? 1 : 0.75;
|
|
7752
|
-
ctx.lineWidth = 1.2;
|
|
7753
|
-
ctx.setLineDash([]);
|
|
7754
|
-
const cx = buttonX + paneButtonSize / 2;
|
|
7755
|
-
const cy = centerY;
|
|
7756
|
-
if (action === "visibility") {
|
|
7757
|
-
ctx.beginPath();
|
|
7758
|
-
ctx.ellipse(cx, cy, 4.6, 3, 0, 0, Math.PI * 2);
|
|
7759
|
-
ctx.stroke();
|
|
7760
|
-
ctx.beginPath();
|
|
7761
|
-
ctx.arc(cx, cy, 1.3, 0, Math.PI * 2);
|
|
7762
|
-
ctx.fill();
|
|
7763
|
-
if (!indicatorVisible) {
|
|
7764
|
-
ctx.beginPath();
|
|
7765
|
-
ctx.moveTo(cx - 5.2, cy + 4.6);
|
|
7766
|
-
ctx.lineTo(cx + 5.2, cy - 4.6);
|
|
7767
|
-
ctx.stroke();
|
|
7768
|
-
}
|
|
7769
|
-
} else if (action === "settings") {
|
|
7770
|
-
ctx.beginPath();
|
|
7771
|
-
ctx.arc(cx, cy, 3.4, 0, Math.PI * 2);
|
|
7772
|
-
ctx.stroke();
|
|
7773
|
-
for (let toothIndex = 0; toothIndex < 8; toothIndex += 1) {
|
|
7774
|
-
const angle = Math.PI / 4 * toothIndex;
|
|
7775
|
-
ctx.beginPath();
|
|
7776
|
-
ctx.moveTo(cx + Math.cos(angle) * 3.4, cy + Math.sin(angle) * 3.4);
|
|
7777
|
-
ctx.lineTo(cx + Math.cos(angle) * 5.2, cy + Math.sin(angle) * 5.2);
|
|
7778
|
-
ctx.stroke();
|
|
7779
|
-
}
|
|
7780
|
-
ctx.beginPath();
|
|
7781
|
-
ctx.arc(cx, cy, 1.1, 0, Math.PI * 2);
|
|
7782
|
-
ctx.fill();
|
|
7783
|
-
} else if (action === "source") {
|
|
7784
|
-
const prevSourceFont = ctx.font;
|
|
7785
|
-
ctx.font = `bold 9px ${mergedOptions.fontFamily}`;
|
|
7786
|
-
drawText("{}", cx, cy + 0.5, "center", "middle", iconColor);
|
|
7787
|
-
ctx.font = prevSourceFont;
|
|
7788
|
-
} else {
|
|
7789
|
-
ctx.beginPath();
|
|
7790
|
-
ctx.moveTo(cx - 3.4, cy - 3.4);
|
|
7791
|
-
ctx.lineTo(cx + 3.4, cy + 3.4);
|
|
7792
|
-
ctx.moveTo(cx + 3.4, cy - 3.4);
|
|
7793
|
-
ctx.lineTo(cx - 3.4, cy + 3.4);
|
|
7794
|
-
ctx.stroke();
|
|
7795
|
-
}
|
|
7796
|
-
ctx.restore();
|
|
7797
|
-
paneButtonRegions.push({
|
|
7798
|
-
id: indicatorId,
|
|
7799
|
-
type: indicatorType,
|
|
7800
|
-
action,
|
|
7801
|
-
x: buttonX,
|
|
7802
|
-
y: buttonY,
|
|
7803
|
-
width: paneButtonSize,
|
|
7804
|
-
height: paneButtonSize
|
|
7805
|
-
});
|
|
7806
|
-
buttonX += paneButtonSize + paneButtonGap;
|
|
7807
|
-
}
|
|
7808
|
-
};
|
|
7815
|
+
const drawPaneButtons = drawIndicatorControls;
|
|
7809
7816
|
activeSeparateIndicators.forEach(({ indicator, plugin }, paneIndex) => {
|
|
7810
7817
|
const paneHeight = separatePaneHeights[paneIndex] ?? 80;
|
|
7811
7818
|
const paneTop = paneTopCursor;
|
|
@@ -8307,26 +8314,56 @@ function createChart(element, options = {}) {
|
|
|
8307
8314
|
};
|
|
8308
8315
|
const labelEntries = activeOverlayIndicators.map(({ indicator, plugin }) => {
|
|
8309
8316
|
const inputValues = Object.entries(indicator.inputs).filter(([key, value]) => !LEGEND_EXCLUDED_INPUT_KEYS.has(key) && typeof value !== "boolean" && isLegendInputValue(value)).slice(0, 2).map(([, value]) => formatLegendValue(value));
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
if (labels.showIndicatorNames) {
|
|
8314
|
-
return plugin.name;
|
|
8315
|
-
}
|
|
8316
|
-
return inputValues.join(" ");
|
|
8317
|
-
}).filter((entry) => entry.length > 0);
|
|
8317
|
+
const text = labels.showIndicatorNames && labels.showIndicatorValues && inputValues.length > 0 ? `${plugin.name} ${inputValues.join(" ")}` : labels.showIndicatorNames ? plugin.name : inputValues.join(" ");
|
|
8318
|
+
return { id: indicator.id, type: indicator.type, visible: indicator.visible, text };
|
|
8319
|
+
}).filter((entry) => entry.text.length > 0);
|
|
8318
8320
|
if (labelEntries.length > 0) {
|
|
8319
8321
|
const prevFont = ctx.font;
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
+
const legendFontSize = Math.max(8, axis.fontSize);
|
|
8323
|
+
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
8322
8324
|
const offsetX = Math.max(0, Number(labels.indicatorLegendOffsetX) || 0);
|
|
8323
8325
|
const offsetY = Math.max(0, Number(labels.indicatorLegendOffsetY) || 0);
|
|
8324
8326
|
const position = labels.indicatorLegendPosition;
|
|
8325
8327
|
const isRight = position === "top-right" || position === "bottom-right";
|
|
8326
8328
|
const isBottom = position === "bottom-left" || position === "bottom-right";
|
|
8327
8329
|
const legendX = isRight ? chartRight - offsetX : chartLeft + offsetX;
|
|
8328
|
-
const
|
|
8329
|
-
|
|
8330
|
+
const legendTop = isBottom ? chartBottom - offsetY : Math.max(chartTop + offsetY, dataLineBottom);
|
|
8331
|
+
const rowHeight = Math.round(legendFontSize * 1.55);
|
|
8332
|
+
labelEntries.forEach((entry, rowIndex) => {
|
|
8333
|
+
const rowTop = isBottom ? legendTop - (labelEntries.length - rowIndex) * rowHeight : legendTop + rowIndex * rowHeight;
|
|
8334
|
+
const rowCenter = rowTop + rowHeight / 2;
|
|
8335
|
+
const dimmed = entry.visible === false;
|
|
8336
|
+
ctx.save();
|
|
8337
|
+
if (dimmed) ctx.globalAlpha = 0.45;
|
|
8338
|
+
drawText(
|
|
8339
|
+
entry.text,
|
|
8340
|
+
legendX,
|
|
8341
|
+
rowCenter,
|
|
8342
|
+
isRight ? "right" : "left",
|
|
8343
|
+
"middle",
|
|
8344
|
+
labels.indicatorTextColor
|
|
8345
|
+
);
|
|
8346
|
+
ctx.restore();
|
|
8347
|
+
const textWidth = measureTextWidth(entry.text);
|
|
8348
|
+
const rowLeft = isRight ? legendX - textWidth : legendX;
|
|
8349
|
+
legendRowRegions.push({
|
|
8350
|
+
id: entry.id,
|
|
8351
|
+
type: entry.type,
|
|
8352
|
+
x: rowLeft,
|
|
8353
|
+
y: rowTop,
|
|
8354
|
+
width: textWidth + LEGEND_CONTROLS_WIDTH,
|
|
8355
|
+
height: rowHeight
|
|
8356
|
+
});
|
|
8357
|
+
if (hoveredLegendId === entry.id) {
|
|
8358
|
+
drawIndicatorControls(
|
|
8359
|
+
entry.id,
|
|
8360
|
+
entry.type,
|
|
8361
|
+
entry.visible !== false,
|
|
8362
|
+
isRight ? legendX + 6 : rowLeft + textWidth + 8,
|
|
8363
|
+
rowCenter
|
|
8364
|
+
);
|
|
8365
|
+
}
|
|
8366
|
+
});
|
|
8330
8367
|
ctx.font = prevFont;
|
|
8331
8368
|
}
|
|
8332
8369
|
}
|
|
@@ -8436,7 +8473,26 @@ function createChart(element, options = {}) {
|
|
|
8436
8473
|
crosshairPriceActionRegion = null;
|
|
8437
8474
|
const layout = overlayLayout;
|
|
8438
8475
|
const crosshair = resolvedCrosshair;
|
|
8439
|
-
if (!layout
|
|
8476
|
+
if (!layout) return;
|
|
8477
|
+
if (!crosshairPoint && externalCrosshair !== null && crosshair.visible) {
|
|
8478
|
+
const index = findNearestIndexForTimeMs(externalCrosshair.timeMs);
|
|
8479
|
+
if (index !== null) {
|
|
8480
|
+
const x = layout.chartLeft + (index + 0.5 - layout.xStart) / layout.xSpan * layout.chartWidth;
|
|
8481
|
+
if (x >= layout.chartLeft && x <= layout.chartRight) {
|
|
8482
|
+
ctx.save();
|
|
8483
|
+
ctx.globalAlpha = 0.55;
|
|
8484
|
+
ctx.strokeStyle = crosshair.color;
|
|
8485
|
+
ctx.lineWidth = Math.max(1, crosshair.width);
|
|
8486
|
+
applyDashPattern(crosshair.style, dashPatterns.dotted, dashPatterns.dashed);
|
|
8487
|
+
ctx.beginPath();
|
|
8488
|
+
ctx.moveTo(crisp(x), crisp(layout.chartTop));
|
|
8489
|
+
ctx.lineTo(crisp(x), crisp(layout.fullChartBottom));
|
|
8490
|
+
ctx.stroke();
|
|
8491
|
+
ctx.restore();
|
|
8492
|
+
}
|
|
8493
|
+
}
|
|
8494
|
+
}
|
|
8495
|
+
if (!crosshair.visible || !crosshairPoint) {
|
|
8440
8496
|
return;
|
|
8441
8497
|
}
|
|
8442
8498
|
const { chartLeft, chartTop, chartRight, chartBottom, chartWidth, chartHeight, fullChartBottom, yMin, yRange, xStart, xSpan: xSpan2 } = layout;
|
|
@@ -8998,6 +9054,9 @@ function createChart(element, options = {}) {
|
|
|
8998
9054
|
if (hits.length === 0) return null;
|
|
8999
9055
|
return hits.find((region) => region.part === "remove") ?? hits[0];
|
|
9000
9056
|
};
|
|
9057
|
+
const getLegendRowAt = (x, y) => legendRowRegions.find(
|
|
9058
|
+
(region) => x >= region.x && x <= region.x + region.width && y >= region.y && y <= region.y + region.height
|
|
9059
|
+
) ?? null;
|
|
9001
9060
|
const getMarkAt = (x, y) => {
|
|
9002
9061
|
const tolerance = touchInputActive ? Math.max(1, mergedOptions.touch?.hitToleranceScale ?? 2.2) : 1;
|
|
9003
9062
|
for (let index = markRegions.length - 1; index >= 0; index -= 1) {
|
|
@@ -10747,6 +10806,12 @@ function createChart(element, options = {}) {
|
|
|
10747
10806
|
setCrosshairPoint(null);
|
|
10748
10807
|
return;
|
|
10749
10808
|
}
|
|
10809
|
+
const legendRow = getLegendRowAt(point.x, point.y);
|
|
10810
|
+
const nextLegendId = legendRow?.id ?? null;
|
|
10811
|
+
if (nextLegendId !== hoveredLegendId) {
|
|
10812
|
+
hoveredLegendId = nextLegendId;
|
|
10813
|
+
scheduleDraw();
|
|
10814
|
+
}
|
|
10750
10815
|
const hoveredPane = getPaneAt(point.x, point.y);
|
|
10751
10816
|
const nextHoveredPaneId = hoveredPane?.id ?? null;
|
|
10752
10817
|
if (nextHoveredPaneId !== hoveredPaneId) {
|
|
@@ -10965,10 +11030,11 @@ function createChart(element, options = {}) {
|
|
|
10965
11030
|
});
|
|
10966
11031
|
paneDividerDrag = null;
|
|
10967
11032
|
}
|
|
10968
|
-
if (event?.type === "pointerleave" && (hoveredPaneId !== null || hoveredPaneButton !== null || hoveredAlertId !== null || hoveredMarkKey !== null)) {
|
|
11033
|
+
if (event?.type === "pointerleave" && (hoveredPaneId !== null || hoveredPaneButton !== null || hoveredAlertId !== null || hoveredMarkKey !== null || hoveredLegendId !== null)) {
|
|
10969
11034
|
hoveredPaneId = null;
|
|
10970
11035
|
hoveredPaneButton = null;
|
|
10971
11036
|
hoveredAlertId = null;
|
|
11037
|
+
hoveredLegendId = null;
|
|
10972
11038
|
if (hoveredMarkKey !== null) {
|
|
10973
11039
|
hoveredMarkKey = null;
|
|
10974
11040
|
markHoverHandler?.(null);
|
|
@@ -11908,6 +11974,12 @@ function createChart(element, options = {}) {
|
|
|
11908
11974
|
const onAlertAction = (handler) => {
|
|
11909
11975
|
alertActionHandler = handler;
|
|
11910
11976
|
};
|
|
11977
|
+
const setExternalCrosshair = (point) => {
|
|
11978
|
+
const nextMs = point && Number.isFinite(point.timeMs) ? point.timeMs : null;
|
|
11979
|
+
if (nextMs === (externalCrosshair?.timeMs ?? null)) return;
|
|
11980
|
+
externalCrosshair = nextMs === null ? null : { timeMs: nextMs };
|
|
11981
|
+
scheduleDraw({ overlayOnly: true });
|
|
11982
|
+
};
|
|
11911
11983
|
const setTimezone = (timezone) => {
|
|
11912
11984
|
timezoneSetting = timezone || "local";
|
|
11913
11985
|
zoneClock = createZoneClock(timezoneSetting);
|
|
@@ -12218,6 +12290,7 @@ function createChart(element, options = {}) {
|
|
|
12218
12290
|
saveState,
|
|
12219
12291
|
loadState,
|
|
12220
12292
|
takeScreenshot,
|
|
12293
|
+
setExternalCrosshair,
|
|
12221
12294
|
setTimezone,
|
|
12222
12295
|
getTimezone,
|
|
12223
12296
|
setTimeFormat,
|