acttrader-charts 1.0.11 → 1.0.13
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/README.md +8 -2
- package/dist/{MACD-DoO45b_C.d.cts → MACD-CEmdbwGz.d.cts} +19 -1
- package/dist/{MACD-DoO45b_C.d.ts → MACD-CEmdbwGz.d.ts} +19 -1
- package/dist/index.cjs +210 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +210 -87
- package/dist/index.js.map +1 -1
- package/dist/indicators/index.d.cts +2 -2
- package/dist/indicators/index.d.ts +2 -2
- package/dist/webview/chart.html +7 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -429,6 +429,9 @@ var DEFAULT_TOP_BAR_CONFIG = {
|
|
|
429
429
|
dropBtnFontFamily: INTER_FONT,
|
|
430
430
|
drawBtnSize: "26px",
|
|
431
431
|
drawBtnIconFontSize: "14px",
|
|
432
|
+
iconBtnSize: "26px",
|
|
433
|
+
mobileIconBtnSize: "28px",
|
|
434
|
+
mobileDrawBtnIconSize: "16px",
|
|
432
435
|
flyoutRowFontSize: "12px",
|
|
433
436
|
flyoutRowFontFamily: INTER_FONT,
|
|
434
437
|
flyoutCategoryFontSize: "10px",
|
|
@@ -466,6 +469,12 @@ var DEFAULT_INDICATOR_OVERLAY_CONFIG = {
|
|
|
466
469
|
dropdownRowFontFamily: INTER_FONT,
|
|
467
470
|
dropdownIconFontSize: "10px"
|
|
468
471
|
};
|
|
472
|
+
var DEFAULT_TRADE_BUTTON_CONFIG = {
|
|
473
|
+
size: 22,
|
|
474
|
+
mobileSize: 24,
|
|
475
|
+
iconSize: 14,
|
|
476
|
+
mobileIconSize: 16
|
|
477
|
+
};
|
|
469
478
|
var DEFAULT_UI_CONFIG = {
|
|
470
479
|
drawingToolbar: DEFAULT_DRAWING_TOOLBAR_CONFIG,
|
|
471
480
|
topBar: DEFAULT_TOP_BAR_CONFIG,
|
|
@@ -473,7 +482,8 @@ var DEFAULT_UI_CONFIG = {
|
|
|
473
482
|
priceAxis: DEFAULT_PRICE_AXIS_CONFIG,
|
|
474
483
|
timeAxis: DEFAULT_TIME_AXIS_CONFIG,
|
|
475
484
|
crosshair: DEFAULT_CROSSHAIR_CONFIG,
|
|
476
|
-
indicatorOverlay: DEFAULT_INDICATOR_OVERLAY_CONFIG
|
|
485
|
+
indicatorOverlay: DEFAULT_INDICATOR_OVERLAY_CONFIG,
|
|
486
|
+
tradeButton: DEFAULT_TRADE_BUTTON_CONFIG
|
|
477
487
|
};
|
|
478
488
|
function resolveUiConfig(override) {
|
|
479
489
|
if (!override) return DEFAULT_UI_CONFIG;
|
|
@@ -484,7 +494,8 @@ function resolveUiConfig(override) {
|
|
|
484
494
|
priceAxis: { ...DEFAULT_PRICE_AXIS_CONFIG, ...override.priceAxis },
|
|
485
495
|
timeAxis: { ...DEFAULT_TIME_AXIS_CONFIG, ...override.timeAxis },
|
|
486
496
|
crosshair: { ...DEFAULT_CROSSHAIR_CONFIG, ...override.crosshair },
|
|
487
|
-
indicatorOverlay: { ...DEFAULT_INDICATOR_OVERLAY_CONFIG, ...override.indicatorOverlay }
|
|
497
|
+
indicatorOverlay: { ...DEFAULT_INDICATOR_OVERLAY_CONFIG, ...override.indicatorOverlay },
|
|
498
|
+
tradeButton: { ...DEFAULT_TRADE_BUTTON_CONFIG, ...override.tradeButton }
|
|
488
499
|
};
|
|
489
500
|
}
|
|
490
501
|
|
|
@@ -2101,7 +2112,7 @@ function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered
|
|
|
2101
2112
|
ctx.restore();
|
|
2102
2113
|
if (draggable) {
|
|
2103
2114
|
drawGripHandle(ctx, gripX, boxY, boxH, colors, hovered);
|
|
2104
|
-
const BTN_ZONE_W = EDIT_R * 2 + EDIT_GAP + CLOSE_R * 2 + BOX_PAD_X / 2;
|
|
2115
|
+
const BTN_ZONE_W = hideConfirmCancel ? 0 : EDIT_R * 2 + EDIT_GAP + CLOSE_R * 2 + BOX_PAD_X / 2;
|
|
2105
2116
|
dragAreas.push({
|
|
2106
2117
|
label: level.label,
|
|
2107
2118
|
type: level.type,
|
|
@@ -2111,7 +2122,8 @@ function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered
|
|
|
2111
2122
|
y: boxY,
|
|
2112
2123
|
w: GRIP_W + 2 + boxW - BTN_ZONE_W,
|
|
2113
2124
|
h: boxH,
|
|
2114
|
-
isBracket: false
|
|
2125
|
+
isBracket: false,
|
|
2126
|
+
isBox: true
|
|
2115
2127
|
});
|
|
2116
2128
|
dragAreas.push({
|
|
2117
2129
|
label: level.label,
|
|
@@ -2124,6 +2136,19 @@ function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered
|
|
|
2124
2136
|
h: 8,
|
|
2125
2137
|
isBracket: false
|
|
2126
2138
|
});
|
|
2139
|
+
} else if (hideConfirmCancel && boxW > 0) {
|
|
2140
|
+
dragAreas.push({
|
|
2141
|
+
label: level.label,
|
|
2142
|
+
type: level.type,
|
|
2143
|
+
data: level.data,
|
|
2144
|
+
price: level.price,
|
|
2145
|
+
x: boxX,
|
|
2146
|
+
y: boxY,
|
|
2147
|
+
w: boxW,
|
|
2148
|
+
h: boxH,
|
|
2149
|
+
isBracket: false,
|
|
2150
|
+
isBox: true
|
|
2151
|
+
});
|
|
2127
2152
|
}
|
|
2128
2153
|
hoverAreas.push({
|
|
2129
2154
|
label: level.label,
|
|
@@ -3224,6 +3249,9 @@ var TopBar = class {
|
|
|
3224
3249
|
this.fullscreenBtn.innerHTML = active ? ICON_FULLSCREEN_EXIT : ICON_FULLSCREEN_ENTER;
|
|
3225
3250
|
this.fullscreenBtn.title = active ? this.labels.exitFullscreenTitle : this.labels.toggleFullscreenTitle;
|
|
3226
3251
|
this.applyIconBtnStyles(this.fullscreenBtn, this.theme, active);
|
|
3252
|
+
if (this.isMobileLayout) {
|
|
3253
|
+
this.resizeSvg(this.fullscreenBtn, this.getSvgSize(this.fullscreenBtn) + 2);
|
|
3254
|
+
}
|
|
3227
3255
|
}
|
|
3228
3256
|
setDrawingsBtnActive(active) {
|
|
3229
3257
|
if (!this.drawingBtn) return;
|
|
@@ -3276,6 +3304,21 @@ var TopBar = class {
|
|
|
3276
3304
|
}
|
|
3277
3305
|
this.durationSep.style.display = btnDisplay;
|
|
3278
3306
|
this.durationDropBtn.style.display = isMobile ? "" : "none";
|
|
3307
|
+
const containerSize = isMobile ? this.cfg.mobileIconBtnSize : this.cfg.iconBtnSize;
|
|
3308
|
+
for (const btn of [this.fullscreenBtn, this.settingsBtn, this.drawingBtn]) {
|
|
3309
|
+
if (!btn) continue;
|
|
3310
|
+
btn.style.width = containerSize;
|
|
3311
|
+
btn.style.height = containerSize;
|
|
3312
|
+
}
|
|
3313
|
+
const delta = isMobile ? 2 : -2;
|
|
3314
|
+
this.resizeSvg(this.fullscreenBtn, this.getSvgSize(this.fullscreenBtn) + delta);
|
|
3315
|
+
if (this.settingsBtn) {
|
|
3316
|
+
this.resizeSvg(this.settingsBtn, this.getSvgSize(this.settingsBtn) + delta);
|
|
3317
|
+
}
|
|
3318
|
+
if (this.drawingBtn) {
|
|
3319
|
+
const drawIconSize = isMobile ? parseInt(this.cfg.mobileDrawBtnIconSize, 10) : parseInt(this.cfg.drawBtnIconFontSize, 10);
|
|
3320
|
+
this.resizeSvg(this.drawingBtn, drawIconSize);
|
|
3321
|
+
}
|
|
3279
3322
|
}
|
|
3280
3323
|
setIndicatorOptions(options) {
|
|
3281
3324
|
this.indicatorOptions = options;
|
|
@@ -3682,13 +3725,14 @@ var TopBar = class {
|
|
|
3682
3725
|
}
|
|
3683
3726
|
applyIconBtnStyles(btn, theme, active) {
|
|
3684
3727
|
btn.dataset.active = String(active);
|
|
3728
|
+
const size = this.isMobileLayout ? this.cfg.mobileIconBtnSize : this.cfg.iconBtnSize;
|
|
3685
3729
|
Object.assign(btn.style, {
|
|
3686
3730
|
background: active ? theme.ui.accentBg : "transparent",
|
|
3687
3731
|
color: active ? theme.ui.accentText : theme.topBar.btnColor,
|
|
3688
3732
|
border: `1px solid ${active ? theme.ui.accent : theme.axisBorder}`,
|
|
3689
3733
|
borderRadius: "5px",
|
|
3690
|
-
width:
|
|
3691
|
-
height:
|
|
3734
|
+
width: size,
|
|
3735
|
+
height: size,
|
|
3692
3736
|
cursor: "pointer",
|
|
3693
3737
|
outline: "none",
|
|
3694
3738
|
display: "flex",
|
|
@@ -3699,6 +3743,20 @@ var TopBar = class {
|
|
|
3699
3743
|
transition: "border-color 0.12s, background 0.12s"
|
|
3700
3744
|
});
|
|
3701
3745
|
}
|
|
3746
|
+
resizeSvg(btn, size) {
|
|
3747
|
+
if (!btn) return;
|
|
3748
|
+
const svg = btn.querySelector("svg");
|
|
3749
|
+
if (svg) {
|
|
3750
|
+
svg.setAttribute("width", String(size));
|
|
3751
|
+
svg.setAttribute("height", String(size));
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
getSvgSize(btn) {
|
|
3755
|
+
if (!btn) return 0;
|
|
3756
|
+
const svg = btn.querySelector("svg");
|
|
3757
|
+
if (!svg) return 0;
|
|
3758
|
+
return parseInt(svg.getAttribute("width") ?? "0", 10);
|
|
3759
|
+
}
|
|
3702
3760
|
};
|
|
3703
3761
|
|
|
3704
3762
|
// src/ui/BottomBar.ts
|
|
@@ -12215,9 +12273,11 @@ var ChartSettingsDialog = class {
|
|
|
12215
12273
|
|
|
12216
12274
|
// src/ui/TradeButton.ts
|
|
12217
12275
|
var TradeButton = class {
|
|
12218
|
-
constructor(theme, priceAxisWidth, onClick, labels = DEFAULT_LABELS.trade) {
|
|
12276
|
+
constructor(theme, priceAxisWidth, onClick, labels = DEFAULT_LABELS.trade, cfg = DEFAULT_TRADE_BUTTON_CONFIG) {
|
|
12219
12277
|
this._visible = false;
|
|
12278
|
+
this._isMobile = false;
|
|
12220
12279
|
this.theme = theme;
|
|
12280
|
+
this.cfg = cfg;
|
|
12221
12281
|
this.el = document.createElement("button");
|
|
12222
12282
|
this.el.innerHTML = ICON_PLUS_CIRCLE;
|
|
12223
12283
|
this.el.title = labels.placeOrderTitle;
|
|
@@ -12225,8 +12285,8 @@ var TradeButton = class {
|
|
|
12225
12285
|
position: "absolute",
|
|
12226
12286
|
right: `${priceAxisWidth + 26}px`,
|
|
12227
12287
|
top: "0",
|
|
12228
|
-
width:
|
|
12229
|
-
height:
|
|
12288
|
+
width: `${cfg.size}px`,
|
|
12289
|
+
height: `${cfg.size}px`,
|
|
12230
12290
|
borderRadius: "50%",
|
|
12231
12291
|
border: `1px solid ${theme.axisBorder}`,
|
|
12232
12292
|
background: theme.tooltip.background,
|
|
@@ -12245,6 +12305,7 @@ var TradeButton = class {
|
|
|
12245
12305
|
pointerEvents: "auto",
|
|
12246
12306
|
userSelect: "none"
|
|
12247
12307
|
});
|
|
12308
|
+
this.applyIconSize(cfg.iconSize);
|
|
12248
12309
|
this.el.addEventListener("click", (e) => {
|
|
12249
12310
|
e.stopPropagation();
|
|
12250
12311
|
onClick();
|
|
@@ -12292,6 +12353,27 @@ var TradeButton = class {
|
|
|
12292
12353
|
right: `${priceAxisWidth + 26}px`
|
|
12293
12354
|
});
|
|
12294
12355
|
}
|
|
12356
|
+
/**
|
|
12357
|
+
* Toggle mobile sizing. When `isMobile` is true, the button diameter and
|
|
12358
|
+
* inner SVG icon are swapped for the configured mobile values; when false,
|
|
12359
|
+
* they revert to desktop values.
|
|
12360
|
+
*/
|
|
12361
|
+
setMobileMode(isMobile) {
|
|
12362
|
+
if (this._isMobile === isMobile) return;
|
|
12363
|
+
this._isMobile = isMobile;
|
|
12364
|
+
const size = isMobile ? this.cfg.mobileSize : this.cfg.size;
|
|
12365
|
+
const iconSize = isMobile ? this.cfg.mobileIconSize : this.cfg.iconSize;
|
|
12366
|
+
this.el.style.width = `${size}px`;
|
|
12367
|
+
this.el.style.height = `${size}px`;
|
|
12368
|
+
this.applyIconSize(iconSize);
|
|
12369
|
+
}
|
|
12370
|
+
applyIconSize(size) {
|
|
12371
|
+
const svg = this.el.querySelector("svg");
|
|
12372
|
+
if (svg) {
|
|
12373
|
+
svg.setAttribute("width", String(size));
|
|
12374
|
+
svg.setAttribute("height", String(size));
|
|
12375
|
+
}
|
|
12376
|
+
}
|
|
12295
12377
|
};
|
|
12296
12378
|
|
|
12297
12379
|
// src/ui/TradePopover.ts
|
|
@@ -13964,7 +14046,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
13964
14046
|
Math.min(Math.ceil(this.viewport.endIndex), Math.round(rawBarIndex))
|
|
13965
14047
|
);
|
|
13966
14048
|
const bar = this.dataStore.all[clamped] ?? null;
|
|
13967
|
-
this.crosshair = isInChartArea && !this.tradePopover?.isVisible ? { x, y, barIndex: clamped, price, bar } : null;
|
|
14049
|
+
this.crosshair = isInChartArea && !this.tradePopover?.isVisible && this.selectedTradeLabel === null ? { x, y, barIndex: clamped, price, bar } : null;
|
|
13968
14050
|
if (this.crosshair) this.emitter.emit("crosshair", this.crosshair);
|
|
13969
14051
|
const hoveringDotLevel = this.positionRenderStyle === "dot" && this.hoveredTradeLabel !== null;
|
|
13970
14052
|
if (this.tradeButton) {
|
|
@@ -14303,8 +14385,9 @@ var _ChartEngine = class _ChartEngine {
|
|
|
14303
14385
|
e.preventDefault();
|
|
14304
14386
|
const level = this.levels.find((l) => l.label === dragHit.label);
|
|
14305
14387
|
if (level) {
|
|
14306
|
-
const
|
|
14307
|
-
|
|
14388
|
+
const isAlreadySelected = this.selectedTradeLabel === level.label;
|
|
14389
|
+
const isMobileDraggable = dragHit.isBracket || level.type === "pending" && level.orderType !== "market" && (isAlreadySelected || !dragHit.isBox);
|
|
14390
|
+
if (this.hideLevelConfirmCancel && !isMobileDraggable) {
|
|
14308
14391
|
const hasPending = this.pendingLevelDrags.has(level.label);
|
|
14309
14392
|
if (this.selectedTradeLabel === level.label && !hasPending) {
|
|
14310
14393
|
this.selectedTradeLabel = null;
|
|
@@ -14482,7 +14565,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
14482
14565
|
Math.min(Math.ceil(this.viewport.endIndex), Math.round(rawBarIndex))
|
|
14483
14566
|
);
|
|
14484
14567
|
const bar = this.dataStore.all[clamped] ?? null;
|
|
14485
|
-
this.crosshair = { x, y, barIndex: clamped, price, bar };
|
|
14568
|
+
this.crosshair = this.selectedTradeLabel === null ? { x, y, barIndex: clamped, price, bar } : null;
|
|
14486
14569
|
if (this.tradeButton) {
|
|
14487
14570
|
this.tradeButton.setY(y);
|
|
14488
14571
|
if (this._isTradingActive) {
|
|
@@ -15092,30 +15175,32 @@ var _ChartEngine = class _ChartEngine {
|
|
|
15092
15175
|
padding: "0 2px"
|
|
15093
15176
|
});
|
|
15094
15177
|
this.canvasWrap.appendChild(this.textInputEl);
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15178
|
+
if (showUI) {
|
|
15179
|
+
this.loadingOverlayEl = document.createElement("div");
|
|
15180
|
+
Object.assign(this.loadingOverlayEl.style, {
|
|
15181
|
+
display: "none",
|
|
15182
|
+
position: "absolute",
|
|
15183
|
+
top: "0",
|
|
15184
|
+
left: "0",
|
|
15185
|
+
width: "100%",
|
|
15186
|
+
height: "100%",
|
|
15187
|
+
alignItems: "center",
|
|
15188
|
+
justifyContent: "center",
|
|
15189
|
+
pointerEvents: "none",
|
|
15190
|
+
zIndex: "20"
|
|
15191
|
+
});
|
|
15192
|
+
const loadingLabel = document.createElement("span");
|
|
15193
|
+
loadingLabel.textContent = this.labels.chart.loading;
|
|
15194
|
+
Object.assign(loadingLabel.style, {
|
|
15195
|
+
color: "rgba(200,200,200,0.9)",
|
|
15196
|
+
fontSize: "13px",
|
|
15197
|
+
background: "rgba(0,0,0,0.45)",
|
|
15198
|
+
padding: "4px 12px",
|
|
15199
|
+
borderRadius: "4px"
|
|
15200
|
+
});
|
|
15201
|
+
this.loadingOverlayEl.appendChild(loadingLabel);
|
|
15202
|
+
this.canvasWrap.appendChild(this.loadingOverlayEl);
|
|
15203
|
+
}
|
|
15119
15204
|
if (showUI) {
|
|
15120
15205
|
this.siEl = document.createElement("div");
|
|
15121
15206
|
Object.assign(this.siEl.style, {
|
|
@@ -15247,7 +15332,8 @@ var _ChartEngine = class _ChartEngine {
|
|
|
15247
15332
|
);
|
|
15248
15333
|
}
|
|
15249
15334
|
},
|
|
15250
|
-
this.labels.trade
|
|
15335
|
+
this.labels.trade,
|
|
15336
|
+
this.uiConfig.tradeButton
|
|
15251
15337
|
);
|
|
15252
15338
|
this.canvasWrap.appendChild(this.tradeButton.el);
|
|
15253
15339
|
this.tradeButton.el.addEventListener("mouseenter", () => {
|
|
@@ -15847,6 +15933,30 @@ var _ChartEngine = class _ChartEngine {
|
|
|
15847
15933
|
this.emitStateChange();
|
|
15848
15934
|
return this;
|
|
15849
15935
|
}
|
|
15936
|
+
/** Programmatically change the active timeframe and reload data. */
|
|
15937
|
+
setTimeframe(tf) {
|
|
15938
|
+
this.timeframe = tf;
|
|
15939
|
+
this.topBar?.setTimeframe(tf);
|
|
15940
|
+
this.emitter.emit("timeframeChange", { timeframe: tf });
|
|
15941
|
+
this.emitStateChange();
|
|
15942
|
+
this.updateCountdownState();
|
|
15943
|
+
this.triggerLoad("timeframe");
|
|
15944
|
+
return this;
|
|
15945
|
+
}
|
|
15946
|
+
/** Update per-theme deep-partial color overrides and rebuild the active theme. */
|
|
15947
|
+
setThemeOverrides(overrides) {
|
|
15948
|
+
this.themeOverrides = overrides;
|
|
15949
|
+
this.theme = this.buildTheme(this.themeName);
|
|
15950
|
+
this.topBar?.setTheme(this.theme);
|
|
15951
|
+
this.bottomBar?.setTheme(this.theme);
|
|
15952
|
+
this.leftBar?.setTheme(this.theme);
|
|
15953
|
+
this.tradeButton?.setTheme(this.theme, this.priceAxisWidth);
|
|
15954
|
+
this.tradePopover?.setTheme(this.theme);
|
|
15955
|
+
this.indicatorSettingsDialog?.setTheme(this.theme);
|
|
15956
|
+
this.chartSettingsDialog?.setTheme(this.theme);
|
|
15957
|
+
this.scheduleRender();
|
|
15958
|
+
return this;
|
|
15959
|
+
}
|
|
15850
15960
|
setSeries(series) {
|
|
15851
15961
|
this.series = series;
|
|
15852
15962
|
this.topBar?.setSeries(series);
|
|
@@ -16375,8 +16485,10 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16375
16485
|
addLevelBracket(label, type) {
|
|
16376
16486
|
const level = this.levels.find((l) => l.label === label);
|
|
16377
16487
|
if (!level) return this;
|
|
16378
|
-
const
|
|
16379
|
-
|
|
16488
|
+
const dragField = type === "sl" ? "stopLoss" : "takeProfit";
|
|
16489
|
+
const alreadyHasInLevel = type === "sl" ? level.stopLossPrice !== void 0 : level.takeProfitPrice !== void 0;
|
|
16490
|
+
const alreadyHasPending = this.pendingLevelDrags.get(label)?.some((c) => c.field === dragField && !c.isRemoval) ?? false;
|
|
16491
|
+
if (alreadyHasInLevel || alreadyHasPending) return this;
|
|
16380
16492
|
const { priceH } = this.getChartLayout();
|
|
16381
16493
|
const priceRange = this._displayedPriceRange ?? this.getScaledPriceRange(this.viewport);
|
|
16382
16494
|
const entryY = this.scaleManager.yToPixel(level.price, priceRange, priceH);
|
|
@@ -16385,6 +16497,10 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16385
16497
|
const bracketY = entryY + (isBelowEntry ? 30 : -30);
|
|
16386
16498
|
const defaultPrice = this.scaleManager.pixelToPrice(bracketY, priceRange, priceH);
|
|
16387
16499
|
this.updateLevelBracket(label, type, defaultPrice);
|
|
16500
|
+
const existingDrags = this.pendingLevelDrags.get(label) ?? [];
|
|
16501
|
+
const filteredDrags = existingDrags.filter((c) => c.field !== dragField);
|
|
16502
|
+
filteredDrags.push({ field: dragField, newPrice: defaultPrice, oldPrice: defaultPrice, isNew: true });
|
|
16503
|
+
this.pendingLevelDrags.set(label, filteredDrags);
|
|
16388
16504
|
this.emitter.emit("tradeLevelBracketActivated", {
|
|
16389
16505
|
label,
|
|
16390
16506
|
bracketType: type,
|
|
@@ -16447,7 +16563,20 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16447
16563
|
* No-op if the target doesn't exist or doesn't have the bracket type.
|
|
16448
16564
|
*/
|
|
16449
16565
|
removeBracket(type, label) {
|
|
16450
|
-
if (label)
|
|
16566
|
+
if (label) {
|
|
16567
|
+
const field = type === "sl" ? "stopLoss" : "takeProfit";
|
|
16568
|
+
const level = this.levels.find((l) => l.label === label);
|
|
16569
|
+
if (!level) return this;
|
|
16570
|
+
const existingChange = this.pendingLevelDrags.get(label)?.find((c) => c.field === field);
|
|
16571
|
+
const effectivePrice = existingChange && !existingChange.isRemoval ? existingChange.newPrice : type === "sl" ? level.stopLossPrice : level.takeProfitPrice;
|
|
16572
|
+
if (effectivePrice === void 0) return this;
|
|
16573
|
+
const existingDrags = this.pendingLevelDrags.get(label) ?? [];
|
|
16574
|
+
const filteredDrags = existingDrags.filter((c) => c.field !== field);
|
|
16575
|
+
filteredDrags.push({ field, newPrice: effectivePrice, oldPrice: effectivePrice, isRemoval: true });
|
|
16576
|
+
this.pendingLevelDrags.set(label, filteredDrags);
|
|
16577
|
+
this.renderTradeLayer();
|
|
16578
|
+
return this;
|
|
16579
|
+
}
|
|
16451
16580
|
if (type === "sl") {
|
|
16452
16581
|
this.draftBracketPnl = { ...this.draftBracketPnl, sl: void 0 };
|
|
16453
16582
|
} else {
|
|
@@ -16469,12 +16598,13 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16469
16598
|
return this;
|
|
16470
16599
|
}
|
|
16471
16600
|
/**
|
|
16472
|
-
* Set or clear the estimated PNL text shown on
|
|
16473
|
-
*
|
|
16601
|
+
* Set or clear the estimated PNL text shown on the SL or TP bracket line.
|
|
16602
|
+
* Applies to the currently active bracket host — a draft order while drafting,
|
|
16603
|
+
* or the selected/hovered level while editing an existing pending order or position.
|
|
16604
|
+
* Pass `null` to clear the text.
|
|
16474
16605
|
* Use this to display the consumer-calculated estimated profit/loss next to the bracket.
|
|
16475
16606
|
*/
|
|
16476
16607
|
setDraftBracketPnl(type, pnlText) {
|
|
16477
|
-
if (!this.draftOrderLabel) return this;
|
|
16478
16608
|
if (type === "sl") {
|
|
16479
16609
|
this.draftBracketPnl = { ...this.draftBracketPnl, sl: pnlText ?? void 0 };
|
|
16480
16610
|
} else {
|
|
@@ -16552,6 +16682,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16552
16682
|
*/
|
|
16553
16683
|
selectLevel(label) {
|
|
16554
16684
|
this.selectedTradeLabel = label;
|
|
16685
|
+
if (label !== null) this.crosshair = null;
|
|
16555
16686
|
this.renderTradeLayer();
|
|
16556
16687
|
return this;
|
|
16557
16688
|
}
|
|
@@ -16859,25 +16990,31 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16859
16990
|
);
|
|
16860
16991
|
const processedLevels = this.levels.filter((l) => !(l.type === "pending" && l.ToClose != null)).map((l) => {
|
|
16861
16992
|
const draftChanges = this.pendingLevelDrags.get(l.label) ?? [];
|
|
16862
|
-
const
|
|
16863
|
-
const
|
|
16993
|
+
const slChange = draftChanges.find((c) => c.field === "stopLoss");
|
|
16994
|
+
const tpChange = draftChanges.find((c) => c.field === "takeProfit");
|
|
16995
|
+
const slDraft = slChange && !slChange.isRemoval ? slChange.newPrice : void 0;
|
|
16996
|
+
const tpDraft = tpChange && !tpChange.isRemoval ? tpChange.newPrice : void 0;
|
|
16997
|
+
const slIsRemoval = slChange?.isRemoval ?? false;
|
|
16998
|
+
const tpIsRemoval = tpChange?.isRemoval ?? false;
|
|
16864
16999
|
const mainDraft = draftChanges.find((c) => c.field === "main")?.newPrice;
|
|
16865
17000
|
const linked = bracketOrders.filter((b) => b.ToClose === l.label);
|
|
16866
|
-
if (linked.length === 0 && slDraft === void 0 && tpDraft === void 0 && mainDraft === void 0)
|
|
17001
|
+
if (linked.length === 0 && slDraft === void 0 && tpDraft === void 0 && mainDraft === void 0 && !slIsRemoval && !tpIsRemoval)
|
|
16867
17002
|
return l;
|
|
16868
17003
|
const clone = { ...l };
|
|
16869
17004
|
if (mainDraft !== void 0) clone.price = mainDraft;
|
|
16870
17005
|
if (slDraft !== void 0) clone.stopLossPrice = slDraft;
|
|
17006
|
+
else if (slIsRemoval) clone.stopLossPrice = void 0;
|
|
16871
17007
|
if (tpDraft !== void 0) clone.takeProfitPrice = tpDraft;
|
|
17008
|
+
else if (tpIsRemoval) clone.takeProfitPrice = void 0;
|
|
16872
17009
|
if (linked.length > 0) {
|
|
16873
17010
|
const parentSide = l.side ?? "buy";
|
|
16874
17011
|
for (const b of linked) {
|
|
16875
17012
|
const isSL = parentSide === "buy" ? b.price < l.price : b.price > l.price;
|
|
16876
17013
|
if (isSL) {
|
|
16877
|
-
clone.stopLossPrice = slDraft ?? clone.stopLossPrice ?? b.price;
|
|
17014
|
+
clone.stopLossPrice = slIsRemoval ? void 0 : slDraft ?? clone.stopLossPrice ?? b.price;
|
|
16878
17015
|
clone._slOrderLabel = b.label;
|
|
16879
17016
|
} else {
|
|
16880
|
-
clone.takeProfitPrice = tpDraft ?? clone.takeProfitPrice ?? b.price;
|
|
17017
|
+
clone.takeProfitPrice = tpIsRemoval ? void 0 : tpDraft ?? clone.takeProfitPrice ?? b.price;
|
|
16881
17018
|
clone._tpOrderLabel = b.label;
|
|
16882
17019
|
}
|
|
16883
17020
|
}
|
|
@@ -16939,8 +17076,9 @@ var _ChartEngine = class _ChartEngine {
|
|
|
16939
17076
|
const parentPrice = this._effectiveEntryPrice(result.label, level?.price ?? oldPrice);
|
|
16940
17077
|
const isEntryOrder = level?.entryPriceEditable === true;
|
|
16941
17078
|
const isDraft = level?.data?._isDraft === true;
|
|
17079
|
+
const isMobilePendingOrder = this.hideLevelConfirmCancel && result.type === "pending" && !isDraft;
|
|
16942
17080
|
const all = this.dataStore.all;
|
|
16943
|
-
const marketPrice = isEntryOrder || isDraft ? 0 : all[all.length - 1]?.close ?? 0;
|
|
17081
|
+
const marketPrice = isEntryOrder || isDraft || isMobilePendingOrder ? 0 : all[all.length - 1]?.close ?? 0;
|
|
16944
17082
|
if (!TradeDragHandler.isBracketPriceValid(
|
|
16945
17083
|
result.newPrice,
|
|
16946
17084
|
result.bracketType,
|
|
@@ -17070,16 +17208,14 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17070
17208
|
if (!level) return;
|
|
17071
17209
|
if (label === this.draftOrderLabel) {
|
|
17072
17210
|
const mainEntry = changes.find((c) => c.field === "main");
|
|
17073
|
-
const slEntry = changes.find((c) => c.field === "stopLoss" && c.isNew);
|
|
17074
|
-
const tpEntry = changes.find((c) => c.field === "takeProfit" && c.isNew);
|
|
17075
17211
|
const draft = level;
|
|
17076
17212
|
this._onOrderSubmit?.({
|
|
17077
17213
|
price: mainEntry?.newPrice ?? draft.price,
|
|
17078
17214
|
lots: this._minLots,
|
|
17079
17215
|
side: draft.side,
|
|
17080
17216
|
orderType: draft.orderType,
|
|
17081
|
-
...
|
|
17082
|
-
...
|
|
17217
|
+
...draft.stopLossPrice !== void 0 ? { stopLoss: draft.stopLossPrice } : {},
|
|
17218
|
+
...draft.takeProfitPrice !== void 0 ? { takeProfit: draft.takeProfitPrice } : {}
|
|
17083
17219
|
});
|
|
17084
17220
|
this.emitter.emit("tradeLevelConfirmed", {
|
|
17085
17221
|
label,
|
|
@@ -17649,6 +17785,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17649
17785
|
this._mobileLayout = isMobile;
|
|
17650
17786
|
this.leftBar?.setMobileMode(isMobile);
|
|
17651
17787
|
this.topBar?.setMobileLayout(isMobile);
|
|
17788
|
+
this.tradeButton?.setMobileMode(isMobile);
|
|
17652
17789
|
if (this.siEl) {
|
|
17653
17790
|
this.siEl.style.flexDirection = isMobile ? "column" : "row";
|
|
17654
17791
|
this.siEl.style.alignItems = isMobile ? "flex-start" : "center";
|
|
@@ -17751,24 +17888,20 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17751
17888
|
const isDraftBracket = parentLevel?.data?._isDraft === true;
|
|
17752
17889
|
if (isDraftBracket && parentLevel) {
|
|
17753
17890
|
const bracketKey = closedLevel.bracketType === "stopLoss" ? "sl" : "tp";
|
|
17754
|
-
|
|
17755
|
-
|
|
17756
|
-
const entryY = this.scaleManager.yToPixel(
|
|
17757
|
-
parentLevel.price,
|
|
17758
|
-
priceRange,
|
|
17759
|
-
priceH
|
|
17760
|
-
);
|
|
17761
|
-
const side = parentLevel.side ?? "buy";
|
|
17762
|
-
const isBelowEntry = side === "buy" && bracketKey === "sl" || side === "sell" && bracketKey === "tp";
|
|
17763
|
-
const bracketY = entryY + (isBelowEntry ? 30 : -30);
|
|
17764
|
-
const defaultPrice = this.scaleManager.pixelToPrice(bracketY, priceRange, priceH);
|
|
17765
|
-
this.updateDraftOrderBracket(bracketKey, defaultPrice);
|
|
17766
|
-
this.emitter.emit("tradeLevelDrag", {
|
|
17891
|
+
this.updateDraftOrderBracket(bracketKey, null);
|
|
17892
|
+
this.emitter.emit("tradeLevelEdit", {
|
|
17767
17893
|
label: closedLevel.label,
|
|
17768
|
-
|
|
17769
|
-
data: parentLevel
|
|
17770
|
-
|
|
17771
|
-
|
|
17894
|
+
type: "pending",
|
|
17895
|
+
data: parentLevel.data,
|
|
17896
|
+
isFullscreen: this.isFullscreen,
|
|
17897
|
+
changes: [
|
|
17898
|
+
{
|
|
17899
|
+
field: closedLevel.bracketType === "stopLoss" ? "REMOVE_SL" : "REMOVE_TP",
|
|
17900
|
+
newPrice: 0,
|
|
17901
|
+
data: parentLevel.data,
|
|
17902
|
+
bracketOrderLabel: void 0
|
|
17903
|
+
}
|
|
17904
|
+
]
|
|
17772
17905
|
});
|
|
17773
17906
|
return;
|
|
17774
17907
|
}
|
|
@@ -17817,7 +17950,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17817
17950
|
Math.min(Math.ceil(this.viewport.endIndex), Math.round(rawBarIndex))
|
|
17818
17951
|
);
|
|
17819
17952
|
const bar = this.dataStore.all[clamped] ?? null;
|
|
17820
|
-
this.crosshair = { x, y, barIndex: clamped, price, bar };
|
|
17953
|
+
this.crosshair = this.selectedTradeLabel === null ? { x, y, barIndex: clamped, price, bar } : null;
|
|
17821
17954
|
if (this.tradeButton) {
|
|
17822
17955
|
this.tradeButton.setY(y);
|
|
17823
17956
|
if (this._isTradingActive) {
|
|
@@ -17841,8 +17974,9 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17841
17974
|
this._isBracketNew = false;
|
|
17842
17975
|
const isEntryOrder = level.entryPriceEditable === true;
|
|
17843
17976
|
const isDraft = level.data?._isDraft === true;
|
|
17977
|
+
const isMobilePendingOrder = this.hideLevelConfirmCancel && level.type === "pending" && !isDraft;
|
|
17844
17978
|
const all = this.dataStore.all;
|
|
17845
|
-
const marketPrice = isEntryOrder || isDraft ? 0 : all[all.length - 1]?.close ?? 0;
|
|
17979
|
+
const marketPrice = isEntryOrder || isDraft || isMobilePendingOrder ? 0 : all[all.length - 1]?.close ?? 0;
|
|
17846
17980
|
this.tradeDragHandler.startBracketDrag(
|
|
17847
17981
|
level,
|
|
17848
17982
|
dragHit.bracketType,
|
|
@@ -17900,20 +18034,9 @@ var _ChartEngine = class _ChartEngine {
|
|
|
17900
18034
|
const initialPrice = this.scaleManager.pixelToPrice(btnCenterY, priceRange, priceH);
|
|
17901
18035
|
const isEntryOrder = level.entryPriceEditable === true;
|
|
17902
18036
|
const isDraft = level.data?._isDraft === true;
|
|
18037
|
+
const isMobilePendingOrder = this.hideLevelConfirmCancel && level.type === "pending" && !isDraft;
|
|
17903
18038
|
const all = this.dataStore.all;
|
|
17904
|
-
const marketPrice = isEntryOrder || isDraft ? 0 : all[all.length - 1]?.close ?? 0;
|
|
17905
|
-
if (!isDraft) {
|
|
17906
|
-
this.emitter.emit("tradeLevelEditOpen", {
|
|
17907
|
-
label: level.label,
|
|
17908
|
-
type: level.type,
|
|
17909
|
-
data: level.data,
|
|
17910
|
-
price: level.price,
|
|
17911
|
-
side: level.side,
|
|
17912
|
-
stopLossPrice: level.stopLossPrice,
|
|
17913
|
-
takeProfitPrice: level.takeProfitPrice,
|
|
17914
|
-
isFullscreen: this.isFullscreen
|
|
17915
|
-
});
|
|
17916
|
-
}
|
|
18039
|
+
const marketPrice = isEntryOrder || isDraft || isMobilePendingOrder ? 0 : all[all.length - 1]?.close ?? 0;
|
|
17917
18040
|
this._pendingBracketOrderLabel = null;
|
|
17918
18041
|
this._isBracketNew = true;
|
|
17919
18042
|
this.tradeDragHandler.startBracketDrag(
|
|
@@ -18276,6 +18399,6 @@ function defaultTransform(msg) {
|
|
|
18276
18399
|
};
|
|
18277
18400
|
}
|
|
18278
18401
|
|
|
18279
|
-
export { AbcdPattern, AnchoredNote, AnchoredVP, Arc, ArrowDown, ArrowMarker, ArrowUp, BatPattern, Brush, ButterflyPattern, Callout, ChartEngine, Circle, CrabPattern, CrossLine, CyclicLines, CypherPattern, DARK_THEME, DEFAULT_BOTTOM_BAR_CONFIG, DEFAULT_CROSSHAIR_CONFIG, DEFAULT_DRAWING_TOOLBAR_CONFIG, DEFAULT_INDICATOR_OVERLAY_CONFIG, DEFAULT_LABELS, DEFAULT_PRICE_AXIS_CONFIG, DEFAULT_TIME_AXIS_CONFIG, DEFAULT_TOP_BAR_CONFIG, DEFAULT_UI_CONFIG, DatePriceRange, DateRange, DisjointChannel, DrawingManager, ElliottCombination, ElliottCorrective, ElliottImpulse, ElliottTriangle, ElliottWxy, Ellipse, FibChannel, FibCircles, FibExtension, FibFan, FibProjection, FibRetracement, FibSpiral, FibTimezone, FixedRangeVP, Flag, FlatChannel, GannBox, GannFan, GannSquare, GartleyPattern, GhostFeed, HeadShoulders, Highlighter, HorizontalLine, InsidePitchfork, LIGHT_THEME, ModifiedSchiff, ParallelChannel, Path, Pitchfork, Polyline, PriceLabel, PriceNote, PriceProjection, PriceRange, Projection, Rectangle, RegressionTrend, RotatedRectangle, Ruler, SchiffPitchfork, SharkPattern, SineLine, Text, ThreeDrives, TimeCycles, TrendAngle, TrendLine, Triangle, TrianglePattern, VerticalLine, VolumeProfile, WebSocketAdapter, aggregateCandles, deepMergeTheme, resolveCssVarsInTheme, resolveLabels, resolveUiConfig };
|
|
18402
|
+
export { AbcdPattern, AnchoredNote, AnchoredVP, Arc, ArrowDown, ArrowMarker, ArrowUp, BatPattern, Brush, ButterflyPattern, Callout, ChartEngine, Circle, CrabPattern, CrossLine, CyclicLines, CypherPattern, DARK_THEME, DEFAULT_BOTTOM_BAR_CONFIG, DEFAULT_CROSSHAIR_CONFIG, DEFAULT_DRAWING_TOOLBAR_CONFIG, DEFAULT_INDICATOR_OVERLAY_CONFIG, DEFAULT_LABELS, DEFAULT_PRICE_AXIS_CONFIG, DEFAULT_TIME_AXIS_CONFIG, DEFAULT_TOP_BAR_CONFIG, DEFAULT_TRADE_BUTTON_CONFIG, DEFAULT_UI_CONFIG, DatePriceRange, DateRange, DisjointChannel, DrawingManager, ElliottCombination, ElliottCorrective, ElliottImpulse, ElliottTriangle, ElliottWxy, Ellipse, FibChannel, FibCircles, FibExtension, FibFan, FibProjection, FibRetracement, FibSpiral, FibTimezone, FixedRangeVP, Flag, FlatChannel, GannBox, GannFan, GannSquare, GartleyPattern, GhostFeed, HeadShoulders, Highlighter, HorizontalLine, InsidePitchfork, LIGHT_THEME, ModifiedSchiff, ParallelChannel, Path, Pitchfork, Polyline, PriceLabel, PriceNote, PriceProjection, PriceRange, Projection, Rectangle, RegressionTrend, RotatedRectangle, Ruler, SchiffPitchfork, SharkPattern, SineLine, Text, ThreeDrives, TimeCycles, TrendAngle, TrendLine, Triangle, TrianglePattern, VerticalLine, VolumeProfile, WebSocketAdapter, aggregateCandles, deepMergeTheme, resolveCssVarsInTheme, resolveLabels, resolveUiConfig };
|
|
18280
18403
|
//# sourceMappingURL=index.js.map
|
|
18281
18404
|
//# sourceMappingURL=index.js.map
|