acttrader-charts 1.1.0 → 1.1.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/README.md +1 -0
- package/dist/{MACD-BgCuLbX_.d.cts → MACD-Dqi682ei.d.cts} +11 -0
- package/dist/{MACD-BgCuLbX_.d.ts → MACD-Dqi682ei.d.ts} +11 -0
- package/dist/index.cjs +31 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +31 -15
- 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 +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -287,6 +287,7 @@ When `enableTrading` is on and live BID/ASK data is streaming, hovering / activa
|
|
|
287
287
|
| `tradeDisplayFilter` | | `"all"` | Which TFC levels are visible: `"all"` · `"positions"` · `"orders"` · `"none"` |
|
|
288
288
|
| `positionRenderStyle` | | auto | Force position render style: `"line"` or `"dot"` |
|
|
289
289
|
| `hideLevelConfirmCancel` | | `false` | Hide on-canvas ✓/✗ confirm-cancel buttons for TFC level edits |
|
|
290
|
+
| `deselectActiveOnOutsideClick` | | `false` | When `true`, clicking/tapping anywhere outside a selected trade level dismisses it (reverting any pending edits, mirroring ✗ Cancel). Default `false` keeps the level active so incidental clicks — price-axis resize, taps outside the QTY input — don't drop an in-progress edit. The level can still be dismissed via ✓/✗, tapping the level again, or `setLevels()` removing it |
|
|
290
291
|
| `showTradeLevelsAlways` | | `false` | Always render SL/TP bracket lines + price pills, even when the parent level is not hovered or selected. The close (×) button stays hover-only so the chart isn't cluttered. Toggleable from the Settings dialog (Trading tab). Persisted in `localStorage`. |
|
|
291
292
|
| `tradeLevelButtonScale` | | `1` | Multiplier for trade-level Confirm/Cancel/Edit/Close button radii and gaps. Scales visuals **and** hit/drag areas together — raise it on touch devices for larger tap targets. Clamped to `[1, 3]`. Also settable at runtime via `chart.setTradeLevelButtonScale(scale)` |
|
|
292
293
|
| `tfcEnabled` | | `true` | Enable the TFC toggle button in the top bar. When `false`, TFC is completely disabled — the toggle button is hidden and all trade levels, draft orders, and the floating trade button are suppressed |
|
|
@@ -879,6 +879,17 @@ interface ChartConfig {
|
|
|
879
879
|
* Default: `false`.
|
|
880
880
|
*/
|
|
881
881
|
hideLevelConfirmCancel?: boolean;
|
|
882
|
+
/**
|
|
883
|
+
* When `true`, clicking or tapping anywhere outside a selected/active trade
|
|
884
|
+
* level dismisses it (reverting any pending edits, mirroring ✗ Cancel).
|
|
885
|
+
* When `false` (default), the active level is preserved across outside
|
|
886
|
+
* clicks — only explicit ✓ / ✗ buttons, tapping the level itself, or
|
|
887
|
+
* `setLevels()` removing it will dismiss it. Recommended `false` so
|
|
888
|
+
* incidental clicks (e.g. price-axis resize, tapping outside the QTY input)
|
|
889
|
+
* don't drop the user's in-progress edit.
|
|
890
|
+
* Default: `false`.
|
|
891
|
+
*/
|
|
892
|
+
deselectActiveOnOutsideClick?: boolean;
|
|
882
893
|
/**
|
|
883
894
|
* Always render SL/TP bracket lines + price pills, even when the parent
|
|
884
895
|
* trade level is not hovered or selected. Close (×) buttons remain
|
|
@@ -879,6 +879,17 @@ interface ChartConfig {
|
|
|
879
879
|
* Default: `false`.
|
|
880
880
|
*/
|
|
881
881
|
hideLevelConfirmCancel?: boolean;
|
|
882
|
+
/**
|
|
883
|
+
* When `true`, clicking or tapping anywhere outside a selected/active trade
|
|
884
|
+
* level dismisses it (reverting any pending edits, mirroring ✗ Cancel).
|
|
885
|
+
* When `false` (default), the active level is preserved across outside
|
|
886
|
+
* clicks — only explicit ✓ / ✗ buttons, tapping the level itself, or
|
|
887
|
+
* `setLevels()` removing it will dismiss it. Recommended `false` so
|
|
888
|
+
* incidental clicks (e.g. price-axis resize, tapping outside the QTY input)
|
|
889
|
+
* don't drop the user's in-progress edit.
|
|
890
|
+
* Default: `false`.
|
|
891
|
+
*/
|
|
892
|
+
deselectActiveOnOutsideClick?: boolean;
|
|
882
893
|
/**
|
|
883
894
|
* Always render SL/TP bracket lines + price pills, even when the parent
|
|
884
895
|
* trade level is not hovered or selected. Close (×) buttons remain
|
package/dist/index.cjs
CHANGED
|
@@ -3371,6 +3371,7 @@ function formatTimestamp(ts, visibleBars, timeframe, spansMultipleDays, timezone
|
|
|
3371
3371
|
return d.toLocaleDateString("en-US", { month: "short", year: "2-digit", timeZone: timezone });
|
|
3372
3372
|
}
|
|
3373
3373
|
function renderTimeAxis(ctx, bars, viewport, scale, theme, chartWidth, axisY, maxLabels = 8, cfg = DEFAULT_TIME_AXIS_CONFIG, timeframe, countdownBarIndex, timezone = "UTC") {
|
|
3374
|
+
if (bars.length === 0) return;
|
|
3374
3375
|
const visibleBars = viewport.endIndex - viewport.startIndex;
|
|
3375
3376
|
const firstBar = bars[0];
|
|
3376
3377
|
const lastBar = bars[bars.length - 1];
|
|
@@ -3379,7 +3380,8 @@ function renderTimeAxis(ctx, bars, viewport, scale, theme, chartWidth, axisY, ma
|
|
|
3379
3380
|
ctx.font = `${cfg.fontSize} ${cfg.fontFamily}`;
|
|
3380
3381
|
ctx.textAlign = "center";
|
|
3381
3382
|
const MIN_GAP = 12;
|
|
3382
|
-
const
|
|
3383
|
+
const sampleBar = bars[Math.floor(bars.length / 2)] ?? bars[0];
|
|
3384
|
+
const sampleLabel = formatTimestamp(sampleBar.time, visibleBars, timeframe, spansMultipleDays, timezone);
|
|
3383
3385
|
const labelW = ctx.measureText(sampleLabel).width;
|
|
3384
3386
|
const minStep = Math.max(1, Math.floor(bars.length / maxLabels));
|
|
3385
3387
|
let step = minStep;
|
|
@@ -18661,6 +18663,9 @@ var _ChartEngine = class _ChartEngine {
|
|
|
18661
18663
|
this.tickActivityTimer = null;
|
|
18662
18664
|
this.tickActivityMs = 3e4;
|
|
18663
18665
|
this.streamStatus = "disconnected";
|
|
18666
|
+
// Set by destroy() so late-firing callbacks (ResizeObserver entries queued
|
|
18667
|
+
// before disconnect, in-flight promises, sockets) bail before touching state.
|
|
18668
|
+
this._isDestroyed = false;
|
|
18664
18669
|
this.indicatorSettingsDialog = null;
|
|
18665
18670
|
this.chartSettingsDialog = null;
|
|
18666
18671
|
this.tradeButton = null;
|
|
@@ -18693,6 +18698,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
18693
18698
|
this.showBidAskLines = false;
|
|
18694
18699
|
this.showActLogo = false;
|
|
18695
18700
|
this.hideLevelConfirmCancel = false;
|
|
18701
|
+
this.deselectActiveOnOutsideClick = false;
|
|
18696
18702
|
this.tradeLevelButtonScale = 1;
|
|
18697
18703
|
this.levelClusteringEnabled = true;
|
|
18698
18704
|
this.clusterThresholdDistance = 20;
|
|
@@ -19662,7 +19668,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
19662
19668
|
}
|
|
19663
19669
|
return;
|
|
19664
19670
|
} else if (this.selectedTradeLabel !== null) {
|
|
19665
|
-
if (!this.hideLevelConfirmCancel) {
|
|
19671
|
+
if (!this.hideLevelConfirmCancel && this.deselectActiveOnOutsideClick) {
|
|
19666
19672
|
const lbl = this.selectedTradeLabel;
|
|
19667
19673
|
const pending = this.pendingLevelDrags.get(lbl);
|
|
19668
19674
|
if (!pending || pending.length === 0) {
|
|
@@ -19813,6 +19819,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
19813
19819
|
}
|
|
19814
19820
|
};
|
|
19815
19821
|
this.onTick = (tick) => {
|
|
19822
|
+
if (this._isDestroyed) return;
|
|
19816
19823
|
const all = this.dataStore.all;
|
|
19817
19824
|
if (all.length === 0) return;
|
|
19818
19825
|
if (this._suppressTicks) return;
|
|
@@ -19952,6 +19959,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
19952
19959
|
this.showBidAskLines = config.showBidAskLines ?? false;
|
|
19953
19960
|
this.showActLogo = config.showActLogo ?? false;
|
|
19954
19961
|
this.hideLevelConfirmCancel = config.hideLevelConfirmCancel ?? false;
|
|
19962
|
+
this.deselectActiveOnOutsideClick = config.deselectActiveOnOutsideClick ?? false;
|
|
19955
19963
|
this.tradeLevelButtonScale = Math.min(Math.max(config.tradeLevelButtonScale ?? 1, 1), 3);
|
|
19956
19964
|
this.levelClusteringEnabled = config.levelClusteringEnabled ?? true;
|
|
19957
19965
|
this.clusterThresholdDistance = config.clusterThresholdDistance ?? 20;
|
|
@@ -22221,6 +22229,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
22221
22229
|
return this;
|
|
22222
22230
|
}
|
|
22223
22231
|
destroy() {
|
|
22232
|
+
this._isDestroyed = true;
|
|
22224
22233
|
this.panHandler.destroy();
|
|
22225
22234
|
this.zoomHandler.destroy();
|
|
22226
22235
|
this.resizeObserver.disconnect();
|
|
@@ -22353,6 +22362,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
22353
22362
|
}
|
|
22354
22363
|
// ── Rendering ─────────────────────────────────────────────────────────────
|
|
22355
22364
|
scheduleRender() {
|
|
22365
|
+
if (this._isDestroyed) return;
|
|
22356
22366
|
if (this.rafId !== null) return;
|
|
22357
22367
|
this.rafId = requestAnimationFrame(() => {
|
|
22358
22368
|
this.rafId = null;
|
|
@@ -22542,6 +22552,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
22542
22552
|
this.positionRenderStyle = activeCount > this.tradesThresholdForHorizontalLine ? "dot" : "line";
|
|
22543
22553
|
}
|
|
22544
22554
|
renderTradeLayer() {
|
|
22555
|
+
if (this._isDestroyed) return;
|
|
22545
22556
|
const dpr = window.devicePixelRatio || 1;
|
|
22546
22557
|
const { tradeCtx: ctx, tradeCanvas: canvas, theme, viewport } = this;
|
|
22547
22558
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
@@ -23087,6 +23098,7 @@ var _ChartEngine = class _ChartEngine {
|
|
|
23087
23098
|
});
|
|
23088
23099
|
}
|
|
23089
23100
|
render() {
|
|
23101
|
+
if (this._isDestroyed) return;
|
|
23090
23102
|
const { ctx, canvas, theme, viewport } = this;
|
|
23091
23103
|
const dpr = window.devicePixelRatio || 1;
|
|
23092
23104
|
const totalW = canvas.width;
|
|
@@ -23534,19 +23546,21 @@ var _ChartEngine = class _ChartEngine {
|
|
|
23534
23546
|
);
|
|
23535
23547
|
if (showCountdown) {
|
|
23536
23548
|
const lastBar2 = this.dataStore.all[this.dataStore.length - 1];
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23549
|
+
if (lastBar2) {
|
|
23550
|
+
const intervalMs = this.timeframeToMs(this.timeframe);
|
|
23551
|
+
renderCandleCountdown(
|
|
23552
|
+
ctx,
|
|
23553
|
+
lastBar2.time,
|
|
23554
|
+
intervalMs,
|
|
23555
|
+
this.dataStore.length - 1,
|
|
23556
|
+
viewport,
|
|
23557
|
+
this.scaleManager,
|
|
23558
|
+
theme,
|
|
23559
|
+
chartW,
|
|
23560
|
+
subPaneY,
|
|
23561
|
+
this.uiConfig.timeAxis
|
|
23562
|
+
);
|
|
23563
|
+
}
|
|
23550
23564
|
}
|
|
23551
23565
|
}
|
|
23552
23566
|
if (this.crosshair) {
|
|
@@ -23635,8 +23649,10 @@ var _ChartEngine = class _ChartEngine {
|
|
|
23635
23649
|
}
|
|
23636
23650
|
}
|
|
23637
23651
|
onResize() {
|
|
23652
|
+
if (this._isDestroyed) return;
|
|
23638
23653
|
const dpr = window.devicePixelRatio || 1;
|
|
23639
23654
|
const rect = this.canvasWrap.getBoundingClientRect();
|
|
23655
|
+
if (rect.width === 0 || rect.height === 0) return;
|
|
23640
23656
|
this._cachedWrapRect = rect;
|
|
23641
23657
|
this._cachedDrawRect = this.drawCanvas.getBoundingClientRect();
|
|
23642
23658
|
for (const c of [this.canvas, this.tradeCanvas, this.drawCanvas]) {
|