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.cjs
CHANGED
|
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
CHART_THEMES: () => CHART_THEMES,
|
|
24
|
+
CHART_THEME_NAMES: () => CHART_THEME_NAMES,
|
|
23
25
|
FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
|
|
24
26
|
POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
|
|
25
27
|
SCRIPT_SOURCE_INPUT_VALUES: () => SCRIPT_SOURCE_INPUT_VALUES,
|
|
@@ -2655,6 +2657,88 @@ var compileScriptIndicator = (definition) => {
|
|
|
2655
2657
|
return plugin;
|
|
2656
2658
|
};
|
|
2657
2659
|
|
|
2660
|
+
// src/themes.ts
|
|
2661
|
+
var CHART_THEMES = {
|
|
2662
|
+
dark: {
|
|
2663
|
+
name: "dark",
|
|
2664
|
+
background: "#0f0f0f",
|
|
2665
|
+
upColor: "#089981",
|
|
2666
|
+
downColor: "#f23645",
|
|
2667
|
+
lineColor: "#2962ff",
|
|
2668
|
+
gridColor: "#3c3c3c",
|
|
2669
|
+
gridOpacity: 0.5,
|
|
2670
|
+
axisTextColor: "#dbdbdb",
|
|
2671
|
+
axisLineColor: "#424242",
|
|
2672
|
+
crosshairColor: "#9598a1",
|
|
2673
|
+
crosshairLabelBackground: "#3c3c3c",
|
|
2674
|
+
crosshairLabelText: "#dbdbdb",
|
|
2675
|
+
crosshairLabelBorder: "#5d5d5d",
|
|
2676
|
+
watermarkColor: "rgba(219,219,219,0.06)",
|
|
2677
|
+
indicatorTextColor: "#b2b5be",
|
|
2678
|
+
labelTextColor: "#ffffff",
|
|
2679
|
+
labelBackground: "#1a1a1a"
|
|
2680
|
+
},
|
|
2681
|
+
light: {
|
|
2682
|
+
name: "light",
|
|
2683
|
+
background: "#ffffff",
|
|
2684
|
+
upColor: "#089981",
|
|
2685
|
+
downColor: "#f23645",
|
|
2686
|
+
lineColor: "#2962ff",
|
|
2687
|
+
gridColor: "#d5d5d5",
|
|
2688
|
+
gridOpacity: 0.9,
|
|
2689
|
+
axisTextColor: "#0f0f0f",
|
|
2690
|
+
axisLineColor: "#c3c3c3",
|
|
2691
|
+
crosshairColor: "#787b86",
|
|
2692
|
+
crosshairLabelBackground: "#4b4b4b",
|
|
2693
|
+
crosshairLabelText: "#ffffff",
|
|
2694
|
+
crosshairLabelBorder: "#878787",
|
|
2695
|
+
watermarkColor: "rgba(15,15,15,0.06)",
|
|
2696
|
+
indicatorTextColor: "#4b4b4b",
|
|
2697
|
+
labelTextColor: "#ffffff",
|
|
2698
|
+
labelBackground: "#f0f3fa"
|
|
2699
|
+
},
|
|
2700
|
+
midnight: {
|
|
2701
|
+
name: "midnight",
|
|
2702
|
+
background: "#171717",
|
|
2703
|
+
upColor: "#22ab94",
|
|
2704
|
+
downColor: "#f23645",
|
|
2705
|
+
lineColor: "#2563eb",
|
|
2706
|
+
gridColor: "#2b2f38",
|
|
2707
|
+
gridOpacity: 0.38,
|
|
2708
|
+
axisTextColor: "#dbe4f0",
|
|
2709
|
+
axisLineColor: "#5f646d",
|
|
2710
|
+
crosshairColor: "#94a3b8",
|
|
2711
|
+
crosshairLabelBackground: "#6b6f76",
|
|
2712
|
+
crosshairLabelText: "#e2e8f0",
|
|
2713
|
+
crosshairLabelBorder: "#e2e8f0",
|
|
2714
|
+
watermarkColor: "rgba(226,232,240,0.05)",
|
|
2715
|
+
indicatorTextColor: "#cbd5e1",
|
|
2716
|
+
labelTextColor: "#dbeafe",
|
|
2717
|
+
labelBackground: "#0b1220"
|
|
2718
|
+
},
|
|
2719
|
+
"high-contrast": {
|
|
2720
|
+
name: "high-contrast",
|
|
2721
|
+
background: "#000000",
|
|
2722
|
+
upColor: "#00e5a0",
|
|
2723
|
+
downColor: "#ff4d5e",
|
|
2724
|
+
lineColor: "#4d9fff",
|
|
2725
|
+
gridColor: "#5a5a5a",
|
|
2726
|
+
gridOpacity: 0.7,
|
|
2727
|
+
axisTextColor: "#ffffff",
|
|
2728
|
+
axisLineColor: "#8a8a8a",
|
|
2729
|
+
crosshairColor: "#ffffff",
|
|
2730
|
+
crosshairLabelBackground: "#ffffff",
|
|
2731
|
+
crosshairLabelText: "#000000",
|
|
2732
|
+
crosshairLabelBorder: "#ffffff",
|
|
2733
|
+
watermarkColor: "rgba(255,255,255,0.08)",
|
|
2734
|
+
indicatorTextColor: "#ffffff",
|
|
2735
|
+
labelTextColor: "#000000",
|
|
2736
|
+
labelBackground: "#1a1a1a"
|
|
2737
|
+
}
|
|
2738
|
+
};
|
|
2739
|
+
var CHART_THEME_NAMES = Object.keys(CHART_THEMES);
|
|
2740
|
+
var resolveTheme = (theme) => typeof theme === "string" ? CHART_THEMES[theme] ?? CHART_THEMES.dark : theme;
|
|
2741
|
+
|
|
2658
2742
|
// src/options.ts
|
|
2659
2743
|
var DEFAULT_GRID_OPTIONS = {
|
|
2660
2744
|
color: "#2b2f38",
|
|
@@ -2854,6 +2938,8 @@ var DEFAULT_OPTIONS = {
|
|
|
2854
2938
|
keyboard: { enabled: true, panBars: 1, deleteSelectedDrawing: true },
|
|
2855
2939
|
accessibility: { label: "Price chart", description: "", focusable: true },
|
|
2856
2940
|
downsampling: { enabled: true, thresholdPx: 1.5 },
|
|
2941
|
+
touch: { hitToleranceScale: 2.2, longPressTooltip: true, longPressMs: 400 },
|
|
2942
|
+
datafeedOptions: { prefetchThresholdBars: 150, cooldownMs: 1200, chunkBars: 1500 },
|
|
2857
2943
|
crosshair: DEFAULT_CROSSHAIR_OPTIONS,
|
|
2858
2944
|
grid: DEFAULT_GRID_OPTIONS,
|
|
2859
2945
|
watermark: DEFAULT_WATERMARK_OPTIONS,
|
|
@@ -2908,6 +2994,14 @@ var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
|
2908
2994
|
...baseOptions.downsampling,
|
|
2909
2995
|
...options.downsampling ?? {}
|
|
2910
2996
|
},
|
|
2997
|
+
touch: {
|
|
2998
|
+
...baseOptions.touch,
|
|
2999
|
+
...options.touch ?? {}
|
|
3000
|
+
},
|
|
3001
|
+
datafeedOptions: {
|
|
3002
|
+
...baseOptions.datafeedOptions,
|
|
3003
|
+
...options.datafeedOptions ?? {}
|
|
3004
|
+
},
|
|
2911
3005
|
crosshair: {
|
|
2912
3006
|
...baseOptions.crosshair,
|
|
2913
3007
|
...options.crosshair ?? {}
|
|
@@ -3082,10 +3176,12 @@ function createChart(element, options = {}) {
|
|
|
3082
3176
|
let drawingDoubleClickHandler = null;
|
|
3083
3177
|
let drawingEditTextHandler = null;
|
|
3084
3178
|
let selectionChangeHandler = null;
|
|
3179
|
+
let longPressHandler = null;
|
|
3085
3180
|
let contextMenuHandler = null;
|
|
3086
3181
|
let keyboardShortcutHandler = null;
|
|
3087
3182
|
let lastSelectionSignature = null;
|
|
3088
3183
|
let magnetMode = "none";
|
|
3184
|
+
let activeThemeName = null;
|
|
3089
3185
|
let priceScaleMode = "linear";
|
|
3090
3186
|
let priceScaleInverted = false;
|
|
3091
3187
|
const PRICE_SCALE_LOG_FLOOR = 1e-9;
|
|
@@ -3841,6 +3937,92 @@ function createChart(element, options = {}) {
|
|
|
3841
3937
|
scheduleDraw({ updateAutoScale: true });
|
|
3842
3938
|
};
|
|
3843
3939
|
const getCompareSeries = () => compareSeriesStates.map((state) => state.options);
|
|
3940
|
+
let datafeed = null;
|
|
3941
|
+
let datafeedUnsubscribe = null;
|
|
3942
|
+
let datafeedLoading = false;
|
|
3943
|
+
let datafeedExhausted = false;
|
|
3944
|
+
let datafeedLastRequestAt = 0;
|
|
3945
|
+
const estimateBarStepMs = () => {
|
|
3946
|
+
if (mergedOptions.timeStepMs > 0) return mergedOptions.timeStepMs;
|
|
3947
|
+
if (data.length < 2) return 6e4;
|
|
3948
|
+
const span = data[data.length - 1].time.getTime() - data[0].time.getTime();
|
|
3949
|
+
return Math.max(1e3, span / (data.length - 1));
|
|
3950
|
+
};
|
|
3951
|
+
const requestDatafeedBars = async (request) => {
|
|
3952
|
+
if (!datafeed) return [];
|
|
3953
|
+
try {
|
|
3954
|
+
return await datafeed.getBars(request) ?? [];
|
|
3955
|
+
} catch (error) {
|
|
3956
|
+
datafeed.onError?.(error, request);
|
|
3957
|
+
return [];
|
|
3958
|
+
}
|
|
3959
|
+
};
|
|
3960
|
+
const maybeLoadOlderHistory = () => {
|
|
3961
|
+
if (!datafeed || datafeedLoading || datafeedExhausted || data.length === 0) return;
|
|
3962
|
+
const options2 = mergedOptions.datafeedOptions ?? DEFAULT_OPTIONS.datafeedOptions;
|
|
3963
|
+
const threshold = options2?.prefetchThresholdBars ?? 150;
|
|
3964
|
+
const cooldown = options2?.cooldownMs ?? 1200;
|
|
3965
|
+
if (Date.now() - datafeedLastRequestAt < cooldown) return;
|
|
3966
|
+
if (xCenter - xSpan / 2 > threshold) return;
|
|
3967
|
+
const stepMs = estimateBarStepMs();
|
|
3968
|
+
const chunk = Math.max(10, options2?.chunkBars ?? 1500);
|
|
3969
|
+
const toMs = data[0].time.getTime();
|
|
3970
|
+
datafeedLoading = true;
|
|
3971
|
+
datafeedLastRequestAt = Date.now();
|
|
3972
|
+
void requestDatafeedBars({
|
|
3973
|
+
fromMs: toMs - chunk * stepMs,
|
|
3974
|
+
toMs,
|
|
3975
|
+
countBack: chunk,
|
|
3976
|
+
firstRequest: false
|
|
3977
|
+
}).then((bars) => {
|
|
3978
|
+
const older = bars.filter((bar) => new Date(bar.t).getTime() < toMs);
|
|
3979
|
+
if (older.length === 0) {
|
|
3980
|
+
datafeedExhausted = true;
|
|
3981
|
+
return;
|
|
3982
|
+
}
|
|
3983
|
+
const merged = [...older, ...data.map((bar) => ({
|
|
3984
|
+
t: bar.time.toISOString(),
|
|
3985
|
+
o: bar.o,
|
|
3986
|
+
h: bar.h,
|
|
3987
|
+
l: bar.l,
|
|
3988
|
+
c: bar.c,
|
|
3989
|
+
...bar.v === void 0 ? {} : { v: bar.v }
|
|
3990
|
+
}))];
|
|
3991
|
+
setData(merged);
|
|
3992
|
+
}).finally(() => {
|
|
3993
|
+
datafeedLoading = false;
|
|
3994
|
+
});
|
|
3995
|
+
};
|
|
3996
|
+
const setDatafeed = async (nextDatafeed) => {
|
|
3997
|
+
datafeedUnsubscribe?.();
|
|
3998
|
+
datafeedUnsubscribe = null;
|
|
3999
|
+
datafeed = nextDatafeed;
|
|
4000
|
+
datafeedExhausted = false;
|
|
4001
|
+
datafeedLoading = false;
|
|
4002
|
+
datafeedLastRequestAt = 0;
|
|
4003
|
+
if (!nextDatafeed) return;
|
|
4004
|
+
await nextDatafeed.onReady?.();
|
|
4005
|
+
if (datafeed !== nextDatafeed) return;
|
|
4006
|
+
const stepMs = estimateBarStepMs();
|
|
4007
|
+
const countBack = Math.max(50, Math.round(mergedOptions.initialVisibleBars * 3));
|
|
4008
|
+
const toMs = Date.now();
|
|
4009
|
+
datafeedLoading = true;
|
|
4010
|
+
const bars = await requestDatafeedBars({
|
|
4011
|
+
fromMs: toMs - countBack * stepMs,
|
|
4012
|
+
toMs,
|
|
4013
|
+
countBack,
|
|
4014
|
+
firstRequest: true
|
|
4015
|
+
});
|
|
4016
|
+
datafeedLoading = false;
|
|
4017
|
+
if (datafeed !== nextDatafeed) return;
|
|
4018
|
+
if (bars.length > 0) {
|
|
4019
|
+
setData(bars);
|
|
4020
|
+
}
|
|
4021
|
+
const unsubscribe = nextDatafeed.subscribeBars?.((bar) => {
|
|
4022
|
+
if (datafeed === nextDatafeed) upsertBar(bar);
|
|
4023
|
+
});
|
|
4024
|
+
datafeedUnsubscribe = typeof unsubscribe === "function" ? unsubscribe : null;
|
|
4025
|
+
};
|
|
3844
4026
|
const formatHoverTimeLabel = (time, mode) => {
|
|
3845
4027
|
if (mode === "time") {
|
|
3846
4028
|
return time.toLocaleTimeString(void 0, {
|
|
@@ -6835,6 +7017,7 @@ function createChart(element, options = {}) {
|
|
|
6835
7017
|
};
|
|
6836
7018
|
paintCrosshairOverlay();
|
|
6837
7019
|
emitSelectionChangeIfMoved();
|
|
7020
|
+
maybeLoadOlderHistory();
|
|
6838
7021
|
};
|
|
6839
7022
|
const paintCrosshairOverlay = () => {
|
|
6840
7023
|
crosshairPriceActionRegion = null;
|
|
@@ -7027,6 +7210,67 @@ function createChart(element, options = {}) {
|
|
|
7027
7210
|
drawText(timeText, timeX + labelPaddingX, timeY + timeHeight / 2, "left", "middle", labelTextColor);
|
|
7028
7211
|
}
|
|
7029
7212
|
}
|
|
7213
|
+
if (longPressState && (mergedOptions.touch?.longPressTooltip ?? true)) {
|
|
7214
|
+
const index = indexFromCanvasX(cx);
|
|
7215
|
+
const bar = index === null ? void 0 : data[index];
|
|
7216
|
+
if (bar) {
|
|
7217
|
+
const barTime = getTimeForIndex(index);
|
|
7218
|
+
const changeAbs = bar.c - bar.o;
|
|
7219
|
+
const changePct = bar.o !== 0 ? changeAbs / bar.o * 100 : 0;
|
|
7220
|
+
const rows = [
|
|
7221
|
+
["O", formatPrice(bar.o), null],
|
|
7222
|
+
["H", formatPrice(bar.h), null],
|
|
7223
|
+
["L", formatPrice(bar.l), null],
|
|
7224
|
+
["C", formatPrice(bar.c), null],
|
|
7225
|
+
[
|
|
7226
|
+
"Chg",
|
|
7227
|
+
`${changeAbs >= 0 ? "+" : ""}${formatPrice(changeAbs)} (${changeAbs >= 0 ? "+" : ""}${changePct.toFixed(2)}%)`,
|
|
7228
|
+
changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor
|
|
7229
|
+
]
|
|
7230
|
+
];
|
|
7231
|
+
if (bar.v !== void 0) {
|
|
7232
|
+
rows.push([
|
|
7233
|
+
"Vol",
|
|
7234
|
+
bar.v >= 1e6 ? `${(bar.v / 1e6).toFixed(2)}M` : bar.v >= 1e3 ? `${(bar.v / 1e3).toFixed(1)}K` : String(Math.round(bar.v)),
|
|
7235
|
+
null
|
|
7236
|
+
]);
|
|
7237
|
+
}
|
|
7238
|
+
const prevFont = ctx.font;
|
|
7239
|
+
const fontSize = 11;
|
|
7240
|
+
ctx.font = `${fontSize}px ${mergedOptions.fontFamily}`;
|
|
7241
|
+
const headerText = barTime ? formatHoverTimeLabel(barTime, "auto") : "";
|
|
7242
|
+
const rowGap = 3;
|
|
7243
|
+
const padding = 8;
|
|
7244
|
+
const labelColumn = 26;
|
|
7245
|
+
const contentWidth = Math.max(
|
|
7246
|
+
measureTextWidth(headerText),
|
|
7247
|
+
...rows.map(([, value]) => labelColumn + measureTextWidth(value))
|
|
7248
|
+
);
|
|
7249
|
+
const boxWidth = Math.ceil(contentWidth) + padding * 2;
|
|
7250
|
+
const boxHeight = padding * 2 + (fontSize + rowGap) * (rows.length + (headerText ? 1 : 0)) - rowGap;
|
|
7251
|
+
const fingerGap = 26;
|
|
7252
|
+
const boxX = cx + fingerGap + boxWidth <= chartRight ? cx + fingerGap : Math.max(chartLeft + 4, cx - fingerGap - boxWidth);
|
|
7253
|
+
const boxY = clamp(cy - boxHeight - fingerGap, chartTop + 4, chartBottom - boxHeight - 4);
|
|
7254
|
+
ctx.save();
|
|
7255
|
+
ctx.fillStyle = "rgba(16,17,20,0.94)";
|
|
7256
|
+
fillRoundedRect(Math.round(boxX), Math.round(boxY), boxWidth, boxHeight, 6);
|
|
7257
|
+
ctx.strokeStyle = "rgba(255,255,255,0.14)";
|
|
7258
|
+
ctx.lineWidth = 1;
|
|
7259
|
+
ctx.strokeRect(Math.round(boxX) + 0.5, Math.round(boxY) + 0.5, boxWidth - 1, boxHeight - 1);
|
|
7260
|
+
let textY = boxY + padding + fontSize / 2;
|
|
7261
|
+
if (headerText) {
|
|
7262
|
+
drawText(headerText, boxX + padding, textY, "left", "middle", "rgba(255,255,255,0.55)");
|
|
7263
|
+
textY += fontSize + rowGap;
|
|
7264
|
+
}
|
|
7265
|
+
for (const [label, value, valueColor] of rows) {
|
|
7266
|
+
drawText(label, boxX + padding, textY, "left", "middle", "rgba(255,255,255,0.5)");
|
|
7267
|
+
drawText(value, boxX + padding + labelColumn, textY, "left", "middle", valueColor ?? "#e6e8ee");
|
|
7268
|
+
textY += fontSize + rowGap;
|
|
7269
|
+
}
|
|
7270
|
+
ctx.restore();
|
|
7271
|
+
ctx.font = prevFont;
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7030
7274
|
};
|
|
7031
7275
|
const drawOverlayOnly = () => {
|
|
7032
7276
|
if (!baseCtx || !overlayLayout || baseCanvas.width !== canvas.width || baseCanvas.height !== canvas.height || baseCanvas.width === 0) {
|
|
@@ -7536,6 +7780,7 @@ function createChart(element, options = {}) {
|
|
|
7536
7780
|
return Math.hypot(x - (x1 + t * dx), y - (y1 + t * dy));
|
|
7537
7781
|
};
|
|
7538
7782
|
const getDrawingHit = (x, y) => {
|
|
7783
|
+
const hitTolerance = touchInputActive ? Math.max(1, mergedOptions.touch?.hitToleranceScale ?? 2.2) : 1;
|
|
7539
7784
|
for (let index = drawings.length - 1; index >= 0; index -= 1) {
|
|
7540
7785
|
const drawing = drawings[index];
|
|
7541
7786
|
if (!drawing?.visible) continue;
|
|
@@ -7544,10 +7789,10 @@ function createChart(element, options = {}) {
|
|
|
7544
7789
|
if (!point) continue;
|
|
7545
7790
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
7546
7791
|
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
7547
|
-
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
7792
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8 * hitTolerance) {
|
|
7548
7793
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7549
7794
|
}
|
|
7550
|
-
if (Math.abs(y - lineY) <= 7) {
|
|
7795
|
+
if (Math.abs(y - lineY) <= 7 * hitTolerance) {
|
|
7551
7796
|
return { drawing, target: "line" };
|
|
7552
7797
|
}
|
|
7553
7798
|
} else if (drawing.type === "vertical-line") {
|
|
@@ -7555,10 +7800,10 @@ function createChart(element, options = {}) {
|
|
|
7555
7800
|
if (!point) continue;
|
|
7556
7801
|
const lineX = canvasXFromDrawingPoint(point);
|
|
7557
7802
|
const handleY = drawState ? (drawState.chartTop + drawState.chartBottom) / 2 : 0;
|
|
7558
|
-
if (Math.hypot(x - lineX, y - handleY) <= 8) {
|
|
7803
|
+
if (Math.hypot(x - lineX, y - handleY) <= 8 * hitTolerance) {
|
|
7559
7804
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7560
7805
|
}
|
|
7561
|
-
if (Math.abs(x - lineX) <= 7) {
|
|
7806
|
+
if (Math.abs(x - lineX) <= 7 * hitTolerance) {
|
|
7562
7807
|
return { drawing, target: "line" };
|
|
7563
7808
|
}
|
|
7564
7809
|
} else if (drawing.type === "trendline") {
|
|
@@ -7569,13 +7814,13 @@ function createChart(element, options = {}) {
|
|
|
7569
7814
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7570
7815
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7571
7816
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7572
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7817
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7573
7818
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7574
7819
|
}
|
|
7575
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7820
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7576
7821
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7577
7822
|
}
|
|
7578
|
-
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
7823
|
+
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7579
7824
|
return { drawing, target: "line" };
|
|
7580
7825
|
}
|
|
7581
7826
|
} else if (drawing.type === "ray") {
|
|
@@ -7586,10 +7831,10 @@ function createChart(element, options = {}) {
|
|
|
7586
7831
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7587
7832
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7588
7833
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7589
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7834
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7590
7835
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7591
7836
|
}
|
|
7592
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7837
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7593
7838
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7594
7839
|
}
|
|
7595
7840
|
const dx = x2 - x1;
|
|
@@ -7599,7 +7844,7 @@ function createChart(element, options = {}) {
|
|
|
7599
7844
|
const t = Math.max(0, ((x - x1) * dx + (y - y1) * dy) / lengthSq);
|
|
7600
7845
|
const projX = x1 + t * dx;
|
|
7601
7846
|
const projY = y1 + t * dy;
|
|
7602
|
-
if (Math.hypot(x - projX, y - projY) <= 6) {
|
|
7847
|
+
if (Math.hypot(x - projX, y - projY) <= 6 * hitTolerance) {
|
|
7603
7848
|
return { drawing, target: "line" };
|
|
7604
7849
|
}
|
|
7605
7850
|
}
|
|
@@ -7611,17 +7856,17 @@ function createChart(element, options = {}) {
|
|
|
7611
7856
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7612
7857
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7613
7858
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7614
|
-
if (Math.hypot(x - x1, y - y1) <= 9) {
|
|
7859
|
+
if (Math.hypot(x - x1, y - y1) <= 9 * hitTolerance) {
|
|
7615
7860
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7616
7861
|
}
|
|
7617
|
-
if (Math.hypot(x - x2, y - y2) <= 9) {
|
|
7862
|
+
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
7618
7863
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7619
7864
|
}
|
|
7620
7865
|
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
7621
7866
|
for (const ratio of fibRatios) {
|
|
7622
7867
|
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
7623
7868
|
const lineY = canvasYFromDrawingPrice(price);
|
|
7624
|
-
if (Math.abs(y - lineY) <= 5) {
|
|
7869
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
7625
7870
|
return { drawing, target: "line" };
|
|
7626
7871
|
}
|
|
7627
7872
|
}
|
|
@@ -7634,30 +7879,30 @@ function createChart(element, options = {}) {
|
|
|
7634
7879
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7635
7880
|
const x1 = canvasXFromDrawingPoint(p1);
|
|
7636
7881
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7637
|
-
if (Math.hypot(x - x0, y - y0) <= 8) {
|
|
7882
|
+
if (Math.hypot(x - x0, y - y0) <= 8 * hitTolerance) {
|
|
7638
7883
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7639
7884
|
}
|
|
7640
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
7885
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7641
7886
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7642
7887
|
}
|
|
7643
7888
|
if (p2) {
|
|
7644
7889
|
const x2 = canvasXFromDrawingPoint(p2);
|
|
7645
7890
|
const y2 = canvasYFromDrawingPrice(p2.price);
|
|
7646
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
7891
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7647
7892
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
7648
7893
|
}
|
|
7649
7894
|
const move = p1.price - p0.price;
|
|
7650
7895
|
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
7651
7896
|
for (const ratio of fibExtRatios) {
|
|
7652
7897
|
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
7653
|
-
if (Math.abs(y - lineY) <= 5) {
|
|
7898
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
7654
7899
|
return { drawing, target: "line" };
|
|
7655
7900
|
}
|
|
7656
7901
|
}
|
|
7657
|
-
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 || distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
7902
|
+
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7658
7903
|
return { drawing, target: "line" };
|
|
7659
7904
|
}
|
|
7660
|
-
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6) {
|
|
7905
|
+
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance) {
|
|
7661
7906
|
return { drawing, target: "line" };
|
|
7662
7907
|
}
|
|
7663
7908
|
} else if (drawing.type === "long-position" || drawing.type === "short-position") {
|
|
@@ -7671,10 +7916,10 @@ function createChart(element, options = {}) {
|
|
|
7671
7916
|
const entryY = canvasYFromDrawingPrice(entry.price);
|
|
7672
7917
|
const targetY = canvasYFromDrawingPrice(target.price);
|
|
7673
7918
|
const stopY = canvasYFromDrawingPrice(stop.price);
|
|
7674
|
-
if (Math.hypot(x - leftX, y - targetY) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7675
|
-
if (Math.hypot(x - leftX, y - entryY) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7676
|
-
if (Math.hypot(x - leftX, y - stopY) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7677
|
-
if (Math.hypot(x - rightX, y - entryY) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7919
|
+
if (Math.hypot(x - leftX, y - targetY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7920
|
+
if (Math.hypot(x - leftX, y - entryY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7921
|
+
if (Math.hypot(x - leftX, y - stopY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7922
|
+
if (Math.hypot(x - rightX, y - entryY) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7678
7923
|
const x0 = Math.min(leftX, rightX);
|
|
7679
7924
|
const x1 = Math.max(leftX, rightX);
|
|
7680
7925
|
const yTop = Math.min(targetY, stopY, entryY);
|
|
@@ -7690,10 +7935,10 @@ function createChart(element, options = {}) {
|
|
|
7690
7935
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7691
7936
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7692
7937
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7693
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7694
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7695
|
-
if (Math.hypot(x - px0, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7696
|
-
if (Math.hypot(x - px1, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7938
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7939
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7940
|
+
if (Math.hypot(x - px0, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7941
|
+
if (Math.hypot(x - px1, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7697
7942
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
7698
7943
|
return { drawing, target: "line" };
|
|
7699
7944
|
}
|
|
@@ -7705,16 +7950,16 @@ function createChart(element, options = {}) {
|
|
|
7705
7950
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7706
7951
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7707
7952
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7708
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7709
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
7710
|
-
if (Math.hypot(x - px0, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 2 };
|
|
7711
|
-
if (Math.hypot(x - px1, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 3 };
|
|
7953
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7954
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7955
|
+
if (Math.hypot(x - px0, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7956
|
+
if (Math.hypot(x - px1, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 3 };
|
|
7712
7957
|
const cx = (px0 + px1) / 2;
|
|
7713
7958
|
const cy = (y0 + y1) / 2;
|
|
7714
7959
|
const rx = Math.max(1, Math.abs(px1 - px0) / 2);
|
|
7715
7960
|
const ry = Math.max(1, Math.abs(y1 - y0) / 2);
|
|
7716
7961
|
const norm = ((x - cx) / rx) ** 2 + ((y - cy) / ry) ** 2;
|
|
7717
|
-
if (norm <= 1) {
|
|
7962
|
+
if (norm <= 1 * hitTolerance) {
|
|
7718
7963
|
return { drawing, target: "line" };
|
|
7719
7964
|
}
|
|
7720
7965
|
} else if (drawing.type === "parallel-channel") {
|
|
@@ -7726,18 +7971,18 @@ function createChart(element, options = {}) {
|
|
|
7726
7971
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7727
7972
|
const x1 = canvasXFromDrawingPoint(p1);
|
|
7728
7973
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7729
|
-
if (Math.hypot(x - x0, y - y0) <= 8) return { drawing, target: "handle", pointIndex: 0 };
|
|
7730
|
-
if (Math.hypot(x - x1, y - y1) <= 8) return { drawing, target: "handle", pointIndex: 1 };
|
|
7974
|
+
if (Math.hypot(x - x0, y - y0) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7975
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7731
7976
|
if (p2) {
|
|
7732
7977
|
const x2 = canvasXFromDrawingPoint(p2);
|
|
7733
7978
|
const y2 = canvasYFromDrawingPrice(p2.price);
|
|
7734
|
-
if (Math.hypot(x - x2, y - y2) <= 8) return { drawing, target: "handle", pointIndex: 2 };
|
|
7979
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) return { drawing, target: "handle", pointIndex: 2 };
|
|
7735
7980
|
const indexSpan = p1.index - p0.index;
|
|
7736
7981
|
const slope = indexSpan !== 0 ? (p1.price - p0.price) / indexSpan : 0;
|
|
7737
7982
|
const offset = p2.price - (p0.price + slope * (p2.index - p0.index));
|
|
7738
7983
|
const q0y = canvasYFromDrawingPrice(p0.price + offset);
|
|
7739
7984
|
const q1y = canvasYFromDrawingPrice(p1.price + offset);
|
|
7740
|
-
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 || distanceToSegment(x, y, x0, q0y, x1, q1y) <= 6) {
|
|
7985
|
+
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x0, q0y, x1, q1y) <= 6 * hitTolerance) {
|
|
7741
7986
|
return { drawing, target: "line" };
|
|
7742
7987
|
}
|
|
7743
7988
|
const minX = Math.min(x0, x1);
|
|
@@ -7750,7 +7995,7 @@ function createChart(element, options = {}) {
|
|
|
7750
7995
|
return { drawing, target: "line" };
|
|
7751
7996
|
}
|
|
7752
7997
|
}
|
|
7753
|
-
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6) {
|
|
7998
|
+
} else if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance) {
|
|
7754
7999
|
return { drawing, target: "line" };
|
|
7755
8000
|
}
|
|
7756
8001
|
} else if (drawing.type === "arrow") {
|
|
@@ -7761,13 +8006,13 @@ function createChart(element, options = {}) {
|
|
|
7761
8006
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
7762
8007
|
const x2 = canvasXFromDrawingPoint(second);
|
|
7763
8008
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
7764
|
-
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
8009
|
+
if (Math.hypot(x - x1, y - y1) <= 8 * hitTolerance) {
|
|
7765
8010
|
return { drawing, target: "handle", pointIndex: 0 };
|
|
7766
8011
|
}
|
|
7767
|
-
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
8012
|
+
if (Math.hypot(x - x2, y - y2) <= 8 * hitTolerance) {
|
|
7768
8013
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
7769
8014
|
}
|
|
7770
|
-
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
8015
|
+
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
7771
8016
|
return { drawing, target: "line" };
|
|
7772
8017
|
}
|
|
7773
8018
|
} else if (drawing.type === "brush") {
|
|
@@ -7779,7 +8024,7 @@ function createChart(element, options = {}) {
|
|
|
7779
8024
|
for (let i = 1; i < pts.length; i += 1) {
|
|
7780
8025
|
const nextX = canvasXFromDrawingPoint(pts[i]);
|
|
7781
8026
|
const nextY = canvasYFromDrawingPrice(pts[i].price);
|
|
7782
|
-
if (distanceToSegment(x, y, prevX, prevY, nextX, nextY) <= 7) {
|
|
8027
|
+
if (distanceToSegment(x, y, prevX, prevY, nextX, nextY) <= 7 * hitTolerance) {
|
|
7783
8028
|
hitBody = true;
|
|
7784
8029
|
break;
|
|
7785
8030
|
}
|
|
@@ -7797,8 +8042,8 @@ function createChart(element, options = {}) {
|
|
|
7797
8042
|
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
7798
8043
|
const bx = canvasXFromDrawingPoint(boxPoint);
|
|
7799
8044
|
const by = canvasYFromDrawingPrice(boxPoint.price);
|
|
7800
|
-
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7801
|
-
if (Math.hypot(x - bx, y - by) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
8045
|
+
if (Math.hypot(x - ax, y - ay) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
8046
|
+
if (Math.hypot(x - bx, y - by) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7802
8047
|
const fontSize = Math.max(6, drawing.fontSize);
|
|
7803
8048
|
const prevFont = ctx.font;
|
|
7804
8049
|
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
@@ -7814,7 +8059,7 @@ function createChart(element, options = {}) {
|
|
|
7814
8059
|
if (x >= bx && x <= bx + blockW && y >= by && y <= by + blockH) {
|
|
7815
8060
|
return { drawing, target: "line" };
|
|
7816
8061
|
}
|
|
7817
|
-
if (distanceToSegment(x, y, bx + blockW / 2, by + blockH / 2, ax, ay) <= 5) {
|
|
8062
|
+
if (distanceToSegment(x, y, bx + blockW / 2, by + blockH / 2, ax, ay) <= 5 * hitTolerance) {
|
|
7818
8063
|
return { drawing, target: "line" };
|
|
7819
8064
|
}
|
|
7820
8065
|
} else if (drawing.type === "price-range") {
|
|
@@ -7825,8 +8070,8 @@ function createChart(element, options = {}) {
|
|
|
7825
8070
|
const px1 = canvasXFromDrawingPoint(p1);
|
|
7826
8071
|
const y0 = canvasYFromDrawingPrice(p0.price);
|
|
7827
8072
|
const y1 = canvasYFromDrawingPrice(p1.price);
|
|
7828
|
-
if (Math.hypot(x - px0, y - y0) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
7829
|
-
if (Math.hypot(x - px1, y - y1) <= 9) return { drawing, target: "handle", pointIndex: 1 };
|
|
8073
|
+
if (Math.hypot(x - px0, y - y0) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
8074
|
+
if (Math.hypot(x - px1, y - y1) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 1 };
|
|
7830
8075
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
7831
8076
|
return { drawing, target: "line" };
|
|
7832
8077
|
}
|
|
@@ -7835,7 +8080,7 @@ function createChart(element, options = {}) {
|
|
|
7835
8080
|
if (!anchor) continue;
|
|
7836
8081
|
const ax = canvasXFromDrawingPoint(anchor);
|
|
7837
8082
|
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
7838
|
-
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
8083
|
+
if (Math.hypot(x - ax, y - ay) <= 9 * hitTolerance) return { drawing, target: "handle", pointIndex: 0 };
|
|
7839
8084
|
const fontSize = Math.max(6, drawing.fontSize);
|
|
7840
8085
|
const prevFont = ctx.font;
|
|
7841
8086
|
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
@@ -7930,8 +8175,9 @@ function createChart(element, options = {}) {
|
|
|
7930
8175
|
if (!drawState || x < drawState.chartLeft || x > drawState.chartRight) {
|
|
7931
8176
|
return null;
|
|
7932
8177
|
}
|
|
8178
|
+
const dividerTolerance = touchInputActive ? 4 * Math.max(1, mergedOptions.touch?.hitToleranceScale ?? 2.2) : 4;
|
|
7933
8179
|
for (const pane of paneLayoutInfos) {
|
|
7934
|
-
if (pane.visible && Math.abs(y - pane.top) <=
|
|
8180
|
+
if (pane.visible && Math.abs(y - pane.top) <= dividerTolerance) {
|
|
7935
8181
|
return { id: pane.id, heightPx: pane.bottom - pane.top };
|
|
7936
8182
|
}
|
|
7937
8183
|
}
|
|
@@ -8424,7 +8670,43 @@ function createChart(element, options = {}) {
|
|
|
8424
8670
|
let lastPointerX = 0;
|
|
8425
8671
|
let lastPointerY = 0;
|
|
8426
8672
|
let activePointerId = null;
|
|
8673
|
+
let touchInputActive = false;
|
|
8427
8674
|
const touchPointers = /* @__PURE__ */ new Map();
|
|
8675
|
+
let longPressTimerId = null;
|
|
8676
|
+
let longPressState = null;
|
|
8677
|
+
const cancelLongPressTimer = () => {
|
|
8678
|
+
if (longPressTimerId !== null) {
|
|
8679
|
+
clearTimeout(longPressTimerId);
|
|
8680
|
+
longPressTimerId = null;
|
|
8681
|
+
}
|
|
8682
|
+
};
|
|
8683
|
+
const emitLongPress = (x, y, scrubbing) => {
|
|
8684
|
+
if (!longPressHandler) return;
|
|
8685
|
+
const rect = canvas.getBoundingClientRect();
|
|
8686
|
+
const index = indexFromCanvasX(x);
|
|
8687
|
+
const barTime = index === null ? null : getTimeForIndex(index);
|
|
8688
|
+
const bar = index === null ? void 0 : data[index];
|
|
8689
|
+
longPressHandler({
|
|
8690
|
+
x,
|
|
8691
|
+
y,
|
|
8692
|
+
clientX: rect.left + x,
|
|
8693
|
+
clientY: rect.top + y,
|
|
8694
|
+
scrubbing,
|
|
8695
|
+
...getHitRegion(x, y) === "plot" ? { price: roundToPricePrecision(priceFromCanvasY(y)) } : {},
|
|
8696
|
+
...index === null ? {} : { index },
|
|
8697
|
+
...barTime ? { time: barTime.toISOString() } : {},
|
|
8698
|
+
...bar ? {
|
|
8699
|
+
point: {
|
|
8700
|
+
t: bar.time.toISOString(),
|
|
8701
|
+
o: bar.o,
|
|
8702
|
+
h: bar.h,
|
|
8703
|
+
l: bar.l,
|
|
8704
|
+
c: bar.c,
|
|
8705
|
+
...bar.v === void 0 ? {} : { v: bar.v }
|
|
8706
|
+
}
|
|
8707
|
+
} : {}
|
|
8708
|
+
});
|
|
8709
|
+
};
|
|
8428
8710
|
let pinchZoomState = null;
|
|
8429
8711
|
const getTouchPair = () => {
|
|
8430
8712
|
const points = Array.from(touchPointers.values());
|
|
@@ -8490,7 +8772,8 @@ function createChart(element, options = {}) {
|
|
|
8490
8772
|
}
|
|
8491
8773
|
};
|
|
8492
8774
|
const onPointerDown = (event) => {
|
|
8493
|
-
|
|
8775
|
+
touchInputActive = event.pointerType === "touch" || event.pointerType === "pen";
|
|
8776
|
+
if (touchInputActive) {
|
|
8494
8777
|
event.preventDefault();
|
|
8495
8778
|
}
|
|
8496
8779
|
if (mergedOptions.accessibility?.focusable !== false && document.activeElement !== canvas) {
|
|
@@ -8507,9 +8790,25 @@ function createChart(element, options = {}) {
|
|
|
8507
8790
|
capturePointer(event.pointerId);
|
|
8508
8791
|
const touchPair = getTouchPair();
|
|
8509
8792
|
if (touchPair) {
|
|
8793
|
+
cancelLongPressTimer();
|
|
8794
|
+
longPressState = null;
|
|
8510
8795
|
beginPinchZoom(touchPair[0], touchPair[1]);
|
|
8511
8796
|
return;
|
|
8512
8797
|
}
|
|
8798
|
+
cancelLongPressTimer();
|
|
8799
|
+
longPressState = null;
|
|
8800
|
+
const touchOptions = mergedOptions.touch ?? {};
|
|
8801
|
+
const wantsTooltip = touchOptions.longPressTooltip !== false || longPressHandler !== null;
|
|
8802
|
+
if (wantsTooltip && !activeDrawingTool && !draftDrawing && getHitRegion(point.x, point.y) === "plot") {
|
|
8803
|
+
const pointerId = event.pointerId;
|
|
8804
|
+
longPressTimerId = window.setTimeout(() => {
|
|
8805
|
+
longPressTimerId = null;
|
|
8806
|
+
longPressState = { pointerId, x: point.x, y: point.y };
|
|
8807
|
+
setCrosshairPoint(point);
|
|
8808
|
+
scheduleDraw({ overlayOnly: true });
|
|
8809
|
+
emitLongPress(point.x, point.y, false);
|
|
8810
|
+
}, Math.max(120, touchOptions.longPressMs ?? 400));
|
|
8811
|
+
}
|
|
8513
8812
|
}
|
|
8514
8813
|
if (measureState) {
|
|
8515
8814
|
if (measureState.dragging) {
|
|
@@ -8675,7 +8974,10 @@ function createChart(element, options = {}) {
|
|
|
8675
8974
|
};
|
|
8676
8975
|
const onPointerMove = (event) => {
|
|
8677
8976
|
if (event.pointerType === "touch" || event.pointerType === "pen") {
|
|
8977
|
+
touchInputActive = true;
|
|
8678
8978
|
event.preventDefault();
|
|
8979
|
+
} else if (event.pointerType === "mouse") {
|
|
8980
|
+
touchInputActive = false;
|
|
8679
8981
|
}
|
|
8680
8982
|
magnetModifierActive = event.metaKey || event.ctrlKey;
|
|
8681
8983
|
shiftKeyActive = event.shiftKey;
|
|
@@ -8684,6 +8986,8 @@ function createChart(element, options = {}) {
|
|
|
8684
8986
|
touchPointers.set(event.pointerId, point);
|
|
8685
8987
|
const touchPair = getTouchPair();
|
|
8686
8988
|
if (touchPair) {
|
|
8989
|
+
cancelLongPressTimer();
|
|
8990
|
+
longPressState = null;
|
|
8687
8991
|
if (!pinchZoomState) {
|
|
8688
8992
|
beginPinchZoom(touchPair[0], touchPair[1]);
|
|
8689
8993
|
}
|
|
@@ -8693,6 +8997,21 @@ function createChart(element, options = {}) {
|
|
|
8693
8997
|
if (pinchZoomState) {
|
|
8694
8998
|
return;
|
|
8695
8999
|
}
|
|
9000
|
+
if (longPressState && longPressState.pointerId === event.pointerId) {
|
|
9001
|
+
longPressState = { ...longPressState, x: point.x, y: point.y };
|
|
9002
|
+
setCrosshairPoint(point);
|
|
9003
|
+
emitCrosshairMove(point.x, point.y, getHitRegion(point.x, point.y) === "plot" ? "plot" : "plot");
|
|
9004
|
+
scheduleDraw({ overlayOnly: true });
|
|
9005
|
+
emitLongPress(point.x, point.y, true);
|
|
9006
|
+
return;
|
|
9007
|
+
}
|
|
9008
|
+
if (longPressTimerId !== null) {
|
|
9009
|
+
const dx = point.x - (pointerDownInfo?.x ?? point.x);
|
|
9010
|
+
const dy = point.y - (pointerDownInfo?.y ?? point.y);
|
|
9011
|
+
if (dx * dx + dy * dy > 36) {
|
|
9012
|
+
cancelLongPressTimer();
|
|
9013
|
+
}
|
|
9014
|
+
}
|
|
8696
9015
|
}
|
|
8697
9016
|
if (pointerDownInfo && pointerDownInfo.pointerId === event.pointerId && !pointerDownInfo.moved) {
|
|
8698
9017
|
const dx = point.x - pointerDownInfo.x;
|
|
@@ -8956,6 +9275,18 @@ function createChart(element, options = {}) {
|
|
|
8956
9275
|
lastPointerY = point.y;
|
|
8957
9276
|
};
|
|
8958
9277
|
const endPointerDrag = (event) => {
|
|
9278
|
+
cancelLongPressTimer();
|
|
9279
|
+
if (longPressState && (!event || event.pointerId === longPressState.pointerId)) {
|
|
9280
|
+
longPressState = null;
|
|
9281
|
+
touchPointers.delete(event?.pointerId ?? -1);
|
|
9282
|
+
setCrosshairPoint(null);
|
|
9283
|
+
isDragging = false;
|
|
9284
|
+
dragMode = null;
|
|
9285
|
+
activePointerId = null;
|
|
9286
|
+
pointerDownInfo = null;
|
|
9287
|
+
scheduleDraw({ overlayOnly: true });
|
|
9288
|
+
return;
|
|
9289
|
+
}
|
|
8959
9290
|
if (event?.pointerType === "touch") {
|
|
8960
9291
|
touchPointers.delete(event.pointerId);
|
|
8961
9292
|
if (pinchZoomState) {
|
|
@@ -9363,6 +9694,23 @@ function createChart(element, options = {}) {
|
|
|
9363
9694
|
window.addEventListener("blur", onWindowBlurMagnet);
|
|
9364
9695
|
}
|
|
9365
9696
|
const updateOptions = (nextOptions) => {
|
|
9697
|
+
const THEMED_OPTION_KEYS = [
|
|
9698
|
+
"backgroundColor",
|
|
9699
|
+
"upColor",
|
|
9700
|
+
"downColor",
|
|
9701
|
+
"lineColor",
|
|
9702
|
+
"gridColor",
|
|
9703
|
+
"axisColor",
|
|
9704
|
+
"grid",
|
|
9705
|
+
"axis",
|
|
9706
|
+
"xAxis",
|
|
9707
|
+
"yAxis",
|
|
9708
|
+
"crosshair",
|
|
9709
|
+
"watermark"
|
|
9710
|
+
];
|
|
9711
|
+
if (THEMED_OPTION_KEYS.some((key) => nextOptions[key] !== void 0) || nextOptions.labels?.indicatorTextColor !== void 0) {
|
|
9712
|
+
activeThemeName = null;
|
|
9713
|
+
}
|
|
9366
9714
|
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
9367
9715
|
const previousWidth = width;
|
|
9368
9716
|
const previousHeight = height;
|
|
@@ -9391,6 +9739,30 @@ function createChart(element, options = {}) {
|
|
|
9391
9739
|
}
|
|
9392
9740
|
scheduleDraw();
|
|
9393
9741
|
};
|
|
9742
|
+
const setTheme = (theme) => {
|
|
9743
|
+
const resolved = resolveTheme(theme);
|
|
9744
|
+
updateOptions({
|
|
9745
|
+
backgroundColor: resolved.background,
|
|
9746
|
+
upColor: resolved.upColor,
|
|
9747
|
+
downColor: resolved.downColor,
|
|
9748
|
+
lineColor: resolved.lineColor,
|
|
9749
|
+
gridColor: resolved.gridColor,
|
|
9750
|
+
grid: { color: resolved.gridColor, opacity: resolved.gridOpacity },
|
|
9751
|
+
axis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9752
|
+
xAxis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9753
|
+
yAxis: { textColor: resolved.axisTextColor, lineColor: resolved.axisLineColor },
|
|
9754
|
+
crosshair: {
|
|
9755
|
+
color: resolved.crosshairColor,
|
|
9756
|
+
labelBackgroundColor: resolved.crosshairLabelBackground,
|
|
9757
|
+
labelTextColor: resolved.crosshairLabelText,
|
|
9758
|
+
labelBorderColor: resolved.crosshairLabelBorder
|
|
9759
|
+
},
|
|
9760
|
+
watermark: { color: resolved.watermarkColor },
|
|
9761
|
+
labels: { indicatorTextColor: resolved.indicatorTextColor }
|
|
9762
|
+
});
|
|
9763
|
+
activeThemeName = resolved.name;
|
|
9764
|
+
};
|
|
9765
|
+
const getTheme = () => activeThemeName;
|
|
9394
9766
|
const setChartType = (type) => {
|
|
9395
9767
|
if (mergedOptions.chartType === type) {
|
|
9396
9768
|
return;
|
|
@@ -9772,6 +10144,9 @@ function createChart(element, options = {}) {
|
|
|
9772
10144
|
const onKeyboardShortcut = (handler) => {
|
|
9773
10145
|
keyboardShortcutHandler = handler;
|
|
9774
10146
|
};
|
|
10147
|
+
const onLongPress = (handler) => {
|
|
10148
|
+
longPressHandler = handler;
|
|
10149
|
+
};
|
|
9775
10150
|
const focus = () => {
|
|
9776
10151
|
canvas.focus({ preventScroll: true });
|
|
9777
10152
|
};
|
|
@@ -9825,6 +10200,10 @@ function createChart(element, options = {}) {
|
|
|
9825
10200
|
return canvas.toDataURL(options2.type ?? "image/png", options2.quality);
|
|
9826
10201
|
};
|
|
9827
10202
|
const destroy = () => {
|
|
10203
|
+
cancelLongPressTimer();
|
|
10204
|
+
datafeedUnsubscribe?.();
|
|
10205
|
+
datafeedUnsubscribe = null;
|
|
10206
|
+
datafeed = null;
|
|
9828
10207
|
cancelKineticPan();
|
|
9829
10208
|
if (smoothingRafId !== null) {
|
|
9830
10209
|
cancelAnimationFrame(smoothingRafId);
|
|
@@ -9912,10 +10291,14 @@ function createChart(element, options = {}) {
|
|
|
9912
10291
|
getMagnetMode,
|
|
9913
10292
|
setPriceScale,
|
|
9914
10293
|
getPriceScale,
|
|
10294
|
+
setTheme,
|
|
10295
|
+
getTheme,
|
|
9915
10296
|
setCompareSeries,
|
|
9916
10297
|
addCompareSeries,
|
|
9917
10298
|
removeCompareSeries,
|
|
9918
10299
|
getCompareSeries,
|
|
10300
|
+
setDatafeed,
|
|
10301
|
+
onLongPress,
|
|
9919
10302
|
cancelDrawing,
|
|
9920
10303
|
setTradeMarkers,
|
|
9921
10304
|
setSelectedDrawing,
|
|
@@ -9940,6 +10323,8 @@ function createChart(element, options = {}) {
|
|
|
9940
10323
|
}
|
|
9941
10324
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9942
10325
|
0 && (module.exports = {
|
|
10326
|
+
CHART_THEMES,
|
|
10327
|
+
CHART_THEME_NAMES,
|
|
9943
10328
|
FIB_DEFAULT_PALETTE,
|
|
9944
10329
|
POSITION_DEFAULT_COLORS,
|
|
9945
10330
|
SCRIPT_SOURCE_INPUT_VALUES,
|