hyperprop-charting-library 0.1.7 → 0.1.9
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 +245 -38
- package/dist/hyperprop-charting-library.d.ts +31 -1
- package/dist/hyperprop-charting-library.js +245 -38
- package/dist/index.cjs +144 -3
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +144 -3
- package/docs/API.md +14 -4
- package/docs/EVENTS.md +33 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -47,6 +47,15 @@ interface CrosshairOptions {
|
|
|
47
47
|
style?: "solid" | "dotted" | "dashed";
|
|
48
48
|
showHorizontal?: boolean;
|
|
49
49
|
showVertical?: boolean;
|
|
50
|
+
showPriceLabel?: boolean;
|
|
51
|
+
showTimeLabel?: boolean;
|
|
52
|
+
timeLabelFormat?: "auto" | "date" | "time" | "datetime";
|
|
53
|
+
labelBackgroundColor?: string;
|
|
54
|
+
labelTextColor?: string;
|
|
55
|
+
labelBorderRadius?: number;
|
|
56
|
+
labelBorderColor?: string;
|
|
57
|
+
labelBorderWidth?: number;
|
|
58
|
+
labelBorderStyle?: "solid" | "dotted" | "dashed";
|
|
50
59
|
}
|
|
51
60
|
interface WatermarkOptions {
|
|
52
61
|
visible?: boolean;
|
|
@@ -143,6 +152,15 @@ interface ChartClickEvent {
|
|
|
143
152
|
price?: number;
|
|
144
153
|
region: "plot" | "x-axis" | "y-axis";
|
|
145
154
|
}
|
|
155
|
+
interface CrosshairMoveEvent {
|
|
156
|
+
x: number;
|
|
157
|
+
y: number;
|
|
158
|
+
region: "plot" | "x-axis" | "y-axis";
|
|
159
|
+
price?: number;
|
|
160
|
+
index?: number;
|
|
161
|
+
time?: string;
|
|
162
|
+
point?: OhlcDataPoint;
|
|
163
|
+
}
|
|
146
164
|
interface TickerLineOptions {
|
|
147
165
|
visible?: boolean;
|
|
148
166
|
style?: "solid" | "dotted" | "dashed";
|
|
@@ -163,6 +181,7 @@ interface ChartInstance {
|
|
|
163
181
|
removeOrderLine: (id: string) => void;
|
|
164
182
|
onOrderAction: (handler: ((event: OrderActionEvent) => void) | null) => void;
|
|
165
183
|
onChartClick: (handler: ((event: ChartClickEvent) => void) | null) => void;
|
|
184
|
+
onCrosshairMove: (handler: ((event: CrosshairMoveEvent) => void) | null) => void;
|
|
166
185
|
setDoubleClickEnabled: (enabled: boolean) => void;
|
|
167
186
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
168
187
|
resize: (width?: number, height?: number) => void;
|
|
@@ -178,4 +197,4 @@ interface OhlcDataPoint {
|
|
|
178
197
|
}
|
|
179
198
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
180
199
|
|
|
181
|
-
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairOptions, type GridOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
|
200
|
+
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type GridOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,15 @@ interface CrosshairOptions {
|
|
|
47
47
|
style?: "solid" | "dotted" | "dashed";
|
|
48
48
|
showHorizontal?: boolean;
|
|
49
49
|
showVertical?: boolean;
|
|
50
|
+
showPriceLabel?: boolean;
|
|
51
|
+
showTimeLabel?: boolean;
|
|
52
|
+
timeLabelFormat?: "auto" | "date" | "time" | "datetime";
|
|
53
|
+
labelBackgroundColor?: string;
|
|
54
|
+
labelTextColor?: string;
|
|
55
|
+
labelBorderRadius?: number;
|
|
56
|
+
labelBorderColor?: string;
|
|
57
|
+
labelBorderWidth?: number;
|
|
58
|
+
labelBorderStyle?: "solid" | "dotted" | "dashed";
|
|
50
59
|
}
|
|
51
60
|
interface WatermarkOptions {
|
|
52
61
|
visible?: boolean;
|
|
@@ -143,6 +152,15 @@ interface ChartClickEvent {
|
|
|
143
152
|
price?: number;
|
|
144
153
|
region: "plot" | "x-axis" | "y-axis";
|
|
145
154
|
}
|
|
155
|
+
interface CrosshairMoveEvent {
|
|
156
|
+
x: number;
|
|
157
|
+
y: number;
|
|
158
|
+
region: "plot" | "x-axis" | "y-axis";
|
|
159
|
+
price?: number;
|
|
160
|
+
index?: number;
|
|
161
|
+
time?: string;
|
|
162
|
+
point?: OhlcDataPoint;
|
|
163
|
+
}
|
|
146
164
|
interface TickerLineOptions {
|
|
147
165
|
visible?: boolean;
|
|
148
166
|
style?: "solid" | "dotted" | "dashed";
|
|
@@ -163,6 +181,7 @@ interface ChartInstance {
|
|
|
163
181
|
removeOrderLine: (id: string) => void;
|
|
164
182
|
onOrderAction: (handler: ((event: OrderActionEvent) => void) | null) => void;
|
|
165
183
|
onChartClick: (handler: ((event: ChartClickEvent) => void) | null) => void;
|
|
184
|
+
onCrosshairMove: (handler: ((event: CrosshairMoveEvent) => void) | null) => void;
|
|
166
185
|
setDoubleClickEnabled: (enabled: boolean) => void;
|
|
167
186
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
168
187
|
resize: (width?: number, height?: number) => void;
|
|
@@ -178,4 +197,4 @@ interface OhlcDataPoint {
|
|
|
178
197
|
}
|
|
179
198
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
180
199
|
|
|
181
|
-
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairOptions, type GridOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
|
200
|
+
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type GridOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,16 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
18
18
|
width: 1,
|
|
19
19
|
style: "dotted",
|
|
20
20
|
showHorizontal: true,
|
|
21
|
-
showVertical: true
|
|
21
|
+
showVertical: true,
|
|
22
|
+
showPriceLabel: true,
|
|
23
|
+
showTimeLabel: true,
|
|
24
|
+
timeLabelFormat: "auto",
|
|
25
|
+
labelBackgroundColor: "#0b1220",
|
|
26
|
+
labelTextColor: "#cbd5e1",
|
|
27
|
+
labelBorderRadius: 3,
|
|
28
|
+
labelBorderColor: "#94a3b8",
|
|
29
|
+
labelBorderWidth: 1,
|
|
30
|
+
labelBorderStyle: "solid"
|
|
22
31
|
};
|
|
23
32
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
24
33
|
visible: false,
|
|
@@ -152,6 +161,7 @@ function createChart(element, options = {}) {
|
|
|
152
161
|
}));
|
|
153
162
|
let orderActionHandler = null;
|
|
154
163
|
let chartClickHandler = null;
|
|
164
|
+
let crosshairMoveHandler = null;
|
|
155
165
|
let orderActionRegions = [];
|
|
156
166
|
let orderDragRegions = [];
|
|
157
167
|
let generatedPriceLineId = 1;
|
|
@@ -339,6 +349,42 @@ function createChart(element, options = {}) {
|
|
|
339
349
|
const extra = index - (data.length - 1);
|
|
340
350
|
return new Date(last.time.getTime() + extra * stepMs);
|
|
341
351
|
};
|
|
352
|
+
const formatHoverTimeLabel = (time, mode) => {
|
|
353
|
+
if (mode === "time") {
|
|
354
|
+
return time.toLocaleTimeString(void 0, {
|
|
355
|
+
hour: "2-digit",
|
|
356
|
+
minute: "2-digit",
|
|
357
|
+
hour12: false
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (mode === "datetime") {
|
|
361
|
+
return time.toLocaleString(void 0, {
|
|
362
|
+
month: "short",
|
|
363
|
+
day: "numeric",
|
|
364
|
+
hour: "2-digit",
|
|
365
|
+
minute: "2-digit",
|
|
366
|
+
hour12: false
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
if (mode === "date") {
|
|
370
|
+
return time.toLocaleDateString(void 0, {
|
|
371
|
+
month: "short",
|
|
372
|
+
day: "numeric"
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
const stepMs = getTimeStepMs();
|
|
376
|
+
if (stepMs < 24 * 60 * 60 * 1e3) {
|
|
377
|
+
return time.toLocaleTimeString(void 0, {
|
|
378
|
+
hour: "2-digit",
|
|
379
|
+
minute: "2-digit",
|
|
380
|
+
hour12: false
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return time.toLocaleDateString(void 0, {
|
|
384
|
+
month: "short",
|
|
385
|
+
day: "numeric"
|
|
386
|
+
});
|
|
387
|
+
};
|
|
342
388
|
const drawText = (text, x, y, align = "left", baseline = "alphabetic", color = mergedOptions.axis?.textColor ?? mergedOptions.axisColor) => {
|
|
343
389
|
ctx.fillStyle = color;
|
|
344
390
|
ctx.textAlign = align;
|
|
@@ -985,6 +1031,61 @@ function createChart(element, options = {}) {
|
|
|
985
1031
|
});
|
|
986
1032
|
drawText(timeLabel, x, chartBottom + 8, "center", "top", axis.textColor);
|
|
987
1033
|
}
|
|
1034
|
+
if (crosshair.visible && crosshairPoint) {
|
|
1035
|
+
const cx = clamp(crosshairPoint.x, chartLeft, chartRight);
|
|
1036
|
+
const cy = clamp(crosshairPoint.y, chartTop, chartBottom);
|
|
1037
|
+
const labelPaddingX = 8;
|
|
1038
|
+
const labelHeight = 20;
|
|
1039
|
+
const labelRadius = Math.max(0, crosshair.labelBorderRadius);
|
|
1040
|
+
const labelBackground = crosshair.labelBackgroundColor;
|
|
1041
|
+
const labelTextColor = crosshair.labelTextColor;
|
|
1042
|
+
const labelBorderColor = crosshair.labelBorderColor;
|
|
1043
|
+
const labelBorderWidth = Math.max(0, crosshair.labelBorderWidth);
|
|
1044
|
+
const labelBorderStyle = crosshair.labelBorderStyle;
|
|
1045
|
+
const strokeCrosshairLabel = (x, y, widthValue) => {
|
|
1046
|
+
if (labelBorderWidth <= 0) {
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
ctx.save();
|
|
1050
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1051
|
+
ctx.lineWidth = labelBorderWidth;
|
|
1052
|
+
if (labelBorderStyle === "dotted") {
|
|
1053
|
+
ctx.setLineDash([2, 3]);
|
|
1054
|
+
} else if (labelBorderStyle === "dashed") {
|
|
1055
|
+
ctx.setLineDash([6, 4]);
|
|
1056
|
+
} else {
|
|
1057
|
+
ctx.setLineDash([]);
|
|
1058
|
+
}
|
|
1059
|
+
strokeRoundedRect(Math.round(x), Math.round(y), widthValue, labelHeight, labelRadius);
|
|
1060
|
+
ctx.restore();
|
|
1061
|
+
};
|
|
1062
|
+
if (crosshair.showPriceLabel) {
|
|
1063
|
+
const hoverPrice = yMin + (chartBottom - cy) / chartHeight * yRange;
|
|
1064
|
+
const priceText = formatPrice(hoverPrice);
|
|
1065
|
+
const priceWidth = Math.ceil(ctx.measureText(priceText).width) + labelPaddingX * 2;
|
|
1066
|
+
const priceX = chartRight + 4;
|
|
1067
|
+
const priceY = clamp(cy - labelHeight / 2, chartTop, chartBottom - labelHeight);
|
|
1068
|
+
ctx.fillStyle = labelBackground;
|
|
1069
|
+
fillRoundedRect(Math.round(priceX), Math.round(priceY), priceWidth, labelHeight, labelRadius);
|
|
1070
|
+
strokeCrosshairLabel(priceX, priceY, priceWidth);
|
|
1071
|
+
drawText(priceText, priceX + labelPaddingX, priceY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1072
|
+
}
|
|
1073
|
+
if (crosshair.showTimeLabel) {
|
|
1074
|
+
const ratio = clamp((cx - chartLeft) / chartWidth, 0, 1);
|
|
1075
|
+
const hoverIndex = Math.round(xStart + ratio * xSpan - 0.5);
|
|
1076
|
+
const hoverTime = getTimeForIndex(hoverIndex);
|
|
1077
|
+
if (hoverTime) {
|
|
1078
|
+
const timeText = formatHoverTimeLabel(hoverTime, crosshair.timeLabelFormat);
|
|
1079
|
+
const timeWidth = Math.ceil(ctx.measureText(timeText).width) + labelPaddingX * 2;
|
|
1080
|
+
const timeX = clamp(cx - timeWidth / 2, chartLeft, chartRight - timeWidth);
|
|
1081
|
+
const timeY = chartBottom + 8;
|
|
1082
|
+
ctx.fillStyle = labelBackground;
|
|
1083
|
+
fillRoundedRect(Math.round(timeX), Math.round(timeY), timeWidth, labelHeight, labelRadius);
|
|
1084
|
+
strokeCrosshairLabel(timeX, timeY, timeWidth);
|
|
1085
|
+
drawText(timeText, timeX + labelPaddingX, timeY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
988
1089
|
};
|
|
989
1090
|
const zoomX = (factor, anchorX) => {
|
|
990
1091
|
if (!drawState || data.length === 0) {
|
|
@@ -1079,6 +1180,39 @@ function createChart(element, options = {}) {
|
|
|
1079
1180
|
const ratio = clamp((drawState.chartBottom - y) / drawState.chartHeight, 0, 1);
|
|
1080
1181
|
return drawState.yMin + ratio * (drawState.yMax - drawState.yMin);
|
|
1081
1182
|
};
|
|
1183
|
+
const indexFromCanvasX = (x) => {
|
|
1184
|
+
if (!drawState) {
|
|
1185
|
+
return null;
|
|
1186
|
+
}
|
|
1187
|
+
const ratio = clamp((x - drawState.chartLeft) / drawState.chartWidth, 0, 1);
|
|
1188
|
+
return Math.round(drawState.xStart + ratio * drawState.xSpan - 0.5);
|
|
1189
|
+
};
|
|
1190
|
+
const emitCrosshairMove = (x, y, region) => {
|
|
1191
|
+
if (!crosshairMoveHandler) {
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
const index = indexFromCanvasX(x);
|
|
1195
|
+
const hoverTime = index === null ? null : getTimeForIndex(index);
|
|
1196
|
+
const parsedPoint = index === null ? void 0 : data[index];
|
|
1197
|
+
const point = parsedPoint === void 0 ? void 0 : {
|
|
1198
|
+
t: parsedPoint.time.toISOString(),
|
|
1199
|
+
o: parsedPoint.o,
|
|
1200
|
+
h: parsedPoint.h,
|
|
1201
|
+
l: parsedPoint.l,
|
|
1202
|
+
c: parsedPoint.c,
|
|
1203
|
+
...parsedPoint.v === void 0 ? {} : { v: parsedPoint.v }
|
|
1204
|
+
};
|
|
1205
|
+
const payload = {
|
|
1206
|
+
x,
|
|
1207
|
+
y,
|
|
1208
|
+
region,
|
|
1209
|
+
...region === "plot" ? { price: Number(priceFromCanvasY(y).toFixed(mergedOptions.priceDecimals)) } : {},
|
|
1210
|
+
...index === null ? {} : { index },
|
|
1211
|
+
...hoverTime ? { time: hoverTime.toISOString() } : {},
|
|
1212
|
+
...point ? { point } : {}
|
|
1213
|
+
};
|
|
1214
|
+
crosshairMoveHandler(payload);
|
|
1215
|
+
};
|
|
1082
1216
|
const getHitRegion = (x, y) => {
|
|
1083
1217
|
if (!drawState) {
|
|
1084
1218
|
return "outside";
|
|
@@ -1230,14 +1364,17 @@ function createChart(element, options = {}) {
|
|
|
1230
1364
|
}
|
|
1231
1365
|
const hoverRegion = getHitRegion(point.x, point.y);
|
|
1232
1366
|
if (hoverRegion === "plot") {
|
|
1233
|
-
canvas.style.cursor = "
|
|
1367
|
+
canvas.style.cursor = "default";
|
|
1234
1368
|
setCrosshairPoint(point);
|
|
1369
|
+
emitCrosshairMove(point.x, point.y, "plot");
|
|
1235
1370
|
} else if (hoverRegion === "x-axis") {
|
|
1236
1371
|
canvas.style.cursor = "ew-resize";
|
|
1237
1372
|
setCrosshairPoint(null);
|
|
1373
|
+
emitCrosshairMove(point.x, point.y, "x-axis");
|
|
1238
1374
|
} else if (hoverRegion === "y-axis") {
|
|
1239
1375
|
canvas.style.cursor = "ns-resize";
|
|
1240
1376
|
setCrosshairPoint(null);
|
|
1377
|
+
emitCrosshairMove(point.x, point.y, "y-axis");
|
|
1241
1378
|
} else {
|
|
1242
1379
|
canvas.style.cursor = "default";
|
|
1243
1380
|
setCrosshairPoint(null);
|
|
@@ -1247,7 +1384,7 @@ function createChart(element, options = {}) {
|
|
|
1247
1384
|
const deltaX = point.x - lastPointerX;
|
|
1248
1385
|
const deltaY = point.y - lastPointerY;
|
|
1249
1386
|
if (dragMode === "plot") {
|
|
1250
|
-
canvas.style.cursor = "
|
|
1387
|
+
canvas.style.cursor = "default";
|
|
1251
1388
|
pan(deltaX, deltaY, true, true);
|
|
1252
1389
|
setCrosshairPoint(null);
|
|
1253
1390
|
} else if (dragMode === "x-axis") {
|
|
@@ -1477,6 +1614,9 @@ function createChart(element, options = {}) {
|
|
|
1477
1614
|
const onChartClick = (handler) => {
|
|
1478
1615
|
chartClickHandler = handler;
|
|
1479
1616
|
};
|
|
1617
|
+
const onCrosshairMove = (handler) => {
|
|
1618
|
+
crosshairMoveHandler = handler;
|
|
1619
|
+
};
|
|
1480
1620
|
const setDoubleClickEnabled = (enabled) => {
|
|
1481
1621
|
doubleClickEnabled = enabled;
|
|
1482
1622
|
};
|
|
@@ -1505,6 +1645,7 @@ function createChart(element, options = {}) {
|
|
|
1505
1645
|
removeOrderLine,
|
|
1506
1646
|
onOrderAction,
|
|
1507
1647
|
onChartClick,
|
|
1648
|
+
onCrosshairMove,
|
|
1508
1649
|
setDoubleClickEnabled,
|
|
1509
1650
|
setDoubleClickAction,
|
|
1510
1651
|
resize,
|
package/docs/API.md
CHANGED
|
@@ -78,6 +78,15 @@ Top-level options:
|
|
|
78
78
|
- `style` (`"solid" | "dotted" | "dashed"`, default `"dotted"`)
|
|
79
79
|
- `showHorizontal` (default `true`)
|
|
80
80
|
- `showVertical` (default `true`)
|
|
81
|
+
- `showPriceLabel` (default `true`)
|
|
82
|
+
- `showTimeLabel` (default `true`)
|
|
83
|
+
- `timeLabelFormat` (`"auto" | "date" | "time" | "datetime"`, default `"auto"`)
|
|
84
|
+
- `labelBackgroundColor` (default `#0b1220`)
|
|
85
|
+
- `labelTextColor` (default `#cbd5e1`)
|
|
86
|
+
- `labelBorderRadius` (default `3`)
|
|
87
|
+
- `labelBorderColor` (default `#94a3b8`)
|
|
88
|
+
- `labelBorderWidth` (default `1`)
|
|
89
|
+
- `labelBorderStyle` (`"solid" | "dotted" | "dashed"`, default `"solid"`)
|
|
81
90
|
|
|
82
91
|
### `WatermarkOptions`
|
|
83
92
|
|
|
@@ -98,12 +107,12 @@ Top-level options:
|
|
|
98
107
|
### `TickerLineOptions`
|
|
99
108
|
|
|
100
109
|
- `visible` (default `true`)
|
|
101
|
-
- `style` (`"solid" | "dotted" | "dashed"`, default `"
|
|
110
|
+
- `style` (`"solid" | "dotted" | "dashed"`, default `"dotted"`)
|
|
102
111
|
- `thickness` (default `1`)
|
|
103
|
-
- `color` (default `#
|
|
104
|
-
- `labelBackgroundColor` (default `#
|
|
112
|
+
- `color` (default `#38bdf8`)
|
|
113
|
+
- `labelBackgroundColor` (default `#38bdf8`)
|
|
105
114
|
- `labelTextColor` (default `#0b1220`)
|
|
106
|
-
- `labelBorderRadius` (default `
|
|
115
|
+
- `labelBorderRadius` (default `3`)
|
|
107
116
|
|
|
108
117
|
### `PriceLineOptions`
|
|
109
118
|
|
|
@@ -203,6 +212,7 @@ Connector/fill visuals:
|
|
|
203
212
|
- `removeOrderLine(id: string): void`
|
|
204
213
|
- `onOrderAction(handler: ((event: OrderActionEvent) => void) | null): void`
|
|
205
214
|
- `onChartClick(handler: ((event: ChartClickEvent) => void) | null): void`
|
|
215
|
+
- `onCrosshairMove(handler: ((event: CrosshairMoveEvent) => void) | null): void`
|
|
206
216
|
- `setDoubleClickEnabled(enabled: boolean): void`
|
|
207
217
|
- `setDoubleClickAction(action: "reset" | "placeLimitOrder"): void`
|
|
208
218
|
- `resize(width?: number, height?: number): void`
|
package/docs/EVENTS.md
CHANGED
|
@@ -76,6 +76,39 @@ type ChartClickEvent = {
|
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
+
## `onCrosshairMove`
|
|
80
|
+
|
|
81
|
+
Register:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
chart.onCrosshairMove((event) => {
|
|
85
|
+
// update OHLC header, hover widgets, etc
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Payload type:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
type CrosshairMoveEvent = {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
region: "plot" | "x-axis" | "y-axis";
|
|
96
|
+
price?: number;
|
|
97
|
+
index?: number;
|
|
98
|
+
time?: string;
|
|
99
|
+
point?: OhlcDataPoint;
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Notes
|
|
104
|
+
|
|
105
|
+
- Fires while hovering in chart regions.
|
|
106
|
+
- For plot hover, `price` is included.
|
|
107
|
+
- `point` is included when hover maps to an existing candle index.
|
|
108
|
+
- Use this to implement TradingView-style dynamic OHLC readout in your app header.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
79
112
|
## Double-click integration
|
|
80
113
|
|
|
81
114
|
Set behavior:
|