hyperprop-charting-library 0.1.139 → 0.1.141
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 +434 -49
- package/dist/hyperprop-charting-library.d.ts +131 -1
- package/dist/hyperprop-charting-library.js +432 -49
- package/dist/index.cjs +434 -49
- package/dist/index.d.cts +131 -1
- package/dist/index.d.ts +131 -1
- package/dist/index.js +432 -49
- package/docs/API.md +55 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2623,6 +2623,88 @@ var compileScriptIndicator = (definition) => {
|
|
|
2623
2623
|
return plugin;
|
|
2624
2624
|
};
|
|
2625
2625
|
|
|
2626
|
+
// src/themes.ts
|
|
2627
|
+
var CHART_THEMES = {
|
|
2628
|
+
dark: {
|
|
2629
|
+
name: "dark",
|
|
2630
|
+
background: "#0f0f0f",
|
|
2631
|
+
upColor: "#089981",
|
|
2632
|
+
downColor: "#f23645",
|
|
2633
|
+
lineColor: "#2962ff",
|
|
2634
|
+
gridColor: "#3c3c3c",
|
|
2635
|
+
gridOpacity: 0.5,
|
|
2636
|
+
axisTextColor: "#dbdbdb",
|
|
2637
|
+
axisLineColor: "#424242",
|
|
2638
|
+
crosshairColor: "#9598a1",
|
|
2639
|
+
crosshairLabelBackground: "#3c3c3c",
|
|
2640
|
+
crosshairLabelText: "#dbdbdb",
|
|
2641
|
+
crosshairLabelBorder: "#5d5d5d",
|
|
2642
|
+
watermarkColor: "rgba(219,219,219,0.06)",
|
|
2643
|
+
indicatorTextColor: "#b2b5be",
|
|
2644
|
+
labelTextColor: "#ffffff",
|
|
2645
|
+
labelBackground: "#1a1a1a"
|
|
2646
|
+
},
|
|
2647
|
+
light: {
|
|
2648
|
+
name: "light",
|
|
2649
|
+
background: "#ffffff",
|
|
2650
|
+
upColor: "#089981",
|
|
2651
|
+
downColor: "#f23645",
|
|
2652
|
+
lineColor: "#2962ff",
|
|
2653
|
+
gridColor: "#d5d5d5",
|
|
2654
|
+
gridOpacity: 0.9,
|
|
2655
|
+
axisTextColor: "#0f0f0f",
|
|
2656
|
+
axisLineColor: "#c3c3c3",
|
|
2657
|
+
crosshairColor: "#787b86",
|
|
2658
|
+
crosshairLabelBackground: "#4b4b4b",
|
|
2659
|
+
crosshairLabelText: "#ffffff",
|
|
2660
|
+
crosshairLabelBorder: "#878787",
|
|
2661
|
+
watermarkColor: "rgba(15,15,15,0.06)",
|
|
2662
|
+
indicatorTextColor: "#4b4b4b",
|
|
2663
|
+
labelTextColor: "#ffffff",
|
|
2664
|
+
labelBackground: "#f0f3fa"
|
|
2665
|
+
},
|
|
2666
|
+
midnight: {
|
|
2667
|
+
name: "midnight",
|
|
2668
|
+
background: "#171717",
|
|
2669
|
+
upColor: "#22ab94",
|
|
2670
|
+
downColor: "#f23645",
|
|
2671
|
+
lineColor: "#2563eb",
|
|
2672
|
+
gridColor: "#2b2f38",
|
|
2673
|
+
gridOpacity: 0.38,
|
|
2674
|
+
axisTextColor: "#dbe4f0",
|
|
2675
|
+
axisLineColor: "#5f646d",
|
|
2676
|
+
crosshairColor: "#94a3b8",
|
|
2677
|
+
crosshairLabelBackground: "#6b6f76",
|
|
2678
|
+
crosshairLabelText: "#e2e8f0",
|
|
2679
|
+
crosshairLabelBorder: "#e2e8f0",
|
|
2680
|
+
watermarkColor: "rgba(226,232,240,0.05)",
|
|
2681
|
+
indicatorTextColor: "#cbd5e1",
|
|
2682
|
+
labelTextColor: "#dbeafe",
|
|
2683
|
+
labelBackground: "#0b1220"
|
|
2684
|
+
},
|
|
2685
|
+
"high-contrast": {
|
|
2686
|
+
name: "high-contrast",
|
|
2687
|
+
background: "#000000",
|
|
2688
|
+
upColor: "#00e5a0",
|
|
2689
|
+
downColor: "#ff4d5e",
|
|
2690
|
+
lineColor: "#4d9fff",
|
|
2691
|
+
gridColor: "#5a5a5a",
|
|
2692
|
+
gridOpacity: 0.7,
|
|
2693
|
+
axisTextColor: "#ffffff",
|
|
2694
|
+
axisLineColor: "#8a8a8a",
|
|
2695
|
+
crosshairColor: "#ffffff",
|
|
2696
|
+
crosshairLabelBackground: "#ffffff",
|
|
2697
|
+
crosshairLabelText: "#000000",
|
|
2698
|
+
crosshairLabelBorder: "#ffffff",
|
|
2699
|
+
watermarkColor: "rgba(255,255,255,0.08)",
|
|
2700
|
+
indicatorTextColor: "#ffffff",
|
|
2701
|
+
labelTextColor: "#000000",
|
|
2702
|
+
labelBackground: "#1a1a1a"
|
|
2703
|
+
}
|
|
2704
|
+
};
|
|
2705
|
+
var CHART_THEME_NAMES = Object.keys(CHART_THEMES);
|
|
2706
|
+
var resolveTheme = (theme) => typeof theme === "string" ? CHART_THEMES[theme] ?? CHART_THEMES.dark : theme;
|
|
2707
|
+
|
|
2626
2708
|
// src/options.ts
|
|
2627
2709
|
var DEFAULT_GRID_OPTIONS = {
|
|
2628
2710
|
color: "#2b2f38",
|
|
@@ -2822,6 +2904,8 @@ var DEFAULT_OPTIONS = {
|
|
|
2822
2904
|
keyboard: { enabled: true, panBars: 1, deleteSelectedDrawing: true },
|
|
2823
2905
|
accessibility: { label: "Price chart", description: "", focusable: true },
|
|
2824
2906
|
downsampling: { enabled: true, thresholdPx: 1.5 },
|
|
2907
|
+
touch: { hitToleranceScale: 2.2, longPressTooltip: true, longPressMs: 400 },
|
|
2908
|
+
datafeedOptions: { prefetchThresholdBars: 150, cooldownMs: 1200, chunkBars: 1500 },
|
|
2825
2909
|
crosshair: DEFAULT_CROSSHAIR_OPTIONS,
|
|
2826
2910
|
grid: DEFAULT_GRID_OPTIONS,
|
|
2827
2911
|
watermark: DEFAULT_WATERMARK_OPTIONS,
|
|
@@ -2876,6 +2960,14 @@ var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
|
2876
2960
|
...baseOptions.downsampling,
|
|
2877
2961
|
...options.downsampling ?? {}
|
|
2878
2962
|
},
|
|
2963
|
+
touch: {
|
|
2964
|
+
...baseOptions.touch,
|
|
2965
|
+
...options.touch ?? {}
|
|
2966
|
+
},
|
|
2967
|
+
datafeedOptions: {
|
|
2968
|
+
...baseOptions.datafeedOptions,
|
|
2969
|
+
...options.datafeedOptions ?? {}
|
|
2970
|
+
},
|
|
2879
2971
|
crosshair: {
|
|
2880
2972
|
...baseOptions.crosshair,
|
|
2881
2973
|
...options.crosshair ?? {}
|
|
@@ -3050,10 +3142,12 @@ function createChart(element, options = {}) {
|
|
|
3050
3142
|
let drawingDoubleClickHandler = null;
|
|
3051
3143
|
let drawingEditTextHandler = null;
|
|
3052
3144
|
let selectionChangeHandler = null;
|
|
3145
|
+
let longPressHandler = null;
|
|
3053
3146
|
let contextMenuHandler = null;
|
|
3054
3147
|
let keyboardShortcutHandler = null;
|
|
3055
3148
|
let lastSelectionSignature = null;
|
|
3056
3149
|
let magnetMode = "none";
|
|
3150
|
+
let activeThemeName = null;
|
|
3057
3151
|
let priceScaleMode = "linear";
|
|
3058
3152
|
let priceScaleInverted = false;
|
|
3059
3153
|
const PRICE_SCALE_LOG_FLOOR = 1e-9;
|
|
@@ -3809,6 +3903,92 @@ function createChart(element, options = {}) {
|
|
|
3809
3903
|
scheduleDraw({ updateAutoScale: true });
|
|
3810
3904
|
};
|
|
3811
3905
|
const getCompareSeries = () => compareSeriesStates.map((state) => state.options);
|
|
3906
|
+
let datafeed = null;
|
|
3907
|
+
let datafeedUnsubscribe = null;
|
|
3908
|
+
let datafeedLoading = false;
|
|
3909
|
+
let datafeedExhausted = false;
|
|
3910
|
+
let datafeedLastRequestAt = 0;
|
|
3911
|
+
const estimateBarStepMs = () => {
|
|
3912
|
+
if (mergedOptions.timeStepMs > 0) return mergedOptions.timeStepMs;
|
|
3913
|
+
if (data.length < 2) return 6e4;
|
|
3914
|
+
const span = data[data.length - 1].time.getTime() - data[0].time.getTime();
|
|
3915
|
+
return Math.max(1e3, span / (data.length - 1));
|
|
3916
|
+
};
|
|
3917
|
+
const requestDatafeedBars = async (request) => {
|
|
3918
|
+
if (!datafeed) return [];
|
|
3919
|
+
try {
|
|
3920
|
+
return await datafeed.getBars(request) ?? [];
|
|
3921
|
+
} catch (error) {
|
|
3922
|
+
datafeed.onError?.(error, request);
|
|
3923
|
+
return [];
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
const maybeLoadOlderHistory = () => {
|
|
3927
|
+
if (!datafeed || datafeedLoading || datafeedExhausted || data.length === 0) return;
|
|
3928
|
+
const options2 = mergedOptions.datafeedOptions ?? DEFAULT_OPTIONS.datafeedOptions;
|
|
3929
|
+
const threshold = options2?.prefetchThresholdBars ?? 150;
|
|
3930
|
+
const cooldown = options2?.cooldownMs ?? 1200;
|
|
3931
|
+
if (Date.now() - datafeedLastRequestAt < cooldown) return;
|
|
3932
|
+
if (xCenter - xSpan / 2 > threshold) return;
|
|
3933
|
+
const stepMs = estimateBarStepMs();
|
|
3934
|
+
const chunk = Math.max(10, options2?.chunkBars ?? 1500);
|
|
3935
|
+
const toMs = data[0].time.getTime();
|
|
3936
|
+
datafeedLoading = true;
|
|
3937
|
+
datafeedLastRequestAt = Date.now();
|
|
3938
|
+
void requestDatafeedBars({
|
|
3939
|
+
fromMs: toMs - chunk * stepMs,
|
|
3940
|
+
toMs,
|
|
3941
|
+
countBack: chunk,
|
|
3942
|
+
firstRequest: false
|
|
3943
|
+
}).then((bars) => {
|
|
3944
|
+
const older = bars.filter((bar) => new Date(bar.t).getTime() < toMs);
|
|
3945
|
+
if (older.length === 0) {
|
|
3946
|
+
datafeedExhausted = true;
|
|
3947
|
+
return;
|
|
3948
|
+
}
|
|
3949
|
+
const merged = [...older, ...data.map((bar) => ({
|
|
3950
|
+
t: bar.time.toISOString(),
|
|
3951
|
+
o: bar.o,
|
|
3952
|
+
h: bar.h,
|
|
3953
|
+
l: bar.l,
|
|
3954
|
+
c: bar.c,
|
|
3955
|
+
...bar.v === void 0 ? {} : { v: bar.v }
|
|
3956
|
+
}))];
|
|
3957
|
+
setData(merged);
|
|
3958
|
+
}).finally(() => {
|
|
3959
|
+
datafeedLoading = false;
|
|
3960
|
+
});
|
|
3961
|
+
};
|
|
3962
|
+
const setDatafeed = async (nextDatafeed) => {
|
|
3963
|
+
datafeedUnsubscribe?.();
|
|
3964
|
+
datafeedUnsubscribe = null;
|
|
3965
|
+
datafeed = nextDatafeed;
|
|
3966
|
+
datafeedExhausted = false;
|
|
3967
|
+
datafeedLoading = false;
|
|
3968
|
+
datafeedLastRequestAt = 0;
|
|
3969
|
+
if (!nextDatafeed) return;
|
|
3970
|
+
await nextDatafeed.onReady?.();
|
|
3971
|
+
if (datafeed !== nextDatafeed) return;
|
|
3972
|
+
const stepMs = estimateBarStepMs();
|
|
3973
|
+
const countBack = Math.max(50, Math.round(mergedOptions.initialVisibleBars * 3));
|
|
3974
|
+
const toMs = Date.now();
|
|
3975
|
+
datafeedLoading = true;
|
|
3976
|
+
const bars = await requestDatafeedBars({
|
|
3977
|
+
fromMs: toMs - countBack * stepMs,
|
|
3978
|
+
toMs,
|
|
3979
|
+
countBack,
|
|
3980
|
+
firstRequest: true
|
|
3981
|
+
});
|
|
3982
|
+
datafeedLoading = false;
|
|
3983
|
+
if (datafeed !== nextDatafeed) return;
|
|
3984
|
+
if (bars.length > 0) {
|
|
3985
|
+
setData(bars);
|
|
3986
|
+
}
|
|
3987
|
+
const unsubscribe = nextDatafeed.subscribeBars?.((bar) => {
|
|
3988
|
+
if (datafeed === nextDatafeed) upsertBar(bar);
|
|
3989
|
+
});
|
|
3990
|
+
datafeedUnsubscribe = typeof unsubscribe === "function" ? unsubscribe : null;
|
|
3991
|
+
};
|
|
3812
3992
|
const formatHoverTimeLabel = (time, mode) => {
|
|
3813
3993
|
if (mode === "time") {
|
|
3814
3994
|
return time.toLocaleTimeString(void 0, {
|
|
@@ -6803,6 +6983,7 @@ function createChart(element, options = {}) {
|
|
|
6803
6983
|
};
|
|
6804
6984
|
paintCrosshairOverlay();
|
|
6805
6985
|
emitSelectionChangeIfMoved();
|
|
6986
|
+
maybeLoadOlderHistory();
|
|
6806
6987
|
};
|
|
6807
6988
|
const paintCrosshairOverlay = () => {
|
|
6808
6989
|
crosshairPriceActionRegion = null;
|
|
@@ -6995,6 +7176,67 @@ function createChart(element, options = {}) {
|
|
|
6995
7176
|
drawText(timeText, timeX + labelPaddingX, timeY + timeHeight / 2, "left", "middle", labelTextColor);
|
|
6996
7177
|
}
|
|
6997
7178
|
}
|
|
7179
|
+
if (longPressState && (mergedOptions.touch?.longPressTooltip ?? true)) {
|
|
7180
|
+
const index = indexFromCanvasX(cx);
|
|
7181
|
+
const bar = index === null ? void 0 : data[index];
|
|
7182
|
+
if (bar) {
|
|
7183
|
+
const barTime = getTimeForIndex(index);
|
|
7184
|
+
const changeAbs = bar.c - bar.o;
|
|
7185
|
+
const changePct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
7186
|
+
const rows = [
|
|
7187
|
+
["O", formatPrice(bar.o), null],
|
|
7188
|
+
["H", formatPrice(bar.h), null],
|
|
7189
|
+
["L", formatPrice(bar.l), null],
|
|
7190
|
+
["C", formatPrice(bar.c), null],
|
|
7191
|
+
[
|
|
7192
|
+
"Chg",
|
|
7193
|
+
`${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${changePct.toFixed(2)}%)`,
|
|
7194
|
+
changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor
|
|
7195
|
+
]
|
|
7196
|
+
];
|
|
7197
|
+
if (bar.v !== void 0) {
|
|
7198
|
+
rows.push([
|
|
7199
|
+
"Vol",
|
|
7200
|
+
bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v)),
|
|
7201
|
+
null
|
|
7202
|
+
]);
|
|
7203
|
+
}
|
|
7204
|
+
const prevFont = ctx.font;
|
|
7205
|
+
const fontSize = 11;
|
|
7206
|
+
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
7207
|
+
const headerText = barTime ? formatHoverTimeLabel(barTime, "auto") : "";
|
|
7208
|
+
const rowGap = 3;
|
|
7209
|
+
const padding = 8;
|
|
7210
|
+
const labelColumn = 26;
|
|
7211
|
+
const contentWidth = Math.max(
|
|
7212
|
+
measureTextWidth(headerText),
|
|
7213
|
+
...rows.map(([, value]) => labelColumn + measureTextWidth(value))
|
|
7214
|
+
);
|
|
7215
|
+
const boxWidth = Math.ceil(contentWidth) + padding * 2;
|
|
7216
|
+
const boxHeight = padding * 2 + (fontSize + rowGap) * (rows.length + (headerText ? 1 : 0)) - rowGap;
|
|
7217
|
+
const fingerGap = 26;
|
|
7218
|
+
const boxX = cx + fingerGap + boxWidth <= chartRight ? cx + fingerGap : Math.max(chartLeft + 4, cx - fingerGap - boxWidth);
|
|
7219
|
+
const boxY = clamp(cy - boxHeight - fingerGap, chartTop + 4, chartBottom - boxHeight - 4);
|
|
7220
|
+
ctx.save();
|
|
7221
|
+
ctx.fillStyle = "rgba(16,17,20,0.94)";
|
|
7222
|
+
fillRoundedRect(Math.round(boxX), Math.round(boxY), boxWidth, boxHeight, 6);
|
|
7223
|
+
ctx.strokeStyle = "rgba(255,255,255,0.14)";
|
|
7224
|
+
ctx.lineWidth = 1;
|
|
7225
|
+
ctx.strokeRect(Math.round(boxX) + 0.5, Math.round(boxY) + 0.5, boxWidth - 1, boxHeight - 1);
|
|
7226
|
+
let textY = boxY + padding + fontSize / 2;
|
|
7227
|
+
if (headerText) {
|
|
7228
|
+
drawText(headerText, boxX + padding, textY, "left", "middle", "rgba(255,255,255,0.55)");
|
|
7229
|
+
textY += fontSize + rowGap;
|
|
7230
|
+
}
|
|
7231
|
+
for (const [label, value, valueColor] of rows) {
|
|
7232
|
+
drawText(label, boxX + padding, textY, "left", "middle", "rgba(255,255,255,0.5)");
|
|
7233
|
+
drawText(value, boxX + padding + labelColumn, textY, "left", "middle", valueColor ?? "#e6e8ee");
|
|
7234
|
+
textY += fontSize + rowGap;
|
|
7235
|
+
}
|
|
7236
|
+
ctx.restore();
|
|
7237
|
+
ctx.font = prevFont;
|
|
7238
|
+
}
|
|
7239
|
+
}
|
|
6998
7240
|
};
|
|
6999
7241
|
const drawOverlayOnly = () => {
|
|
7000
7242
|
if (!baseCtx || !overlayLayout || baseCanvas.width !== canvas.width || baseCanvas.height !== canvas.height || baseCanvas.width === 0) {
|
|
@@ -7504,6 +7746,7 @@ function createChart(element, options = {}) {
|
|
|
7504
7746
|
return Math.hypot(x - (x1 + t * dx), y - (y1 + t * dy));
|
|
7505
7747
|
};
|
|
7506
7748
|
const getDrawingHit = (x, y) => {
|
|
7749
|
+
const hitTolerance = touchInputActive ? Math.max(1, mergedOptions.touch?.hitToleranceScale ?? 2.2) : 1;
|
|
7507
7750
|
for (let index = drawings.length - 1; index >= 0; index -= 1) {
|
|
7508
7751
|
const drawing = drawings[index];
|
|
7509
7752
|
if (!drawing?.visible) continue;
|
|
@@ -7512,10 +7755,10 @@ function createChart(element, options = {}) {
|
|
|
7512
7755
|
if (!point) continue;
|
|
7513
7756
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
7514
7757
|
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
7515
|
-
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
7758
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8 * hitTolerance) {
|
|
7516
7759
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7517
7760
|
}
|
|
7518
|
-
if (Math.abs(y - lineY) <= 7) {
|
|
7761
|
+
if (Math.abs(y - lineY) <= 7 * hitTolerance) {
|
|
7519
7762
|
return { drawing, target: "line" };
|
|
7520
7763
|
}
|
|
7521
7764
|
} else if (drawing.type === "vertical-line") {
|
|
@@ -7523,10 +7766,10 @@ function createChart(element, options = {}) {
|
|
|
7523
7766
|
if (!point) continue;
|
|
7524
7767
|
const lineX = canvasXFromDrawingPoint(point);
|
|
7525
7768
|
const handleY = drawState ? (drawState.chartTop + drawState.chartBottom) / 2 : 0;
|
|
7526
|
-
if (Math.hypot(x - lineX, y - handleY) <= 8) {
|
|
7769
|
+
if (Math.hypot(x - lineX, y - handleY) <= 8 * hitTolerance) {
|
|
7527
7770
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7528
7771
|
}
|
|
7529
|
-
if (Math.abs(x - lineX) <= 7) {
|
|
7772
|
+
if (Math.abs(x - lineX) <= 7 * hitTolerance) {
|
|
7530
7773
|
return { drawing, target: "line" };
|
|
7531
7774
|
}
|
|
7532
7775
|
} else if (drawing.type === "trendline") {
|
|
@@ -7537,13 +7780,13 @@ function createChart(element, options = {}) {
|
|
|
7537
7780
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7538
7781
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7539
7782
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7540
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7783
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7541
7784
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7542
7785
|
}
|
|
7543
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7786
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7544
7787
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7545
7788
|
}
|
|
7546
|
-
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
7789
|
+
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7547
7790
|
return { drawing, target: "line" };
|
|
7548
7791
|
}
|
|
7549
7792
|
} else if (drawing.type === "ray") {
|
|
@@ -7554,10 +7797,10 @@ function createChart(element, options = {}) {
|
|
|
7554
7797
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7555
7798
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7556
7799
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7557
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7800
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7558
7801
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7559
7802
|
}
|
|
7560
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7803
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7561
7804
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7562
7805
|
}
|
|
7563
7806
|
const dx = x2 - x1;
|
|
@@ -7567,7 +7810,7 @@ function createChart(element, options = {}) {
|
|
|
7567
7810
|
const t = Math.max(0, ((x - x1) * dx + (y - y1) * dy) / lengthSq);
|
|
7568
7811
|
const projX = x1 + t * dx;
|
|
7569
7812
|
const projY = y1 + t * dy;
|
|
7570
|
-
if (Math.hypot(x - projX, y - projY) <= 6) {
|
|
7813
|
+
if (Math.hypot(x - projX, y - projY) <= 6 * hitTolerance) {
|
|
7571
7814
|
return { drawing, target: "line" };
|
|
7572
7815
|
}
|
|
7573
7816
|
}
|
|
@@ -7579,17 +7822,17 @@ function createChart(element, options = {}) {
|
|
|
7579
7822
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7580
7823
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7581
7824
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7582
|
-
if (Math.hypot(x - x1, y - y1) <= 9) {
|
|
7825
|
+
if (Math.hypot(x - x1, y - y1) <= 9 * hitTolerance) {
|
|
7583
7826
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7584
7827
|
}
|
|
7585
|
-
if (Math.hypot(x - x2, y - y2) <= 9) {
|
|
7828
|
+
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
7586
7829
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7587
7830
|
}
|
|
7588
7831
|
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
7589
7832
|
for (const ratio of fibRatios) {
|
|
7590
7833
|
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
7591
7834
|
const lineY = canvasYFromDrawingPrice(price);
|
|
7592
|
-
if (Math.abs(y - lineY) <= 5) {
|
|
7835
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
7593
7836
|
return { drawing, target: "line" };
|
|
7594
7837
|
}
|
|
7595
7838
|
}
|
|
@@ -7602,30 +7845,30 @@ function createChart(element, options = {}) {
|
|
|
7602
7845
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7603
7846
|
const x1 = canvasXFromDrawingPoint(p1);
|
|
7604
7847
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7605
|
-
if (Math.hypot(x - x0, y - y0) <= 8) {
|
|
7848
|
+
if (Math.hypot(x - x0, y - y0) <= 8 * hitTolerance) {
|
|
7606
7849
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7607
7850
|
}
|
|
7608
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7851
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7609
7852
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7610
7853
|
}
|
|
7611
7854
|
if (p2) {
|
|
7612
7855
|
const x2 = canvasXFromDrawingPoint(p2);
|
|
7613
7856
|
const y2 = canvasYFromDrawingPrice(p2.price);
|
|
7614
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7857
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7615
7858
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
7616
7859
|
}
|
|
7617
7860
|
const move = p1.price - p0.price;
|
|
7618
7861
|
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
7619
7862
|
for (const ratio of fibExtRatios) {
|
|
7620
7863
|
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
7621
|
-
if (Math.abs(y - lineY) <= 5) {
|
|
7864
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
7622
7865
|
return { drawing, target: "line" };
|
|
7623
7866
|
}
|
|
7624
7867
|
}
|
|
7625
|
-
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 || distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
7868
|
+
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7626
7869
|
return { drawing, target: "line" };
|
|
7627
7870
|
}
|
|
7628
|
-
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6) {
|
|
7871
|
+
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance) {
|
|
7629
7872
|
return { drawing, target: "line" };
|
|
7630
7873
|
}
|
|
7631
7874
|
} else if (drawing.type === "long-position" || drawing.type === "short-position") {
|
|
@@ -7639,10 +7882,10 @@ function createChart(element, options = {}) {
|
|
|
7639
7882
|
const entryY = canvasYFromDrawingPrice(entry.price);
|
|
7640
7883
|
const targetY = canvasYFromDrawingPrice(target.price);
|
|
7641
7884
|
const stopY = canvasYFromDrawingPrice(stop.price);
|
|
7642
|
-
if (Math.hypot(x - leftX, y - targetY) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7643
|
-
if (Math.hypot(x - leftX, y - entryY) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7644
|
-
if (Math.hypot(x - leftX, y - stopY) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7645
|
-
if (Math.hypot(x - rightX, y - entryY) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7885
|
+
if (Math.hypot(x - leftX, y - targetY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7886
|
+
if (Math.hypot(x - leftX, y - entryY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7887
|
+
if (Math.hypot(x - leftX, y - stopY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7888
|
+
if (Math.hypot(x - rightX, y - entryY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7646
7889
|
const x0 = Math.min(leftX, rightX);
|
|
7647
7890
|
const x1 = Math.max(leftX, rightX);
|
|
7648
7891
|
const yTop = Math.min(targetY, stopY, entryY);
|
|
@@ -7658,10 +7901,10 @@ function createChart(element, options = {}) {
|
|
|
7658
7901
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7659
7902
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7660
7903
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7661
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7662
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7663
|
-
if (Math.hypot(x - px0, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7664
|
-
if (Math.hypot(x - px1, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7904
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7905
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7906
|
+
if (Math.hypot(x - px0, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7907
|
+
if (Math.hypot(x - px1, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7665
7908
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
7666
7909
|
return { drawing, target: "line" };
|
|
7667
7910
|
}
|
|
@@ -7673,16 +7916,16 @@ function createChart(element, options = {}) {
|
|
|
7673
7916
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7674
7917
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7675
7918
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7676
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7677
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7678
|
-
if (Math.hypot(x - px0, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7679
|
-
if (Math.hypot(x - px1, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7919
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7920
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7921
|
+
if (Math.hypot(x - px0, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7922
|
+
if (Math.hypot(x - px1, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7680
7923
|
const cx = (px0 + px1) / 2;
|
|
7681
7924
|
const cy = (y0 + y1) / 2;
|
|
7682
7925
|
const rx = Math.max(1, Math.abs(px1 - px0) / 2);
|
|
7683
7926
|
const ry = Math.max(1, Math.abs(y1 - y0) / 2);
|
|
7684
7927
|
const norm = ((x - cx) / rx) ** 2 + ((y - cy) / ry) ** 2;
|
|
7685
|
-
if (norm <= 1) {
|
|
7928
|
+
if (norm <= 1 * hitTolerance) {
|
|
7686
7929
|
return { drawing, target: "line" };
|
|
7687
7930
|
}
|
|
7688
7931
|
} else if (drawing.type === "parallel-channel") {
|
|
@@ -7694,18 +7937,18 @@ function createChart(element, options = {}) {
|
|
|
7694
7937
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7695
7938
|
const x1 = canvasXFromDrawingPoint(p1);
|
|
7696
7939
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7697
|
-
if (Math.hypot(x - x0, y - y0) <= 8) return { drawing, target: "handle", pointIndex: 0 };
|
|
7698
|
-
if (Math.hypot(x - x1, y - y1) <= 8) return { drawing, target: "handle", pointIndex: 1 };
|
|
7940
|
+
if (Math.hypot(x - x0, y - y0) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7941
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7699
7942
|
if (p2) {
|
|
7700
7943
|
const x2 = canvasXFromDrawingPoint(p2);
|
|
7701
7944
|
const y2 = canvasYFromDrawingPrice(p2.price);
|
|
7702
|
-
if (Math.hypot(x - x2, y - y2) <= 8) return { drawing, target: "handle", pointIndex: 2 };
|
|
7945
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7703
7946
|
const indexSpan = p1.index - p0.index;
|
|
7704
7947
|
const slope = indexSpan !== 0 ? (p1.price - p0.price) / indexSpan : 0;
|
|
7705
7948
|
const offset = p2.price - (p0.price + slope * (p2.index - p0.index));
|
|
7706
7949
|
const q0y = canvasYFromDrawingPrice(p0.price + offset);
|
|
7707
7950
|
const q1y = canvasYFromDrawingPrice(p1.price + offset);
|
|
7708
|
-
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 || distanceToSegment(x, y, x0, q0y, x1, q1y) <= 6) {
|
|
7951
|
+
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x0, q0y, x1, q1y) <= 6 * hitTolerance) {
|
|
7709
7952
|
return { drawing, target: "line" };
|
|
7710
7953
|
}
|
|
7711
7954
|
const minX = Math.min(x0, x1);
|
|
@@ -7718,7 +7961,7 @@ function createChart(element, options = {}) {
|
|
|
7718
7961
|
return { drawing, target: "line" };
|
|
7719
7962
|
}
|
|
7720
7963
|
}
|
|
7721
|
-
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6) {
|
|
7964
|
+
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance) {
|
|
7722
7965
|
return { drawing, target: "line" };
|
|
7723
7966
|
}
|
|
7724
7967
|
} else if (drawing.type === "arrow") {
|
|
@@ -7729,13 +7972,13 @@ function createChart(element, options = {}) {
|
|
|
7729
7972
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7730
7973
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7731
7974
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7732
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7975
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7733
7976
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7734
7977
|
}
|
|
7735
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7978
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7736
7979
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7737
7980
|
}
|
|
7738
|
-
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
7981
|
+
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7739
7982
|
return { drawing, target: "line" };
|
|
7740
7983
|
}
|
|
7741
7984
|
} else if (drawing.type === "brush") {
|
|
@@ -7747,7 +7990,7 @@ function createChart(element, options = {}) {
|
|
|
7747
7990
|
for (let i = 1; i < pts.length; i += 1) {
|
|
7748
7991
|
const nextX = canvasXFromDrawingPoint(pts[i]);
|
|
7749
7992
|
const nextY = canvasYFromDrawingPrice(pts[i].price);
|
|
7750
|
-
if (distanceToSegment(x, y, prevX, prevY, nextX, nextY) <= 7) {
|
|
7993
|
+
if (distanceToSegment(x, y, prevX, prevY, nextX, nextY) <= 7 * hitTolerance) {
|
|
7751
7994
|
hitBody = true;
|
|
7752
7995
|
break;
|
|
7753
7996
|
}
|
|
@@ -7765,8 +8008,8 @@ function createChart(element, options = {}) {
|
|
|
7765
8008
|
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
7766
8009
|
const bx = canvasXFromDrawingPoint(boxPoint);
|
|
7767
8010
|
const by = canvasYFromDrawingPrice(boxPoint.price);
|
|
7768
|
-
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7769
|
-
if (Math.hypot(x - bx, y - by) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
8011
|
+
if (Math.hypot(x - ax, y - ay) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
8012
|
+
if (Math.hypot(x - bx, y - by) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7770
8013
|
const fontSize = Math.max(6, drawing.fontSize);
|
|
7771
8014
|
const prevFont = ctx.font;
|
|
7772
8015
|
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
@@ -7782,7 +8025,7 @@ function createChart(element, options = {}) {
|
|
|
7782
8025
|
if (x >= bx && x <= bx + blockW && y >= by && y <= by + blockH) {
|
|
7783
8026
|
return { drawing, target: "line" };
|
|
7784
8027
|
}
|
|
7785
|
-
if (distanceToSegment(x, y, bx + blockW / 2, by + blockH / 2, ax, ay) <= 5) {
|
|
8028
|
+
if (distanceToSegment(x, y, bx + blockW / 2, by + blockH / 2, ax, ay) <= 5 * hitTolerance) {
|
|
7786
8029
|
return { drawing, target: "line" };
|
|
7787
8030
|
}
|
|
7788
8031
|
} else if (drawing.type === "price-range") {
|
|
@@ -7793,8 +8036,8 @@ function createChart(element, options = {}) {
|
|
|
7793
8036
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7794
8037
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7795
8038
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7796
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7797
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
8039
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
8040
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7798
8041
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
7799
8042
|
return { drawing, target: "line" };
|
|
7800
8043
|
}
|
|
@@ -7803,7 +8046,7 @@ function createChart(element, options = {}) {
|
|
|
7803
8046
|
if (!anchor) continue;
|
|
7804
8047
|
const ax = canvasXFromDrawingPoint(anchor);
|
|
7805
8048
|
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
7806
|
-
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
8049
|
+
if (Math.hypot(x - ax, y - ay) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7807
8050
|
const fontSize = Math.max(6, drawing.fontSize);
|
|
7808
8051
|
const prevFont = ctx.font;
|
|
7809
8052
|
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
@@ -7898,8 +8141,9 @@ function createChart(element, options = {}) {
|
|
|
7898
8141
|
if (!drawState || x < drawState.chartLeft || x > drawState.chartRight) {
|
|
7899
8142
|
return null;
|
|
7900
8143
|
}
|
|
8144
|
+
const dividerTolerance = touchInputActive ? 4 * Math.max(1, mergedOptions.touch?.hitToleranceScale ?? 2.2) : 4;
|
|
7901
8145
|
for (const pane of paneLayoutInfos) {
|
|
7902
|
-
if (pane.visible && Math.abs(y - pane.top) <=
|
|
8146
|
+
if (pane.visible && Math.abs(y - pane.top) <= dividerTolerance) {
|
|
7903
8147
|
return { id: pane.id, heightPx: pane.bottom - pane.top };
|
|
7904
8148
|
}
|
|
7905
8149
|
}
|
|
@@ -8392,7 +8636,43 @@ function createChart(element, options = {}) {
|
|
|
8392
8636
|
let lastPointerX = 0;
|
|
8393
8637
|
let lastPointerY = 0;
|
|
8394
8638
|
let activePointerId = null;
|
|
8639
|
+
let touchInputActive = false;
|
|
8395
8640
|
const touchPointers = /* @__PURE__ */ new Map();
|
|
8641
|
+
let longPressTimerId = null;
|
|
8642
|
+
let longPressState = null;
|
|
8643
|
+
const cancelLongPressTimer = () => {
|
|
8644
|
+
if (longPressTimerId !== null) {
|
|
8645
|
+
clearTimeout(longPressTimerId);
|
|
8646
|
+
longPressTimerId = null;
|
|
8647
|
+
}
|
|
8648
|
+
};
|
|
8649
|
+
const emitLongPress = (x, y, scrubbing) => {
|
|
8650
|
+
if (!longPressHandler) return;
|
|
8651
|
+
const rect = canvas.getBoundingClientRect();
|
|
8652
|
+
const index = indexFromCanvasX(x);
|
|
8653
|
+
const barTime = index === null ? null : getTimeForIndex(index);
|
|
8654
|
+
const bar = index === null ? void 0 : data[index];
|
|
8655
|
+
longPressHandler({
|
|
8656
|
+
x,
|
|
8657
|
+
y,
|
|
8658
|
+
clientX: rect.left + x,
|
|
8659
|
+
clientY: rect.top + y,
|
|
8660
|
+
scrubbing,
|
|
8661
|
+
...getHitRegion(x, y) === "plot" ? { price: roundToPricePrecision(priceFromCanvasY(y)) } : {},
|
|
8662
|
+
...index === null ? {} : { index },
|
|
8663
|
+
...barTime ? { time: barTime.toISOString() } : {},
|
|
8664
|
+
...bar ? {
|
|
8665
|
+
point: {
|
|
8666
|
+
t: bar.time.toISOString(),
|
|
8667
|
+
o: bar.o,
|
|
8668
|
+
h: bar.h,
|
|
8669
|
+
l: bar.l,
|
|
8670
|
+
c: bar.c,
|
|
8671
|
+
...bar.v === void 0 ? {} : { v: bar.v }
|
|
8672
|
+
}
|
|
8673
|
+
} : {}
|
|
8674
|
+
});
|
|
8675
|
+
};
|
|
8396
8676
|
let pinchZoomState = null;
|
|
8397
8677
|
const getTouchPair = () => {
|
|
8398
8678
|
const points = Array.from(touchPointers.values());
|
|
@@ -8458,7 +8738,8 @@ function createChart(element, options = {}) {
|
|
|
8458
8738
|
}
|
|
8459
8739
|
};
|
|
8460
8740
|
const onPointerDown = (event) => {
|
|
8461
|
-
|
|
8741
|
+
touchInputActive = event.pointerType === "touch" || event.pointerType === "pen";
|
|
8742
|
+
if (touchInputActive) {
|
|
8462
8743
|
event.preventDefault();
|
|
8463
8744
|
}
|
|
8464
8745
|
if (mergedOptions.accessibility?.focusable !== false && document.activeElement !== canvas) {
|
|
@@ -8475,9 +8756,25 @@ function createChart(element, options = {}) {
|
|
|
8475
8756
|
capturePointer(event.pointerId);
|
|
8476
8757
|
const touchPair = getTouchPair();
|
|
8477
8758
|
if (touchPair) {
|
|
8759
|
+
cancelLongPressTimer();
|
|
8760
|
+
longPressState = null;
|
|
8478
8761
|
beginPinchZoom(touchPair[0], touchPair[1]);
|
|
8479
8762
|
return;
|
|
8480
8763
|
}
|
|
8764
|
+
cancelLongPressTimer();
|
|
8765
|
+
longPressState = null;
|
|
8766
|
+
const touchOptions = mergedOptions.touch ?? {};
|
|
8767
|
+
const wantsTooltip = touchOptions.longPressTooltip !== false || longPressHandler !== null;
|
|
8768
|
+
if (wantsTooltip && !activeDrawingTool && !draftDrawing && getHitRegion(point.x, point.y) === "plot") {
|
|
8769
|
+
const pointerId = event.pointerId;
|
|
8770
|
+
longPressTimerId = window.setTimeout(() => {
|
|
8771
|
+
longPressTimerId = null;
|
|
8772
|
+
longPressState = { pointerId, x: point.x, y: point.y };
|
|
8773
|
+
setCrosshairPoint(point);
|
|
8774
|
+
scheduleDraw({ overlayOnly: true });
|
|
8775
|
+
emitLongPress(point.x, point.y, false);
|
|
8776
|
+
}, Math.max(120, touchOptions.longPressMs ?? 400));
|
|
8777
|
+
}
|
|
8481
8778
|
}
|
|
8482
8779
|
if (measureState) {
|
|
8483
8780
|
if (measureState.dragging) {
|
|
@@ -8643,7 +8940,10 @@ function createChart(element, options = {}) {
|
|
|
8643
8940
|
};
|
|
8644
8941
|
const onPointerMove = (event) => {
|
|
8645
8942
|
if (event.pointerType === "touch" || event.pointerType === "pen") {
|
|
8943
|
+
touchInputActive = true;
|
|
8646
8944
|
event.preventDefault();
|
|
8945
|
+
} else if (event.pointerType === "mouse") {
|
|
8946
|
+
touchInputActive = false;
|
|
8647
8947
|
}
|
|
8648
8948
|
magnetModifierActive = event.metaKey || event.ctrlKey;
|
|
8649
8949
|
shiftKeyActive = event.shiftKey;
|
|
@@ -8652,6 +8952,8 @@ function createChart(element, options = {}) {
|
|
|
8652
8952
|
touchPointers.set(event.pointerId, point);
|
|
8653
8953
|
const touchPair = getTouchPair();
|
|
8654
8954
|
if (touchPair) {
|
|
8955
|
+
cancelLongPressTimer();
|
|
8956
|
+
longPressState = null;
|
|
8655
8957
|
if (!pinchZoomState) {
|
|
8656
8958
|
beginPinchZoom(touchPair[0], touchPair[1]);
|
|
8657
8959
|
}
|
|
@@ -8661,6 +8963,21 @@ function createChart(element, options = {}) {
|
|
|
8661
8963
|
if (pinchZoomState) {
|
|
8662
8964
|
return;
|
|
8663
8965
|
}
|
|
8966
|
+
if (longPressState && longPressState.pointerId === event.pointerId) {
|
|
8967
|
+
longPressState = { ...longPressState, x: point.x, y: point.y };
|
|
8968
|
+
setCrosshairPoint(point);
|
|
8969
|
+
emitCrosshairMove(point.x, point.y, getHitRegion(point.x, point.y) === "plot" ? "plot" : "plot");
|
|
8970
|
+
scheduleDraw({ overlayOnly: true });
|
|
8971
|
+
emitLongPress(point.x, point.y, true);
|
|
8972
|
+
return;
|
|
8973
|
+
}
|
|
8974
|
+
if (longPressTimerId !== null) {
|
|
8975
|
+
const dx = point.x - (pointerDownInfo?.x ?? point.x);
|
|
8976
|
+
const dy = point.y - (pointerDownInfo?.y ?? point.y);
|
|
8977
|
+
if (dx * dx + dy * dy > 36) {
|
|
8978
|
+
cancelLongPressTimer();
|
|
8979
|
+
}
|
|
8980
|
+
}
|
|
8664
8981
|
}
|
|
8665
8982
|
if (pointerDownInfo && pointerDownInfo.pointerId === event.pointerId && !pointerDownInfo.moved) {
|
|
8666
8983
|
const dx = point.x - pointerDownInfo.x;
|
|
@@ -8924,6 +9241,18 @@ function createChart(element, options = {}) {
|
|
|
8924
9241
|
lastPointerY = point.y;
|
|
8925
9242
|
};
|
|
8926
9243
|
const endPointerDrag = (event) => {
|
|
9244
|
+
cancelLongPressTimer();
|
|
9245
|
+
if (longPressState && (!event || event.pointerId === longPressState.pointerId)) {
|
|
9246
|
+
longPressState = null;
|
|
9247
|
+
touchPointers.delete(event?.pointerId ?? -1);
|
|
9248
|
+
setCrosshairPoint(null);
|
|
9249
|
+
isDragging = false;
|
|
9250
|
+
dragMode = null;
|
|
9251
|
+
activePointerId = null;
|
|
9252
|
+
pointerDownInfo = null;
|
|
9253
|
+
scheduleDraw({ overlayOnly: true });
|
|
9254
|
+
return;
|
|
9255
|
+
}
|
|
8927
9256
|
if (event?.pointerType === "touch") {
|
|
8928
9257
|
touchPointers.delete(event.pointerId);
|
|
8929
9258
|
if (pinchZoomState) {
|
|
@@ -9331,6 +9660,23 @@ function createChart(element, options = {}) {
|
|
|
9331
9660
|
window.addEventListener("blur", onWindowBlurMagnet);
|
|
9332
9661
|
}
|
|
9333
9662
|
const updateOptions = (nextOptions) => {
|
|
9663
|
+
const THEMED_OPTION_KEYS = [
|
|
9664
|
+
"backgroundColor",
|
|
9665
|
+
"upColor",
|
|
9666
|
+
"downColor",
|
|
9667
|
+
"lineColor",
|
|
9668
|
+
"gridColor",
|
|
9669
|
+
"axisColor",
|
|
9670
|
+
"grid",
|
|
9671
|
+
"axis",
|
|
9672
|
+
"xAxis",
|
|
9673
|
+
"yAxis",
|
|
9674
|
+
"crosshair",
|
|
9675
|
+
"watermark"
|
|
9676
|
+
];
|
|
9677
|
+
if (THEMED_OPTION_KEYS.some((key) => nextOptions[key] !== void 0) || nextOptions.labels?.indicatorTextColor !== void 0) {
|
|
9678
|
+
activeThemeName = null;
|
|
9679
|
+
}
|
|
9334
9680
|
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
9335
9681
|
const previousWidth = width;
|
|
9336
9682
|
const previousHeight = height;
|
|
@@ -9359,6 +9705,30 @@ function createChart(element, options = {}) {
|
|
|
9359
9705
|
}
|
|
9360
9706
|
scheduleDraw();
|
|
9361
9707
|
};
|
|
9708
|
+
const setTheme = (theme) => {
|
|
9709
|
+
const resolved = resolveTheme(theme);
|
|
9710
|
+
updateOptions({
|
|
9711
|
+
backgroundColor: resolved.background,
|
|
9712
|
+
upColor: resolved.upColor,
|
|
9713
|
+
downColor: resolved.downColor,
|
|
9714
|
+
lineColor: resolved.lineColor,
|
|
9715
|
+
gridColor: resolved.gridColor,
|
|
9716
|
+
grid: { color: resolved.gridColor, opacity: resolved.gridOpacity },
|
|
9717
|
+
axis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9718
|
+
xAxis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9719
|
+
yAxis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9720
|
+
crosshair: {
|
|
9721
|
+
color: resolved.crosshairColor,
|
|
9722
|
+
labelBackgroundColor: resolved.crosshairLabelBackground,
|
|
9723
|
+
labelTextColor: resolved.crosshairLabelText,
|
|
9724
|
+
labelBorderColor: resolved.crosshairLabelBorder
|
|
9725
|
+
},
|
|
9726
|
+
watermark: { color: resolved.watermarkColor },
|
|
9727
|
+
labels: { indicatorTextColor: resolved.indicatorTextColor }
|
|
9728
|
+
});
|
|
9729
|
+
activeThemeName = resolved.name;
|
|
9730
|
+
};
|
|
9731
|
+
const getTheme = () => activeThemeName;
|
|
9362
9732
|
const setChartType = (type) => {
|
|
9363
9733
|
if (mergedOptions.chartType === type) {
|
|
9364
9734
|
return;
|
|
@@ -9740,6 +10110,9 @@ function createChart(element, options = {}) {
|
|
|
9740
10110
|
const onKeyboardShortcut = (handler) => {
|
|
9741
10111
|
keyboardShortcutHandler = handler;
|
|
9742
10112
|
};
|
|
10113
|
+
const onLongPress = (handler) => {
|
|
10114
|
+
longPressHandler = handler;
|
|
10115
|
+
};
|
|
9743
10116
|
const focus = () => {
|
|
9744
10117
|
canvas.focus({ preventScroll: true });
|
|
9745
10118
|
};
|
|
@@ -9793,6 +10166,10 @@ function createChart(element, options = {}) {
|
|
|
9793
10166
|
return canvas.toDataURL(options2.type ?? "image/png", options2.quality);
|
|
9794
10167
|
};
|
|
9795
10168
|
const destroy = () => {
|
|
10169
|
+
cancelLongPressTimer();
|
|
10170
|
+
datafeedUnsubscribe?.();
|
|
10171
|
+
datafeedUnsubscribe = null;
|
|
10172
|
+
datafeed = null;
|
|
9796
10173
|
cancelKineticPan();
|
|
9797
10174
|
if (smoothingRafId !== null) {
|
|
9798
10175
|
cancelAnimationFrame(smoothingRafId);
|
|
@@ -9880,10 +10257,14 @@ function createChart(element, options = {}) {
|
|
|
9880
10257
|
getMagnetMode,
|
|
9881
10258
|
setPriceScale,
|
|
9882
10259
|
getPriceScale,
|
|
10260
|
+
setTheme,
|
|
10261
|
+
getTheme,
|
|
9883
10262
|
setCompareSeries,
|
|
9884
10263
|
addCompareSeries,
|
|
9885
10264
|
removeCompareSeries,
|
|
9886
10265
|
getCompareSeries,
|
|
10266
|
+
setDatafeed,
|
|
10267
|
+
onLongPress,
|
|
9887
10268
|
cancelDrawing,
|
|
9888
10269
|
setTradeMarkers,
|
|
9889
10270
|
setSelectedDrawing,
|
|
@@ -9907,6 +10288,8 @@ function createChart(element, options = {}) {
|
|
|
9907
10288
|
};
|
|
9908
10289
|
}
|
|
9909
10290
|
export {
|
|
10291
|
+
CHART_THEMES,
|
|
10292
|
+
CHART_THEME_NAMES,
|
|
9910
10293
|
FIB_DEFAULT_PALETTE,
|
|
9911
10294
|
POSITION_DEFAULT_COLORS,
|
|
9912
10295
|
SCRIPT_SOURCE_INPUT_VALUES,
|