acttrader-charts 1.3.0-beta.1 → 1.3.0-beta.2
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/index.cjs +77 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +77 -6
- package/dist/index.js.map +1 -1
- package/dist/webview/chart.html +23 -21
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1890,6 +1890,8 @@ var FONT_BRACKET = "12px 'Inter', system-ui, sans-serif";
|
|
|
1890
1890
|
var BRACKET_BASE_RATIO = 0.68;
|
|
1891
1891
|
var BRACKET_COL_OFFSETS = [0, -0.08, 0.08];
|
|
1892
1892
|
var ADD_BRACKET_BTN_OFFSET_PX = 30;
|
|
1893
|
+
var __bracketDraws = [];
|
|
1894
|
+
var __lastDupeSignature = "";
|
|
1893
1895
|
function hasPnl(level) {
|
|
1894
1896
|
return level.type === "position" && !!level.pnlText;
|
|
1895
1897
|
}
|
|
@@ -1934,8 +1936,9 @@ function getLevelDisplayText(level, price, precision, omitLots = false) {
|
|
|
1934
1936
|
}
|
|
1935
1937
|
function computeBracketLineX(levels, scale, priceRange, priceH, chartW, draggingLabel, dragNewPrice, hoveredLabel, selectedLabel, bracketBoxH = BRACKET_BOX_H) {
|
|
1936
1938
|
const items = [];
|
|
1939
|
+
const lineXOwner = hoveredLabel ?? selectedLabel;
|
|
1937
1940
|
for (const level of levels) {
|
|
1938
|
-
if (level.label !==
|
|
1941
|
+
if (level.label !== lineXOwner) continue;
|
|
1939
1942
|
const bh = level;
|
|
1940
1943
|
if (bh.stopLossPrice !== void 0) {
|
|
1941
1944
|
const key = `${level.label}:stopLoss`;
|
|
@@ -2031,6 +2034,9 @@ function isDraggable(level) {
|
|
|
2031
2034
|
return !!level.entryPriceEditable;
|
|
2032
2035
|
return false;
|
|
2033
2036
|
}
|
|
2037
|
+
function passiveBracketsVisible(alwaysShowBrackets, activeLabel) {
|
|
2038
|
+
return alwaysShowBrackets && activeLabel === null;
|
|
2039
|
+
}
|
|
2034
2040
|
function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH, precision, hoveredLabel = null, draggingLabel = null, dragNewPrice = null, selectedLabel = null, pendingLabels = /* @__PURE__ */ new Set(), positionStyle = "line", hideConfirmCancel = false, draftOrderLabel = null, draftBracketPnl = {}, expandedClusters = /* @__PURE__ */ new Set(), clusterThresholdPx = 0, showQuantityField = false, dragNewSLPrice = null, dragNewTPPrice = null, buttonScale = 1, alwaysShowBrackets = false, anchorXResolver = null, timeDragEnabled = false) {
|
|
2035
2041
|
if (levels.length === 0)
|
|
2036
2042
|
return {
|
|
@@ -2044,6 +2050,7 @@ function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH
|
|
|
2044
2050
|
clusters: []
|
|
2045
2051
|
};
|
|
2046
2052
|
const colors = theme.tradeLevels;
|
|
2053
|
+
__bracketDraws = [];
|
|
2047
2054
|
const s = Math.min(Math.max(buttonScale, 1), 3);
|
|
2048
2055
|
const closeR = CLOSE_R * s;
|
|
2049
2056
|
const editR = EDIT_R * s;
|
|
@@ -2144,8 +2151,9 @@ function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH
|
|
|
2144
2151
|
);
|
|
2145
2152
|
const bracketItems = [];
|
|
2146
2153
|
const fallbackX = chartW * BRACKET_BASE_RATIO;
|
|
2154
|
+
const cascadeOwner = hoveredLabel ?? selectedLabel;
|
|
2147
2155
|
for (const level of levels) {
|
|
2148
|
-
if (level.label !==
|
|
2156
|
+
if (level.label !== cascadeOwner) continue;
|
|
2149
2157
|
const bh = level;
|
|
2150
2158
|
const mainDrag = draggingLabel === level.label;
|
|
2151
2159
|
if (bh.stopLossPrice !== void 0) {
|
|
@@ -2192,6 +2200,10 @@ function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH
|
|
|
2192
2200
|
}
|
|
2193
2201
|
const activeLabel = hoveredLabel ?? selectedLabel;
|
|
2194
2202
|
const bracketPnlHostLabel = draftOrderLabel ?? selectedLabel;
|
|
2203
|
+
const effectiveAlwaysShowBrackets = passiveBracketsVisible(
|
|
2204
|
+
alwaysShowBrackets,
|
|
2205
|
+
activeLabel
|
|
2206
|
+
);
|
|
2195
2207
|
const visibleMeasured = measured.filter((m) => !collapsedLabels.has(m.level.label));
|
|
2196
2208
|
const drawOrder = [
|
|
2197
2209
|
...visibleMeasured.filter((m) => m.level.label !== activeLabel),
|
|
@@ -2243,9 +2255,10 @@ function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH
|
|
|
2243
2255
|
dragNewTPPrice,
|
|
2244
2256
|
buttonScale,
|
|
2245
2257
|
bracketBoxYMap,
|
|
2246
|
-
|
|
2258
|
+
effectiveAlwaysShowBrackets,
|
|
2247
2259
|
timeDragEnabled && anchorXResolver ? anchorXResolver(level) : null,
|
|
2248
|
-
timeDragEnabled
|
|
2260
|
+
timeDragEnabled,
|
|
2261
|
+
level.label === activeLabel
|
|
2249
2262
|
);
|
|
2250
2263
|
const ec = labelToExpandedCluster.get(level.label);
|
|
2251
2264
|
if (ec && layout.boxY !== layout.y - boxH / 2) {
|
|
@@ -2327,6 +2340,50 @@ function renderTradeLevels(ctx, levels, scale, priceRange, theme, chartW, priceH
|
|
|
2327
2340
|
}
|
|
2328
2341
|
}
|
|
2329
2342
|
}
|
|
2343
|
+
{
|
|
2344
|
+
globalThis.__bracketDrawsLast = __bracketDraws.slice();
|
|
2345
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2346
|
+
for (const d of __bracketDraws) {
|
|
2347
|
+
const k = `${d.bracketType}@${d.price}`;
|
|
2348
|
+
counts.set(k, (counts.get(k) ?? 0) + 1);
|
|
2349
|
+
}
|
|
2350
|
+
const dupeKeys = [...counts.entries()].filter(([, n]) => n > 1).map(([k]) => k);
|
|
2351
|
+
if (dupeKeys.length > 0) {
|
|
2352
|
+
const signature = dupeKeys.join(",") + "|" + __bracketDraws.map((d) => `${d.label}/${d.levelType}/${d.bW}`).join(",");
|
|
2353
|
+
if (signature !== __lastDupeSignature) {
|
|
2354
|
+
__lastDupeSignature = signature;
|
|
2355
|
+
const frame = {
|
|
2356
|
+
hoveredLabel,
|
|
2357
|
+
selectedLabel,
|
|
2358
|
+
draftOrderLabel,
|
|
2359
|
+
draftBracketPnl,
|
|
2360
|
+
levels: levels.map((l) => ({
|
|
2361
|
+
label: l.label,
|
|
2362
|
+
type: l.type,
|
|
2363
|
+
price: l.price,
|
|
2364
|
+
sl: l.stopLossPrice,
|
|
2365
|
+
tp: l.takeProfitPrice,
|
|
2366
|
+
isDraft: !!l.data?._isDraft
|
|
2367
|
+
}))
|
|
2368
|
+
};
|
|
2369
|
+
console.warn(
|
|
2370
|
+
`[ActCharts] DUPLICATE BRACKET BOX \u2192 ${dupeKeys.join(", ")}
|
|
2371
|
+
hovered=${hoveredLabel ?? "null"} selected=${selectedLabel ?? "null"} draft=${draftOrderLabel ?? "null"}
|
|
2372
|
+
` + __bracketDraws.map(
|
|
2373
|
+
(d, i) => ` box#${i + 1} label=${d.label} type=${d.levelType} draft=${d.isDraft} ${d.bracketType}@${d.price} bX=${d.bX} bW=${d.bW} right=${d.rightEdge} boxY=${d.boxY} pnl=${d.pnlText === null ? "none" : JSON.stringify(d.pnlText)} hideCC=${d.hideConfirmCancel}`
|
|
2374
|
+
).join("\n") + `
|
|
2375
|
+
levels this frame: ` + frame.levels.map((l) => `${l.label}/${l.type}${l.isDraft ? "/DRAFT" : ""} price=${l.price} sl=${l.sl} tp=${l.tp}`).join(" | ")
|
|
2376
|
+
);
|
|
2377
|
+
if (typeof window !== "undefined") {
|
|
2378
|
+
window.__bracketDupe = {
|
|
2379
|
+
dupeKeys,
|
|
2380
|
+
frame,
|
|
2381
|
+
draws: __bracketDraws.slice()
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2330
2387
|
ctx.restore();
|
|
2331
2388
|
return {
|
|
2332
2389
|
hitAreas,
|
|
@@ -2482,7 +2539,7 @@ function drawDotHoverBox(ctx, level, y, dotX, dotR, theme, precision) {
|
|
|
2482
2539
|
});
|
|
2483
2540
|
ctx.restore();
|
|
2484
2541
|
}
|
|
2485
|
-
function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered, selected, scale, priceRange, priceH, draggingLabel, dragNewPrice, bracketLineXMap, hasPendingChanges, positionStyle, hitAreas, editAreas, hoverAreas, dragAreas, confirmAreas, addBracketAreas, hideConfirmCancel = false, draftBracketPnl, showQuantityField = false, draftQtyPillAreas, dragNewSLPrice = null, dragNewTPPrice = null, buttonScale = 1, bracketBoxYMap, alwaysShowBrackets = false, anchorX = null, timeDragEnabled = false) {
|
|
2542
|
+
function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered, selected, scale, priceRange, priceH, draggingLabel, dragNewPrice, bracketLineXMap, hasPendingChanges, positionStyle, hitAreas, editAreas, hoverAreas, dragAreas, confirmAreas, addBracketAreas, hideConfirmCancel = false, draftBracketPnl, showQuantityField = false, draftQtyPillAreas, dragNewSLPrice = null, dragNewTPPrice = null, buttonScale = 1, bracketBoxYMap, alwaysShowBrackets = false, anchorX = null, timeDragEnabled = false, isBracketOwner) {
|
|
2486
2543
|
const { y, boxY, boxW, boxH } = layout;
|
|
2487
2544
|
const color = levelColor(level, colors, theme);
|
|
2488
2545
|
const active = hovered || selected;
|
|
@@ -2532,7 +2589,8 @@ function drawLevel(ctx, level, layout, chartW, colors, theme, precision, hovered
|
|
|
2532
2589
|
const boxX = draggable ? groupX + GRIP_W + 2 : groupX;
|
|
2533
2590
|
const badgeTimeDrag = timeDragEnabled && level.timeDraggable === true;
|
|
2534
2591
|
const bracketHost = level;
|
|
2535
|
-
|
|
2592
|
+
const bracketOwner = isBracketOwner ?? active;
|
|
2593
|
+
if (bracketOwner || isMarketDraft || passiveBracketShow) {
|
|
2536
2594
|
const slDragKey = `${level.label}:stopLoss`;
|
|
2537
2595
|
const tpDragKey = `${level.label}:takeProfit`;
|
|
2538
2596
|
const mainDragActive = draggingLabel === level.label;
|
|
@@ -2994,6 +3052,19 @@ function drawBracketLine(ctx, level, bracketType, bracketPrice, scale, priceRang
|
|
|
2994
3052
|
const bY = boxYOverride ?? naturalBoxY;
|
|
2995
3053
|
const boxCenterY = bY + bH / 2;
|
|
2996
3054
|
const displaced = Math.abs(bY - naturalBoxY) >= 2;
|
|
3055
|
+
__bracketDraws.push({
|
|
3056
|
+
label: level.label,
|
|
3057
|
+
levelType: level.type,
|
|
3058
|
+
isDraft: !!level.data?._isDraft,
|
|
3059
|
+
bracketType,
|
|
3060
|
+
price,
|
|
3061
|
+
bX: Math.round(bX),
|
|
3062
|
+
bW: Math.round(bW),
|
|
3063
|
+
rightEdge: Math.round(bX + bW),
|
|
3064
|
+
boxY: Math.round(bY),
|
|
3065
|
+
pnlText: pnlText ?? null,
|
|
3066
|
+
hideConfirmCancel
|
|
3067
|
+
});
|
|
2997
3068
|
if (displaced) {
|
|
2998
3069
|
drawBracketLeader(ctx, bX + bW / 2, boxCenterY, y, theme);
|
|
2999
3070
|
}
|