hyperprop-charting-library 0.1.137 → 0.1.138
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 +316 -1
- package/dist/hyperprop-charting-library.d.ts +117 -1
- package/dist/hyperprop-charting-library.js +316 -1
- package/dist/index.cjs +316 -1
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +316 -1
- package/docs/API.md +100 -0
- package/package.json +1 -1
|
@@ -2819,6 +2819,8 @@ var DEFAULT_OPTIONS = {
|
|
|
2819
2819
|
pinOutOfRangeLines: false,
|
|
2820
2820
|
doubleClickEnabled: true,
|
|
2821
2821
|
doubleClickAction: "reset",
|
|
2822
|
+
keyboard: { enabled: true, panBars: 1, deleteSelectedDrawing: true },
|
|
2823
|
+
accessibility: { label: "Price chart", description: "", focusable: true },
|
|
2822
2824
|
crosshair: DEFAULT_CROSSHAIR_OPTIONS,
|
|
2823
2825
|
grid: DEFAULT_GRID_OPTIONS,
|
|
2824
2826
|
watermark: DEFAULT_WATERMARK_OPTIONS,
|
|
@@ -2861,6 +2863,14 @@ var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
|
2861
2863
|
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
2862
2864
|
...options.yAxis ?? {}
|
|
2863
2865
|
},
|
|
2866
|
+
keyboard: {
|
|
2867
|
+
...baseOptions.keyboard,
|
|
2868
|
+
...options.keyboard ?? {}
|
|
2869
|
+
},
|
|
2870
|
+
accessibility: {
|
|
2871
|
+
...baseOptions.accessibility,
|
|
2872
|
+
...options.accessibility ?? {}
|
|
2873
|
+
},
|
|
2864
2874
|
crosshair: {
|
|
2865
2875
|
...baseOptions.crosshair,
|
|
2866
2876
|
...options.crosshair ?? {}
|
|
@@ -3034,6 +3044,10 @@ function createChart(element, options = {}) {
|
|
|
3034
3044
|
let drawingSelectHandler = null;
|
|
3035
3045
|
let drawingDoubleClickHandler = null;
|
|
3036
3046
|
let drawingEditTextHandler = null;
|
|
3047
|
+
let selectionChangeHandler = null;
|
|
3048
|
+
let contextMenuHandler = null;
|
|
3049
|
+
let keyboardShortcutHandler = null;
|
|
3050
|
+
let lastSelectionSignature = null;
|
|
3037
3051
|
let magnetMode = "none";
|
|
3038
3052
|
let priceScaleMode = "linear";
|
|
3039
3053
|
let priceScaleInverted = false;
|
|
@@ -3196,6 +3210,39 @@ function createChart(element, options = {}) {
|
|
|
3196
3210
|
canvas.style.setProperty("-webkit-user-select", "none");
|
|
3197
3211
|
canvas.style.setProperty("-webkit-touch-callout", "none");
|
|
3198
3212
|
canvas.setAttribute("draggable", "false");
|
|
3213
|
+
const applyAccessibilityAttributes = () => {
|
|
3214
|
+
const a11y = mergedOptions.accessibility ?? {};
|
|
3215
|
+
const focusable = a11y.focusable !== false;
|
|
3216
|
+
if (focusable) {
|
|
3217
|
+
canvas.tabIndex = 0;
|
|
3218
|
+
} else {
|
|
3219
|
+
canvas.removeAttribute("tabindex");
|
|
3220
|
+
}
|
|
3221
|
+
canvas.setAttribute("role", "application");
|
|
3222
|
+
canvas.setAttribute("aria-label", a11y.label ?? "Price chart");
|
|
3223
|
+
if (a11y.description) {
|
|
3224
|
+
canvas.setAttribute("aria-description", a11y.description);
|
|
3225
|
+
} else {
|
|
3226
|
+
canvas.removeAttribute("aria-description");
|
|
3227
|
+
}
|
|
3228
|
+
if (focusable && (mergedOptions.keyboard?.enabled ?? true)) {
|
|
3229
|
+
canvas.setAttribute(
|
|
3230
|
+
"aria-keyshortcuts",
|
|
3231
|
+
"ArrowLeft ArrowRight ArrowUp ArrowDown Plus Minus Home End Delete Escape"
|
|
3232
|
+
);
|
|
3233
|
+
} else {
|
|
3234
|
+
canvas.removeAttribute("aria-keyshortcuts");
|
|
3235
|
+
}
|
|
3236
|
+
};
|
|
3237
|
+
applyAccessibilityAttributes();
|
|
3238
|
+
let focusFromPointer = false;
|
|
3239
|
+
canvas.addEventListener("focus", () => {
|
|
3240
|
+
canvas.style.outline = focusFromPointer ? "none" : "";
|
|
3241
|
+
focusFromPointer = false;
|
|
3242
|
+
});
|
|
3243
|
+
canvas.addEventListener("blur", () => {
|
|
3244
|
+
canvas.style.outline = "none";
|
|
3245
|
+
});
|
|
3199
3246
|
element.innerHTML = "";
|
|
3200
3247
|
element.appendChild(canvas);
|
|
3201
3248
|
const baseCanvas = document.createElement("canvas");
|
|
@@ -6423,6 +6470,7 @@ function createChart(element, options = {}) {
|
|
|
6423
6470
|
xSpan
|
|
6424
6471
|
};
|
|
6425
6472
|
paintCrosshairOverlay();
|
|
6473
|
+
emitSelectionChangeIfMoved();
|
|
6426
6474
|
};
|
|
6427
6475
|
const paintCrosshairOverlay = () => {
|
|
6428
6476
|
crosshairPriceActionRegion = null;
|
|
@@ -7023,6 +7071,98 @@ function createChart(element, options = {}) {
|
|
|
7023
7071
|
const ratio = (priceScaleTransform(price) - scaledMin) / scaledRange;
|
|
7024
7072
|
return priceScaleInverted ? drawState.chartTop + ratio * drawState.chartHeight : drawState.chartBottom - ratio * drawState.chartHeight;
|
|
7025
7073
|
};
|
|
7074
|
+
const getDrawingBounds = (drawing) => {
|
|
7075
|
+
if (!drawState || drawing.points.length === 0) {
|
|
7076
|
+
return null;
|
|
7077
|
+
}
|
|
7078
|
+
const { chartLeft, chartRight, chartTop, chartBottom } = drawState;
|
|
7079
|
+
let left;
|
|
7080
|
+
let right;
|
|
7081
|
+
let top;
|
|
7082
|
+
let bottom;
|
|
7083
|
+
if (drawing.type === "horizontal-line") {
|
|
7084
|
+
const y = canvasYFromDrawingPrice(drawing.points[0].price);
|
|
7085
|
+
left = chartLeft;
|
|
7086
|
+
right = chartRight;
|
|
7087
|
+
top = y;
|
|
7088
|
+
bottom = y;
|
|
7089
|
+
} else if (drawing.type === "vertical-line") {
|
|
7090
|
+
const x = canvasXFromDrawingPoint(drawing.points[0]);
|
|
7091
|
+
left = x;
|
|
7092
|
+
right = x;
|
|
7093
|
+
top = chartTop;
|
|
7094
|
+
bottom = chartBottom;
|
|
7095
|
+
} else {
|
|
7096
|
+
const xs = drawing.points.map((point) => canvasXFromDrawingPoint(point));
|
|
7097
|
+
const ys = drawing.points.map((point) => canvasYFromDrawingPrice(point.price));
|
|
7098
|
+
left = Math.min(...xs);
|
|
7099
|
+
right = Math.max(...xs);
|
|
7100
|
+
top = Math.min(...ys);
|
|
7101
|
+
bottom = Math.max(...ys);
|
|
7102
|
+
if (drawing.type === "ray") {
|
|
7103
|
+
right = chartRight;
|
|
7104
|
+
}
|
|
7105
|
+
}
|
|
7106
|
+
const clampX = (value) => clamp(value, chartLeft, chartRight);
|
|
7107
|
+
const clampY = (value) => clamp(value, chartTop, chartBottom);
|
|
7108
|
+
left = clampX(left);
|
|
7109
|
+
right = clampX(right);
|
|
7110
|
+
top = clampY(top);
|
|
7111
|
+
bottom = clampY(bottom);
|
|
7112
|
+
return {
|
|
7113
|
+
left,
|
|
7114
|
+
top,
|
|
7115
|
+
right,
|
|
7116
|
+
bottom,
|
|
7117
|
+
centerX: (left + right) / 2,
|
|
7118
|
+
centerY: (top + bottom) / 2
|
|
7119
|
+
};
|
|
7120
|
+
};
|
|
7121
|
+
const getSelectedDrawingWithBounds = () => {
|
|
7122
|
+
if (!selectedDrawingId) {
|
|
7123
|
+
return null;
|
|
7124
|
+
}
|
|
7125
|
+
const drawing = drawings.find((entry) => entry.id === selectedDrawingId);
|
|
7126
|
+
if (!drawing || !drawing.visible) {
|
|
7127
|
+
return null;
|
|
7128
|
+
}
|
|
7129
|
+
const bounds = getDrawingBounds(drawing);
|
|
7130
|
+
return bounds ? { drawing: serializeDrawing(drawing), bounds } : null;
|
|
7131
|
+
};
|
|
7132
|
+
const emitSelectionChangeIfMoved = () => {
|
|
7133
|
+
if (!selectionChangeHandler) {
|
|
7134
|
+
lastSelectionSignature = null;
|
|
7135
|
+
return;
|
|
7136
|
+
}
|
|
7137
|
+
const selection = getSelectedDrawingWithBounds();
|
|
7138
|
+
if (!selection || !drawState) {
|
|
7139
|
+
if (lastSelectionSignature !== null) {
|
|
7140
|
+
lastSelectionSignature = null;
|
|
7141
|
+
selectionChangeHandler(null);
|
|
7142
|
+
}
|
|
7143
|
+
return;
|
|
7144
|
+
}
|
|
7145
|
+
const dragging = drawingDragState !== null;
|
|
7146
|
+
const { bounds } = selection;
|
|
7147
|
+
const signature = `${selection.drawing.id}:${Math.round(bounds.left)}:${Math.round(bounds.top)}:${Math.round(
|
|
7148
|
+
bounds.right
|
|
7149
|
+
)}:${Math.round(bounds.bottom)}:${dragging ? 1 : 0}`;
|
|
7150
|
+
if (signature === lastSelectionSignature) {
|
|
7151
|
+
return;
|
|
7152
|
+
}
|
|
7153
|
+
lastSelectionSignature = signature;
|
|
7154
|
+
selectionChangeHandler({
|
|
7155
|
+
drawing: selection.drawing,
|
|
7156
|
+
bounds,
|
|
7157
|
+
plot: {
|
|
7158
|
+
left: drawState.chartLeft,
|
|
7159
|
+
top: drawState.chartTop,
|
|
7160
|
+
right: drawState.chartRight,
|
|
7161
|
+
bottom: drawState.chartBottom
|
|
7162
|
+
},
|
|
7163
|
+
dragging
|
|
7164
|
+
});
|
|
7165
|
+
};
|
|
7026
7166
|
const distanceToSegment = (x, y, x1, y1, x2, y2) => {
|
|
7027
7167
|
const dx = x2 - x1;
|
|
7028
7168
|
const dy = y2 - y1;
|
|
@@ -7989,6 +8129,10 @@ function createChart(element, options = {}) {
|
|
|
7989
8129
|
if (event.pointerType === "touch" || event.pointerType === "pen") {
|
|
7990
8130
|
event.preventDefault();
|
|
7991
8131
|
}
|
|
8132
|
+
if (mergedOptions.accessibility?.focusable !== false && document.activeElement !== canvas) {
|
|
8133
|
+
focusFromPointer = true;
|
|
8134
|
+
canvas.focus({ preventScroll: true });
|
|
8135
|
+
}
|
|
7992
8136
|
cancelKineticPan();
|
|
7993
8137
|
panVelocitySamples.length = 0;
|
|
7994
8138
|
magnetModifierActive = event.metaKey || event.ctrlKey;
|
|
@@ -8106,12 +8250,14 @@ function createChart(element, options = {}) {
|
|
|
8106
8250
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
8107
8251
|
if (drawingHit) {
|
|
8108
8252
|
selectedDrawingId = drawingHit.drawing.id;
|
|
8253
|
+
const selectBounds = getDrawingBounds(drawingHit.drawing);
|
|
8109
8254
|
drawingSelectHandler?.({
|
|
8110
8255
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
8111
8256
|
target: drawingHit.target,
|
|
8112
8257
|
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
8113
8258
|
x: point.x,
|
|
8114
|
-
y: point.y
|
|
8259
|
+
y: point.y,
|
|
8260
|
+
...selectBounds ? { bounds: selectBounds } : {}
|
|
8115
8261
|
});
|
|
8116
8262
|
if (!drawingHit.drawing.locked) {
|
|
8117
8263
|
const startCanvasPoint = drawingPointFromCanvas(point.x, point.y, false);
|
|
@@ -8672,7 +8818,152 @@ function createChart(element, options = {}) {
|
|
|
8672
8818
|
};
|
|
8673
8819
|
const onContextMenu = (event) => {
|
|
8674
8820
|
event.preventDefault();
|
|
8821
|
+
if (!contextMenuHandler || !drawState) {
|
|
8822
|
+
return;
|
|
8823
|
+
}
|
|
8824
|
+
const point = getCanvasPoint(event);
|
|
8825
|
+
const hitRegion = getHitRegion(point.x, point.y);
|
|
8826
|
+
if (hitRegion === "outside") {
|
|
8827
|
+
return;
|
|
8828
|
+
}
|
|
8829
|
+
const pane = hitRegion === "plot" ? getPaneAt(point.x, point.y) : null;
|
|
8830
|
+
const drawingHit = hitRegion === "plot" && !pane ? getDrawingHit(point.x, point.y) : null;
|
|
8831
|
+
if (drawingHit) {
|
|
8832
|
+
if (selectedDrawingId !== drawingHit.drawing.id) {
|
|
8833
|
+
selectedDrawingId = drawingHit.drawing.id;
|
|
8834
|
+
scheduleDraw();
|
|
8835
|
+
}
|
|
8836
|
+
}
|
|
8837
|
+
const region = drawingHit ? "drawing" : pane ? "indicator-pane" : hitRegion;
|
|
8838
|
+
const index = indexFromCanvasX(point.x);
|
|
8839
|
+
const barTime = index === null ? null : getTimeForIndex(index);
|
|
8840
|
+
const bar = index === null ? void 0 : data[index];
|
|
8841
|
+
const inMainPane = !pane && (hitRegion === "plot" || hitRegion === "y-axis");
|
|
8842
|
+
contextMenuHandler({
|
|
8843
|
+
region,
|
|
8844
|
+
x: point.x,
|
|
8845
|
+
y: point.y,
|
|
8846
|
+
clientX: event.clientX,
|
|
8847
|
+
clientY: event.clientY,
|
|
8848
|
+
...inMainPane ? { price: roundToPricePrecision(priceFromCanvasY(point.y)) } : {},
|
|
8849
|
+
...index === null ? {} : { index },
|
|
8850
|
+
...barTime ? { time: barTime.toISOString() } : {},
|
|
8851
|
+
...bar ? {
|
|
8852
|
+
point: {
|
|
8853
|
+
t: bar.time.toISOString(),
|
|
8854
|
+
o: bar.o,
|
|
8855
|
+
h: bar.h,
|
|
8856
|
+
l: bar.l,
|
|
8857
|
+
c: bar.c,
|
|
8858
|
+
...bar.v === void 0 ? {} : { v: bar.v }
|
|
8859
|
+
}
|
|
8860
|
+
} : {},
|
|
8861
|
+
...drawingHit ? {
|
|
8862
|
+
drawing: serializeDrawing(drawingHit.drawing),
|
|
8863
|
+
drawingTarget: drawingHit.target,
|
|
8864
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex }
|
|
8865
|
+
} : {},
|
|
8866
|
+
...pane ? { indicator: { id: pane.id, type: pane.type } } : {}
|
|
8867
|
+
});
|
|
8868
|
+
};
|
|
8869
|
+
const onCanvasKeyDown = (event) => {
|
|
8870
|
+
const keyboard = mergedOptions.keyboard ?? {};
|
|
8871
|
+
if (keyboard.enabled === false) {
|
|
8872
|
+
return;
|
|
8873
|
+
}
|
|
8874
|
+
if (event.altKey || event.ctrlKey || event.metaKey) {
|
|
8875
|
+
return;
|
|
8876
|
+
}
|
|
8877
|
+
const panStep = Math.max(1, keyboard.panBars ?? 1) * (event.shiftKey ? 10 : 1);
|
|
8878
|
+
const emit = (action, drawing) => {
|
|
8879
|
+
keyboardShortcutHandler?.({
|
|
8880
|
+
action,
|
|
8881
|
+
key: event.key,
|
|
8882
|
+
shiftKey: event.shiftKey,
|
|
8883
|
+
...drawing ? { drawing } : {}
|
|
8884
|
+
});
|
|
8885
|
+
};
|
|
8886
|
+
switch (event.key) {
|
|
8887
|
+
case "Delete":
|
|
8888
|
+
case "Backspace": {
|
|
8889
|
+
if (keyboard.deleteSelectedDrawing === false || !selectedDrawingId) {
|
|
8890
|
+
return;
|
|
8891
|
+
}
|
|
8892
|
+
const target = drawings.find((entry) => entry.id === selectedDrawingId);
|
|
8893
|
+
if (!target) {
|
|
8894
|
+
return;
|
|
8895
|
+
}
|
|
8896
|
+
const removed = serializeDrawing(target);
|
|
8897
|
+
removeDrawing(selectedDrawingId);
|
|
8898
|
+
selectedDrawingId = null;
|
|
8899
|
+
scheduleDraw();
|
|
8900
|
+
emit("delete-drawing", removed);
|
|
8901
|
+
break;
|
|
8902
|
+
}
|
|
8903
|
+
case "Escape": {
|
|
8904
|
+
if (cancelDrawing()) {
|
|
8905
|
+
emit("cancel");
|
|
8906
|
+
break;
|
|
8907
|
+
}
|
|
8908
|
+
if (activeDrawingTool) {
|
|
8909
|
+
setActiveDrawingTool(null);
|
|
8910
|
+
emit("cancel");
|
|
8911
|
+
break;
|
|
8912
|
+
}
|
|
8913
|
+
if (selectedDrawingId) {
|
|
8914
|
+
setSelectedDrawing(null);
|
|
8915
|
+
emit("cancel");
|
|
8916
|
+
break;
|
|
8917
|
+
}
|
|
8918
|
+
return;
|
|
8919
|
+
}
|
|
8920
|
+
case "ArrowLeft":
|
|
8921
|
+
panX(-panStep);
|
|
8922
|
+
emit("pan-left");
|
|
8923
|
+
break;
|
|
8924
|
+
case "ArrowRight":
|
|
8925
|
+
panX(panStep);
|
|
8926
|
+
emit("pan-right");
|
|
8927
|
+
break;
|
|
8928
|
+
case "ArrowUp":
|
|
8929
|
+
case "ArrowDown": {
|
|
8930
|
+
if (!drawState) {
|
|
8931
|
+
return;
|
|
8932
|
+
}
|
|
8933
|
+
const step = (drawState.yMax - drawState.yMin) / 20 * (event.shiftKey ? 5 : 1);
|
|
8934
|
+
panY(event.key === "ArrowUp" ? step : -step);
|
|
8935
|
+
emit(event.key === "ArrowUp" ? "pan-up" : "pan-down");
|
|
8936
|
+
break;
|
|
8937
|
+
}
|
|
8938
|
+
case "+":
|
|
8939
|
+
case "=":
|
|
8940
|
+
zoomInX();
|
|
8941
|
+
emit("zoom-in");
|
|
8942
|
+
break;
|
|
8943
|
+
case "-":
|
|
8944
|
+
case "_":
|
|
8945
|
+
zoomOutX();
|
|
8946
|
+
emit("zoom-out");
|
|
8947
|
+
break;
|
|
8948
|
+
case "Home":
|
|
8949
|
+
fitContent();
|
|
8950
|
+
emit("reset-viewport");
|
|
8951
|
+
break;
|
|
8952
|
+
case "End":
|
|
8953
|
+
setFollowingLatest(true);
|
|
8954
|
+
emit("scroll-to-realtime");
|
|
8955
|
+
break;
|
|
8956
|
+
case "r":
|
|
8957
|
+
case "R":
|
|
8958
|
+
resetViewport();
|
|
8959
|
+
emit("reset-viewport");
|
|
8960
|
+
break;
|
|
8961
|
+
default:
|
|
8962
|
+
return;
|
|
8963
|
+
}
|
|
8964
|
+
event.preventDefault();
|
|
8675
8965
|
};
|
|
8966
|
+
canvas.addEventListener("keydown", onCanvasKeyDown);
|
|
8676
8967
|
canvas.addEventListener("pointerdown", onPointerDown);
|
|
8677
8968
|
canvas.addEventListener("pointermove", onPointerMove);
|
|
8678
8969
|
canvas.addEventListener("pointerup", endPointerDrag);
|
|
@@ -8719,6 +9010,7 @@ function createChart(element, options = {}) {
|
|
|
8719
9010
|
resetRightMarginCache();
|
|
8720
9011
|
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
8721
9012
|
doubleClickAction = mergedOptions.doubleClickAction;
|
|
9013
|
+
applyAccessibilityAttributes();
|
|
8722
9014
|
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
8723
9015
|
if (!isTickerSmoothingEnabled) {
|
|
8724
9016
|
smoothedTickerPrice = null;
|
|
@@ -9102,6 +9394,23 @@ function createChart(element, options = {}) {
|
|
|
9102
9394
|
const onDrawingHover = (handler) => {
|
|
9103
9395
|
drawingHoverHandler = handler;
|
|
9104
9396
|
};
|
|
9397
|
+
const onSelectionChange = (handler) => {
|
|
9398
|
+
selectionChangeHandler = handler;
|
|
9399
|
+
lastSelectionSignature = null;
|
|
9400
|
+
if (handler) {
|
|
9401
|
+
emitSelectionChangeIfMoved();
|
|
9402
|
+
}
|
|
9403
|
+
};
|
|
9404
|
+
const getSelectedDrawing = () => getSelectedDrawingWithBounds();
|
|
9405
|
+
const onContextMenuHandler = (handler) => {
|
|
9406
|
+
contextMenuHandler = handler;
|
|
9407
|
+
};
|
|
9408
|
+
const onKeyboardShortcut = (handler) => {
|
|
9409
|
+
keyboardShortcutHandler = handler;
|
|
9410
|
+
};
|
|
9411
|
+
const focus = () => {
|
|
9412
|
+
canvas.focus({ preventScroll: true });
|
|
9413
|
+
};
|
|
9105
9414
|
const saveState = () => {
|
|
9106
9415
|
const drawingDefaults = {};
|
|
9107
9416
|
for (const [tool, defaults] of drawingToolDefaults) {
|
|
@@ -9166,6 +9475,7 @@ function createChart(element, options = {}) {
|
|
|
9166
9475
|
drawRafId = null;
|
|
9167
9476
|
pendingDrawUpdateAutoScale = false;
|
|
9168
9477
|
}
|
|
9478
|
+
canvas.removeEventListener("keydown", onCanvasKeyDown);
|
|
9169
9479
|
canvas.removeEventListener("pointerdown", onPointerDown);
|
|
9170
9480
|
canvas.removeEventListener("pointermove", onPointerMove);
|
|
9171
9481
|
canvas.removeEventListener("pointerup", endPointerDrag);
|
|
@@ -9229,6 +9539,11 @@ function createChart(element, options = {}) {
|
|
|
9229
9539
|
onDrawingSelect,
|
|
9230
9540
|
onDrawingDoubleClick,
|
|
9231
9541
|
onDrawingEditText,
|
|
9542
|
+
onSelectionChange,
|
|
9543
|
+
getSelectedDrawing,
|
|
9544
|
+
onContextMenu: onContextMenuHandler,
|
|
9545
|
+
onKeyboardShortcut,
|
|
9546
|
+
focus,
|
|
9232
9547
|
setMagnetMode,
|
|
9233
9548
|
getMagnetMode,
|
|
9234
9549
|
setPriceScale,
|