@forgecharts/sdk 1.5.82 → 1.5.84
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/api/EventBus.d.ts +1 -1
- package/dist/api/{TChart.d.ts → ForgeCharts.d.ts} +47 -4
- package/dist/api/ForgeCharts.d.ts.map +1 -0
- package/dist/api/createChart.d.ts +4 -4
- package/dist/api/createChart.d.ts.map +1 -1
- package/dist/core/Chart.d.ts +5 -5
- package/dist/core/Chart.d.ts.map +1 -1
- package/dist/core/Series.d.ts +14 -0
- package/dist/core/Series.d.ts.map +1 -1
- package/dist/core/__tests__/seriesCutoff.test.d.ts +2 -0
- package/dist/core/__tests__/seriesCutoff.test.d.ts.map +1 -0
- package/dist/datafeed/DatafeedConnector.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +520 -27
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +520 -27
- package/dist/internal.js.map +1 -1
- package/dist/licensing/packageFeatures.d.ts.map +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/pixi/PixiCandlestickRenderer.d.ts +4 -0
- package/dist/pixi/PixiCandlestickRenderer.d.ts.map +1 -1
- package/dist/pixi/PixiChart.d.ts +18 -2
- package/dist/pixi/PixiChart.d.ts.map +1 -1
- package/dist/pixi/PixiHistogramRenderer.d.ts +2 -0
- package/dist/pixi/PixiHistogramRenderer.d.ts.map +1 -1
- package/dist/pixi/PixiLineRenderer.d.ts +2 -0
- package/dist/pixi/PixiLineRenderer.d.ts.map +1 -1
- package/dist/react/canvas/ChartCanvas.d.ts +20 -2
- package/dist/react/canvas/ChartCanvas.d.ts.map +1 -1
- package/dist/react/hooks/useUserPackage.d.ts.map +1 -1
- package/dist/react/index.js +807 -63
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +814 -83
- package/dist/react/internal.js.map +1 -1
- package/dist/react/shell/AlertsDrawer.d.ts +11 -0
- package/dist/react/shell/AlertsDrawer.d.ts.map +1 -0
- package/dist/react/shell/ManagedAppShell.d.ts +1 -1
- package/dist/react/shell/ManagedAppShell.d.ts.map +1 -1
- package/dist/react/workspace/ChartWorkspace.d.ts +10 -1
- package/dist/react/workspace/ChartWorkspace.d.ts.map +1 -1
- package/dist/react/workspace/LayoutMenu.d.ts +3 -1
- package/dist/react/workspace/LayoutMenu.d.ts.map +1 -1
- package/dist/react/workspace/toolbars/TopToolbar.d.ts +7 -1
- package/dist/react/workspace/toolbars/TopToolbar.d.ts.map +1 -1
- package/dist/types/ChartBackend.d.ts +17 -4
- package/dist/types/ChartBackend.d.ts.map +1 -1
- package/dist/types/ISeries.d.ts +5 -0
- package/dist/types/ISeries.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/api/TChart.d.ts.map +0 -1
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TextStyle, Application,
|
|
1
|
+
import { TextStyle, Application, Graphics, Container, Text, FillGradient, CanvasTextMetrics } from 'pixi.js';
|
|
2
2
|
import { forwardRef, useRef, useState, useEffect, useImperativeHandle, useCallback, createContext, useMemo, useContext } from 'react';
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import ReactDOM, { createPortal } from 'react-dom';
|
|
@@ -1383,6 +1383,7 @@ var Series = class _Series {
|
|
|
1383
1383
|
// ─── ISeries implementation ──────────────────────────────────────────────────
|
|
1384
1384
|
setData(data) {
|
|
1385
1385
|
this._data = [...data].sort((a, b) => a.time - b.time);
|
|
1386
|
+
this._cutoffView = null;
|
|
1386
1387
|
this.onDataChanged?.();
|
|
1387
1388
|
}
|
|
1388
1389
|
/**
|
|
@@ -1422,11 +1423,47 @@ var Series = class _Series {
|
|
|
1422
1423
|
this._data = this._data.slice(this._data.length - 1e5);
|
|
1423
1424
|
}
|
|
1424
1425
|
}
|
|
1426
|
+
this._cutoffView = null;
|
|
1425
1427
|
this.onDataChanged?.();
|
|
1426
1428
|
}
|
|
1427
|
-
|
|
1429
|
+
/**
|
|
1430
|
+
* Bar-replay display cutoff. When set, data() returns only bars at or
|
|
1431
|
+
* before this time while the FULL tape keeps flowing underneath — the
|
|
1432
|
+
* datafeed keeps writing live bars via setData/update, and everything
|
|
1433
|
+
* downstream (renderers, indicators, crosshair, last-price) naturally sees
|
|
1434
|
+
* the truncated past. Replay is not a mode the pipeline knows about; it is
|
|
1435
|
+
* this clamp plus a controller that moves it.
|
|
1436
|
+
*/
|
|
1437
|
+
_cutoffTime = null;
|
|
1438
|
+
_cutoffView = null;
|
|
1439
|
+
setCutoffTime(time) {
|
|
1440
|
+
this._cutoffTime = time;
|
|
1441
|
+
this._cutoffView = null;
|
|
1442
|
+
this.onDataChanged?.();
|
|
1443
|
+
}
|
|
1444
|
+
cutoffTime() {
|
|
1445
|
+
return this._cutoffTime;
|
|
1446
|
+
}
|
|
1447
|
+
/** The complete tape, ignoring any replay cutoff. Datafeed-side reads only. */
|
|
1448
|
+
fullData() {
|
|
1428
1449
|
return this._data;
|
|
1429
1450
|
}
|
|
1451
|
+
data() {
|
|
1452
|
+
if (this._cutoffTime === null) return this._data;
|
|
1453
|
+
const len = this._data.length;
|
|
1454
|
+
const cached = this._cutoffView;
|
|
1455
|
+
if (cached && cached.len === len && cached.cutoff === this._cutoffTime) return cached.view;
|
|
1456
|
+
let lo = 0;
|
|
1457
|
+
let hi = len;
|
|
1458
|
+
while (lo < hi) {
|
|
1459
|
+
const mid = lo + hi >>> 1;
|
|
1460
|
+
if (this._data[mid].time <= this._cutoffTime) lo = mid + 1;
|
|
1461
|
+
else hi = mid;
|
|
1462
|
+
}
|
|
1463
|
+
const view = this._data.slice(0, lo);
|
|
1464
|
+
this._cutoffView = { len, cutoff: this._cutoffTime, view };
|
|
1465
|
+
return view;
|
|
1466
|
+
}
|
|
1430
1467
|
applyOptions(options) {
|
|
1431
1468
|
this._options = { ...this._options, ...options };
|
|
1432
1469
|
}
|
|
@@ -4757,14 +4794,14 @@ var Chart = class {
|
|
|
4757
4794
|
_crosshairEnabled = true;
|
|
4758
4795
|
_magnetMode = "snap-xy";
|
|
4759
4796
|
// ── Trading overlay ───────────────────────────────────────────────────────────
|
|
4760
|
-
/** Current set of order lines supplied by
|
|
4797
|
+
/** Current set of order lines supplied by ForgeCharts for canvas rendering. */
|
|
4761
4798
|
_tradingOrders = [];
|
|
4762
4799
|
/** Called whenever a drawing is committed (created or updated). */
|
|
4763
4800
|
onDrawingCommitted;
|
|
4764
4801
|
/** Fired when an EXISTING drawing is modified via drag (handle or body move). */
|
|
4765
4802
|
onDrawingEdited;
|
|
4766
4803
|
_drawingEditDirty = false;
|
|
4767
|
-
/** Ctrl+Z / Ctrl+Y — drawing history is owned by
|
|
4804
|
+
/** Ctrl+Z / Ctrl+Y — drawing history is owned by ForgeCharts. */
|
|
4768
4805
|
onUndoRequest;
|
|
4769
4806
|
onRedoRequest;
|
|
4770
4807
|
/** Called whenever a drawing is deleted. */
|
|
@@ -4780,7 +4817,7 @@ var Chart = class {
|
|
|
4780
4817
|
/** Called when the user drags a TP/SL pill off an entry line to create a bracket leg. */
|
|
4781
4818
|
onTpSlCreate;
|
|
4782
4819
|
/**
|
|
4783
|
-
* Called after every pan or zoom interaction so external code (e.g.
|
|
4820
|
+
* Called after every pan or zoom interaction so external code (e.g. ForgeCharts)
|
|
4784
4821
|
* can check whether the visible time range now extends past the oldest
|
|
4785
4822
|
* loaded bar and trigger a lazy history fetch.
|
|
4786
4823
|
*/
|
|
@@ -5283,11 +5320,11 @@ var Chart = class {
|
|
|
5283
5320
|
}
|
|
5284
5321
|
ctx.restore();
|
|
5285
5322
|
}
|
|
5286
|
-
/** Provides the overlay renderer with the latest order list from
|
|
5323
|
+
/** Provides the overlay renderer with the latest order list from ForgeCharts. */
|
|
5287
5324
|
setTradingOrders(orders) {
|
|
5288
5325
|
this._tradingOrders = orders;
|
|
5289
5326
|
}
|
|
5290
|
-
/** Provides the overlay renderer with the latest position list from
|
|
5327
|
+
/** Provides the overlay renderer with the latest position list from ForgeCharts. */
|
|
5291
5328
|
setTradingPositions(_positions) {
|
|
5292
5329
|
}
|
|
5293
5330
|
/** Sets contract switch markers for continuous futures roll dates. */
|
|
@@ -6114,9 +6151,17 @@ var PixiCandlestickRenderer = class {
|
|
|
6114
6151
|
this._gfx = new Graphics();
|
|
6115
6152
|
layer.addChild(this._gfx);
|
|
6116
6153
|
}
|
|
6154
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
6155
|
+
clear() {
|
|
6156
|
+
this._gfx.clear();
|
|
6157
|
+
}
|
|
6117
6158
|
draw(bars, transform, opts) {
|
|
6118
6159
|
const gfx = this._gfx;
|
|
6119
6160
|
gfx.clear();
|
|
6161
|
+
if (opts?.type === "bar") {
|
|
6162
|
+
this._drawBars(bars, transform, opts);
|
|
6163
|
+
return;
|
|
6164
|
+
}
|
|
6120
6165
|
if (bars.length === 0) return;
|
|
6121
6166
|
const { plotWidth: pw, plotHeight: ph } = transform;
|
|
6122
6167
|
const upColor = hexToNum(opts && "upColor" in opts ? opts.upColor : void 0, UP_COLOR);
|
|
@@ -6247,6 +6292,36 @@ var PixiCandlestickRenderer = class {
|
|
|
6247
6292
|
/**
|
|
6248
6293
|
* Converts OHLCV bars to Heikin-Ashi values before drawing.
|
|
6249
6294
|
*/
|
|
6295
|
+
/** Classic OHLC bars: high-low spine, open tick left, close tick right. */
|
|
6296
|
+
_drawBars(bars, transform, opts) {
|
|
6297
|
+
const gfx = this._gfx;
|
|
6298
|
+
if (bars.length === 0) return;
|
|
6299
|
+
const upColor = hexToNum(opts && "upColor" in opts ? opts.upColor : void 0, UP_COLOR);
|
|
6300
|
+
const downColor = hexToNum(opts && "downColor" in opts ? opts.downColor : void 0, DOWN_COLOR);
|
|
6301
|
+
const { plotWidth: pw } = transform;
|
|
6302
|
+
let barPitch = pw / Math.max(1, bars.length);
|
|
6303
|
+
if (bars.length >= 2) {
|
|
6304
|
+
const dx = Math.abs(transform.timeToX(bars[1].time) - transform.timeToX(bars[0].time));
|
|
6305
|
+
if (dx > 0) barPitch = dx;
|
|
6306
|
+
}
|
|
6307
|
+
const tick = Math.max(1.5, Math.min(barPitch * 0.35, 6));
|
|
6308
|
+
const lineW = barPitch < 3 ? 1 : 1.5;
|
|
6309
|
+
for (const bar of bars) {
|
|
6310
|
+
const x = transform.timeToX(bar.time);
|
|
6311
|
+
if (x < -barPitch || x > pw + barPitch) continue;
|
|
6312
|
+
const yHigh = transform.priceToY(bar.high);
|
|
6313
|
+
const yLow = transform.priceToY(bar.low);
|
|
6314
|
+
const yOpen = transform.priceToY(bar.open);
|
|
6315
|
+
const yClose = transform.priceToY(bar.close);
|
|
6316
|
+
const color = bar.close >= bar.open ? upColor : downColor;
|
|
6317
|
+
gfx.moveTo(x, yHigh).lineTo(x, yLow);
|
|
6318
|
+
if (barPitch >= 3) {
|
|
6319
|
+
gfx.moveTo(x - tick, yOpen).lineTo(x, yOpen);
|
|
6320
|
+
gfx.moveTo(x, yClose).lineTo(x + tick, yClose);
|
|
6321
|
+
}
|
|
6322
|
+
gfx.stroke({ color, width: lineW });
|
|
6323
|
+
}
|
|
6324
|
+
}
|
|
6250
6325
|
drawHeikinAshi(bars, transform, opts) {
|
|
6251
6326
|
const first = bars[0];
|
|
6252
6327
|
const last = bars[bars.length - 1];
|
|
@@ -7569,6 +7644,10 @@ var PixiLineRenderer = class {
|
|
|
7569
7644
|
this._gradientCache = null;
|
|
7570
7645
|
this._gfx.destroy(true);
|
|
7571
7646
|
}
|
|
7647
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
7648
|
+
clear() {
|
|
7649
|
+
this._gfx.clear();
|
|
7650
|
+
}
|
|
7572
7651
|
draw(bars, transform, options) {
|
|
7573
7652
|
const gfx = this._gfx;
|
|
7574
7653
|
gfx.clear();
|
|
@@ -7663,6 +7742,10 @@ var PixiHistogramRenderer = class {
|
|
|
7663
7742
|
destroy() {
|
|
7664
7743
|
this._gfx.destroy(true);
|
|
7665
7744
|
}
|
|
7745
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
7746
|
+
clear() {
|
|
7747
|
+
this._gfx.clear();
|
|
7748
|
+
}
|
|
7666
7749
|
draw(bars, transform) {
|
|
7667
7750
|
const gfx = this._gfx;
|
|
7668
7751
|
gfx.clear();
|
|
@@ -8642,7 +8725,7 @@ var PixiChart = class {
|
|
|
8642
8725
|
/** Fired when an EXISTING drawing is modified via drag (handle or body move). */
|
|
8643
8726
|
onDrawingEdited;
|
|
8644
8727
|
_drawingEditDirty = false;
|
|
8645
|
-
/** Ctrl+Z / Ctrl+Y — drawing history is owned by
|
|
8728
|
+
/** Ctrl+Z / Ctrl+Y — drawing history is owned by ForgeCharts. */
|
|
8646
8729
|
onUndoRequest;
|
|
8647
8730
|
onRedoRequest;
|
|
8648
8731
|
/** Called whenever a drawing is deleted. */
|
|
@@ -8657,7 +8740,7 @@ var PixiChart = class {
|
|
|
8657
8740
|
onDrawingContextMenu;
|
|
8658
8741
|
/** Called when the user double-clicks a drawing. */
|
|
8659
8742
|
onDrawingDoubleClick;
|
|
8660
|
-
/** Called after every pan/zoom so
|
|
8743
|
+
/** Called after every pan/zoom so ForgeCharts can trigger lazy history loading. */
|
|
8661
8744
|
onViewportChanged;
|
|
8662
8745
|
constructor(container, options = {}) {
|
|
8663
8746
|
this._container = container;
|
|
@@ -8764,6 +8847,12 @@ var PixiChart = class {
|
|
|
8764
8847
|
this.onViewportChanged?.();
|
|
8765
8848
|
},
|
|
8766
8849
|
onCrosshairMove: (x, y) => {
|
|
8850
|
+
if (this._replaySelect) {
|
|
8851
|
+
const t = this._cursorBucketTime(x);
|
|
8852
|
+
this._replayHoverTime = t;
|
|
8853
|
+
this._replaySelect.onHover(t);
|
|
8854
|
+
this._drawReplayDim(x);
|
|
8855
|
+
}
|
|
8767
8856
|
if (!this._crosshairEnabled) return;
|
|
8768
8857
|
if (this._magnetMode === "off") {
|
|
8769
8858
|
this._crosshairRenderer.update(x, y, this._cursorBucketTime(x));
|
|
@@ -9053,7 +9142,7 @@ var PixiChart = class {
|
|
|
9053
9142
|
}).catch(() => {
|
|
9054
9143
|
});
|
|
9055
9144
|
}
|
|
9056
|
-
// ─── Drawing objects (used by PixiChart directly;
|
|
9145
|
+
// ─── Drawing objects (used by PixiChart directly; ForgeCharts uses DrawingManager) ─
|
|
9057
9146
|
/** @internal Used by PixiChart when DrawingManager pushes an update. */
|
|
9058
9147
|
setDrawings(drawings) {
|
|
9059
9148
|
this._drawings = [...drawings];
|
|
@@ -9062,6 +9151,47 @@ var PixiChart = class {
|
|
|
9062
9151
|
// ─── Rendering ───────────────────────────────────────────────────────────────
|
|
9063
9152
|
/** Styles whose renderer has already logged a failure this session. */
|
|
9064
9153
|
_renderErrorLogged = /* @__PURE__ */ new Set();
|
|
9154
|
+
// ── Bar-replay anchor selection ─────────────────────────────────────────
|
|
9155
|
+
_replaySelect = null;
|
|
9156
|
+
_replayHoverTime = null;
|
|
9157
|
+
_replayDimGfx = null;
|
|
9158
|
+
_replayClickHandler = null;
|
|
9159
|
+
setReplaySelect(cb) {
|
|
9160
|
+
this._replaySelect = cb;
|
|
9161
|
+
this._replayHoverTime = null;
|
|
9162
|
+
if (cb) {
|
|
9163
|
+
this._replayClickHandler = () => {
|
|
9164
|
+
if (this._replayHoverTime !== null) this._replaySelect?.onCommit(this._replayHoverTime);
|
|
9165
|
+
};
|
|
9166
|
+
this._app.canvas.addEventListener("click", this._replayClickHandler);
|
|
9167
|
+
this._app.canvas.style.cursor = "crosshair";
|
|
9168
|
+
} else {
|
|
9169
|
+
if (this._replayClickHandler) {
|
|
9170
|
+
this._app.canvas.removeEventListener("click", this._replayClickHandler);
|
|
9171
|
+
this._replayClickHandler = null;
|
|
9172
|
+
}
|
|
9173
|
+
this._app.canvas.style.cursor = "";
|
|
9174
|
+
if (this._replayDimGfx) {
|
|
9175
|
+
this._replayDimGfx.clear();
|
|
9176
|
+
this._replayDimGfx.destroy();
|
|
9177
|
+
this._replayDimGfx = null;
|
|
9178
|
+
}
|
|
9179
|
+
}
|
|
9180
|
+
}
|
|
9181
|
+
/** Translucent veil over the bars a replay-anchor click would remove. */
|
|
9182
|
+
_drawReplayDim(x) {
|
|
9183
|
+
if (!this._replayDimGfx) {
|
|
9184
|
+
this._replayDimGfx = new Graphics();
|
|
9185
|
+
this._layers.get(5 /* Interaction */).addChildAt(this._replayDimGfx, 0);
|
|
9186
|
+
}
|
|
9187
|
+
const gfx = this._replayDimGfx;
|
|
9188
|
+
const { plotWidth, plotHeight } = this._transform;
|
|
9189
|
+
gfx.clear();
|
|
9190
|
+
if (x >= 0 && x < plotWidth) {
|
|
9191
|
+
gfx.rect(x, 0, plotWidth - x, plotHeight).fill({ color: 8421520, alpha: 0.35 });
|
|
9192
|
+
}
|
|
9193
|
+
this._layers.dirty.mark(5 /* Interaction */);
|
|
9194
|
+
}
|
|
9065
9195
|
_renderFrame() {
|
|
9066
9196
|
if (!this._ready || this._destroyed) return;
|
|
9067
9197
|
const t = this._transform;
|
|
@@ -9071,6 +9201,9 @@ var PixiChart = class {
|
|
|
9071
9201
|
if (dirty.isDirty(1 /* PriceSeries */)) {
|
|
9072
9202
|
this._autoFitPriceRange();
|
|
9073
9203
|
dirty.mark(0 /* Background */);
|
|
9204
|
+
this._candleRenderer.clear();
|
|
9205
|
+
this._lineRenderer.clear();
|
|
9206
|
+
this._histogramRenderer.clear();
|
|
9074
9207
|
for (const series of this._series) {
|
|
9075
9208
|
const opts = series.options();
|
|
9076
9209
|
if (opts.visible === false) continue;
|
|
@@ -9283,6 +9416,16 @@ var PixiChart = class {
|
|
|
9283
9416
|
}
|
|
9284
9417
|
this._markViewportDirty();
|
|
9285
9418
|
}
|
|
9419
|
+
/**
|
|
9420
|
+
* Pans the viewport so the bar at `time` sits at the horizontal center.
|
|
9421
|
+
* Used by bar replay: the anchor candle the trader picked becomes the
|
|
9422
|
+
* chart's center, with the (empty, dimmed-away) future to its right.
|
|
9423
|
+
*/
|
|
9424
|
+
centerOnTime(time) {
|
|
9425
|
+
const px = this._transform.timeToX(time);
|
|
9426
|
+
this._transform.pan(-(px - this._transform.plotWidth / 2), 0);
|
|
9427
|
+
this._markViewportDirty();
|
|
9428
|
+
}
|
|
9286
9429
|
/** Pans the viewport so the latest bar sits near the right edge. */
|
|
9287
9430
|
_scrollToLatestBar() {
|
|
9288
9431
|
let latestTime = -Infinity;
|
|
@@ -11207,8 +11350,10 @@ var KIT_FEATURE_TO_CAPABILITY = {
|
|
|
11207
11350
|
multi_chart_layout: "multiChartLayout"
|
|
11208
11351
|
};
|
|
11209
11352
|
var UNMAPPED_KIT_FEATURES = [
|
|
11210
|
-
"delayed_data"
|
|
11211
|
-
|
|
11353
|
+
"delayed_data"
|
|
11354
|
+
// 'ai_script_conversion' (deleted in migration 028) and 'agent' (the
|
|
11355
|
+
// ai_agent duplicate, deleted in migration 052) used to sit here; a key
|
|
11356
|
+
// that no longer exists in the catalog needs no unmapped entry.
|
|
11212
11357
|
];
|
|
11213
11358
|
var PACKAGE_GATED_CAPABILITIES = new Set(
|
|
11214
11359
|
Object.values(KIT_FEATURE_TO_CAPABILITY)
|
|
@@ -12018,8 +12163,8 @@ var ManagedTradingController = class {
|
|
|
12018
12163
|
}
|
|
12019
12164
|
};
|
|
12020
12165
|
|
|
12021
|
-
// src/api/
|
|
12022
|
-
var
|
|
12166
|
+
// src/api/ForgeCharts.ts
|
|
12167
|
+
var ForgeCharts = class _ForgeCharts {
|
|
12023
12168
|
_core;
|
|
12024
12169
|
_bus;
|
|
12025
12170
|
_indicators;
|
|
@@ -12410,7 +12555,7 @@ var TChart = class _TChart {
|
|
|
12410
12555
|
"[ForgeCharts] ForgeScript indicators are not enabled on the active license. Contact your license provider to enable the forgeScript feature."
|
|
12411
12556
|
);
|
|
12412
12557
|
}
|
|
12413
|
-
let finalConfig =
|
|
12558
|
+
let finalConfig = _ForgeCharts.OVERLAY_ONLY.has(config.type) && config.overlay !== true ? { ...config, overlay: true } : config;
|
|
12414
12559
|
if (finalConfig.overlay !== true && !canUseMultiPane()) {
|
|
12415
12560
|
console.warn("[ForgeCharts] multiPane is not enabled on the active license \u2014 indicator added as a price-pane overlay instead.");
|
|
12416
12561
|
finalConfig = { ...finalConfig, overlay: true };
|
|
@@ -12588,7 +12733,7 @@ var TChart = class _TChart {
|
|
|
12588
12733
|
*/
|
|
12589
12734
|
startDrawingTool(type) {
|
|
12590
12735
|
this._assertAlive();
|
|
12591
|
-
if (
|
|
12736
|
+
if (_ForgeCharts.EXTENDED_DRAWING_TOOLS.has(type) && !canUseExtendedDrawings()) {
|
|
12592
12737
|
console.warn(`[ForgeCharts] Drawing tool '${type}' requires the extendedDrawings feature, which is not enabled on the active license.`);
|
|
12593
12738
|
return;
|
|
12594
12739
|
}
|
|
@@ -12626,6 +12771,14 @@ var TChart = class _TChart {
|
|
|
12626
12771
|
/** Set contract switch roll markers for continuous futures. */
|
|
12627
12772
|
setContractSwitches(switches) {
|
|
12628
12773
|
this._assertAlive();
|
|
12774
|
+
if (!canRenderOverlays()) {
|
|
12775
|
+
if (switches.length > 0) {
|
|
12776
|
+
console.warn("[ForgeCharts] Overlay rendering (overlays) is not enabled on the active plan \u2014 contract switch markers suppressed.");
|
|
12777
|
+
}
|
|
12778
|
+
this._core.setContractSwitches([]);
|
|
12779
|
+
this._core.markDirty();
|
|
12780
|
+
return;
|
|
12781
|
+
}
|
|
12629
12782
|
this._core.setContractSwitches(switches);
|
|
12630
12783
|
this._core.markDirty();
|
|
12631
12784
|
}
|
|
@@ -12669,7 +12822,7 @@ var TChart = class _TChart {
|
|
|
12669
12822
|
const snap = this._drawings.all().map((d) => ({ ...d, points: [...d.points] }));
|
|
12670
12823
|
this._drawHistory.splice(this._drawHistIdx + 1);
|
|
12671
12824
|
this._drawHistory.push(snap);
|
|
12672
|
-
if (this._drawHistory.length >
|
|
12825
|
+
if (this._drawHistory.length > _ForgeCharts._HIST_MAX) this._drawHistory.shift();
|
|
12673
12826
|
this._drawHistIdx = this._drawHistory.length - 1;
|
|
12674
12827
|
}
|
|
12675
12828
|
/** Steps drawing state one edit back (Ctrl+Z). */
|
|
@@ -13034,6 +13187,186 @@ var TChart = class _TChart {
|
|
|
13034
13187
|
}
|
|
13035
13188
|
return this._unmanagedIngestion;
|
|
13036
13189
|
}
|
|
13190
|
+
// ─── Bar replay ───────────────────────────────────────────────────────────────
|
|
13191
|
+
//
|
|
13192
|
+
// Replay is a display cutoff on the primary series (Series.setCutoffTime)
|
|
13193
|
+
// plus this controller moving it. The full tape keeps flowing underneath —
|
|
13194
|
+
// live bars land in fullData() and stay hidden until stepped over or the
|
|
13195
|
+
// replay exits — so no datafeed, indicator, or renderer knows replay
|
|
13196
|
+
// exists. Selection (the hover shadow of what a click would remove) is a
|
|
13197
|
+
// backend surface only Pixi implements; ForgeCharts refuses replay elsewhere.
|
|
13198
|
+
/** Playback speeds, in bars per second. */
|
|
13199
|
+
static REPLAY_SPEEDS = [0.5, 1, 2, 5, 10, 15, 20];
|
|
13200
|
+
_replay = {
|
|
13201
|
+
selecting: false,
|
|
13202
|
+
active: false,
|
|
13203
|
+
playing: false,
|
|
13204
|
+
speedIdx: 1,
|
|
13205
|
+
timer: null
|
|
13206
|
+
};
|
|
13207
|
+
_emitReplayState() {
|
|
13208
|
+
this._bus.emit("replayStateChanged", {
|
|
13209
|
+
selecting: this._replay.selecting,
|
|
13210
|
+
active: this._replay.active,
|
|
13211
|
+
playing: this._replay.playing,
|
|
13212
|
+
speed: _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx],
|
|
13213
|
+
cutoffTime: this._series.cutoffTime()
|
|
13214
|
+
});
|
|
13215
|
+
}
|
|
13216
|
+
/** Current replay state — the control strip's render source. */
|
|
13217
|
+
replayState() {
|
|
13218
|
+
return {
|
|
13219
|
+
selecting: this._replay.selecting,
|
|
13220
|
+
active: this._replay.active,
|
|
13221
|
+
playing: this._replay.playing,
|
|
13222
|
+
speed: _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx],
|
|
13223
|
+
cutoffTime: this._series.cutoffTime()
|
|
13224
|
+
};
|
|
13225
|
+
}
|
|
13226
|
+
/**
|
|
13227
|
+
* Enter replay-anchor selection: the cursor shadows everything a click
|
|
13228
|
+
* would remove; clicking commits that bucket as the replay head. Returns
|
|
13229
|
+
* false (with a warning) when the plan lacks bar_replay or the backend
|
|
13230
|
+
* has no selection surface.
|
|
13231
|
+
*/
|
|
13232
|
+
replayEnterSelection() {
|
|
13233
|
+
this._assertAlive();
|
|
13234
|
+
if (!canUseBarReplay()) {
|
|
13235
|
+
console.warn("[ForgeCharts] Bar replay (bar_replay) is not enabled on the active plan.");
|
|
13236
|
+
return false;
|
|
13237
|
+
}
|
|
13238
|
+
if (!this._core.setReplaySelect) {
|
|
13239
|
+
console.warn("[ForgeCharts] Bar replay requires the Pixi render backend.");
|
|
13240
|
+
return false;
|
|
13241
|
+
}
|
|
13242
|
+
this._replayStopTimer();
|
|
13243
|
+
this._replay.selecting = true;
|
|
13244
|
+
this._replay.playing = false;
|
|
13245
|
+
this._core.setReplaySelect({
|
|
13246
|
+
onHover: () => {
|
|
13247
|
+
},
|
|
13248
|
+
onCommit: (time) => this._replayCommit(time)
|
|
13249
|
+
});
|
|
13250
|
+
this._emitReplayState();
|
|
13251
|
+
return true;
|
|
13252
|
+
}
|
|
13253
|
+
/** Leave selection without committing (existing replay, if any, survives). */
|
|
13254
|
+
replayCancelSelection() {
|
|
13255
|
+
this._assertAlive();
|
|
13256
|
+
if (!this._replay.selecting) return;
|
|
13257
|
+
this._replay.selecting = false;
|
|
13258
|
+
this._core.setReplaySelect?.(null);
|
|
13259
|
+
this._emitReplayState();
|
|
13260
|
+
}
|
|
13261
|
+
_replayCommit(time) {
|
|
13262
|
+
this._replay.selecting = false;
|
|
13263
|
+
this._core.setReplaySelect?.(null);
|
|
13264
|
+
this._series.setCutoffTime(time);
|
|
13265
|
+
this._replay.active = true;
|
|
13266
|
+
this._replay.playing = false;
|
|
13267
|
+
this._core.centerOnTime?.(time);
|
|
13268
|
+
this._core.markDirty();
|
|
13269
|
+
this._emitReplayState();
|
|
13270
|
+
}
|
|
13271
|
+
replayPlay() {
|
|
13272
|
+
this._assertAlive();
|
|
13273
|
+
if (!this._replay.active || this._replay.playing) return;
|
|
13274
|
+
this._replay.playing = true;
|
|
13275
|
+
this._replayStartTimer();
|
|
13276
|
+
this._emitReplayState();
|
|
13277
|
+
}
|
|
13278
|
+
replayPause() {
|
|
13279
|
+
this._assertAlive();
|
|
13280
|
+
if (!this._replay.playing) return;
|
|
13281
|
+
this._replay.playing = false;
|
|
13282
|
+
this._replayStopTimer();
|
|
13283
|
+
this._emitReplayState();
|
|
13284
|
+
}
|
|
13285
|
+
/** Advance the replay head n bars. Pauses at the end of the tape. */
|
|
13286
|
+
replayStepForward(n = 1) {
|
|
13287
|
+
this._assertAlive();
|
|
13288
|
+
if (!this._replay.active) return;
|
|
13289
|
+
const full = this._series.fullData();
|
|
13290
|
+
const shown = this._series.data().length;
|
|
13291
|
+
const nextIdx = Math.min(shown + n, full.length) - 1;
|
|
13292
|
+
if (nextIdx < shown) {
|
|
13293
|
+
this.replayPause();
|
|
13294
|
+
return;
|
|
13295
|
+
}
|
|
13296
|
+
this._series.setCutoffTime(full[nextIdx].time);
|
|
13297
|
+
this._core.markDirty();
|
|
13298
|
+
if (nextIdx >= full.length - 1) this.replayPause();
|
|
13299
|
+
this._emitReplayState();
|
|
13300
|
+
}
|
|
13301
|
+
/** Rewind the replay head n bars back in time (default 10). */
|
|
13302
|
+
replayRewind(n = 10) {
|
|
13303
|
+
this._assertAlive();
|
|
13304
|
+
if (!this._replay.active) return;
|
|
13305
|
+
const full = this._series.fullData();
|
|
13306
|
+
const shown = this._series.data().length;
|
|
13307
|
+
const idx = Math.max(shown - 1 - n, 0);
|
|
13308
|
+
if (full.length === 0) return;
|
|
13309
|
+
this._series.setCutoffTime(full[idx].time);
|
|
13310
|
+
this._core.markDirty();
|
|
13311
|
+
this._emitReplayState();
|
|
13312
|
+
}
|
|
13313
|
+
/** Set an exact playback speed (nearest catalogued value). */
|
|
13314
|
+
replaySetSpeed(speed) {
|
|
13315
|
+
this._assertAlive();
|
|
13316
|
+
let best = 0;
|
|
13317
|
+
for (let i = 0; i < _ForgeCharts.REPLAY_SPEEDS.length; i++) {
|
|
13318
|
+
if (Math.abs(_ForgeCharts.REPLAY_SPEEDS[i] - speed) < Math.abs(_ForgeCharts.REPLAY_SPEEDS[best] - speed)) best = i;
|
|
13319
|
+
}
|
|
13320
|
+
this._replay.speedIdx = best;
|
|
13321
|
+
if (this._replay.playing) this._replayStartTimer();
|
|
13322
|
+
this._emitReplayState();
|
|
13323
|
+
}
|
|
13324
|
+
/**
|
|
13325
|
+
* Restore a persisted replay session (browser refresh mid-replay). Applies
|
|
13326
|
+
* the same gate as entering selection; the cutoff simply lands where it
|
|
13327
|
+
* was, paused, with the anchor centered. A cutoff at or beyond the tape's
|
|
13328
|
+
* head means the replay had effectively finished — nothing is restored.
|
|
13329
|
+
*/
|
|
13330
|
+
replayRestore(cutoffTime, speed) {
|
|
13331
|
+
this._assertAlive();
|
|
13332
|
+
if (!canUseBarReplay()) return false;
|
|
13333
|
+
const full = this._series.fullData();
|
|
13334
|
+
const last = full[full.length - 1];
|
|
13335
|
+
if (!last || cutoffTime >= last.time) return false;
|
|
13336
|
+
if (speed !== void 0) this.replaySetSpeed(speed);
|
|
13337
|
+
this._replayCommit(cutoffTime);
|
|
13338
|
+
return true;
|
|
13339
|
+
}
|
|
13340
|
+
/** Cycle to the next playback speed; restarts the timer when playing. */
|
|
13341
|
+
replayCycleSpeed() {
|
|
13342
|
+
this._assertAlive();
|
|
13343
|
+
this._replay.speedIdx = (this._replay.speedIdx + 1) % _ForgeCharts.REPLAY_SPEEDS.length;
|
|
13344
|
+
if (this._replay.playing) this._replayStartTimer();
|
|
13345
|
+
this._emitReplayState();
|
|
13346
|
+
return _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx];
|
|
13347
|
+
}
|
|
13348
|
+
/** Exit replay entirely: the full tape (live head included) returns. */
|
|
13349
|
+
replayExit() {
|
|
13350
|
+
this._assertAlive();
|
|
13351
|
+
this._replayStopTimer();
|
|
13352
|
+
this._replay.selecting = false;
|
|
13353
|
+
this._replay.active = false;
|
|
13354
|
+
this._replay.playing = false;
|
|
13355
|
+
this._core.setReplaySelect?.(null);
|
|
13356
|
+
this._series.setCutoffTime(null);
|
|
13357
|
+
this._core.markDirty();
|
|
13358
|
+
this._core.scrollToEnd();
|
|
13359
|
+
this._emitReplayState();
|
|
13360
|
+
}
|
|
13361
|
+
_replayStartTimer() {
|
|
13362
|
+
this._replayStopTimer();
|
|
13363
|
+
const speed = _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx];
|
|
13364
|
+
this._replay.timer = setInterval(() => this.replayStepForward(1), Math.max(1e3 / speed, 16));
|
|
13365
|
+
}
|
|
13366
|
+
_replayStopTimer() {
|
|
13367
|
+
if (this._replay.timer) clearInterval(this._replay.timer);
|
|
13368
|
+
this._replay.timer = null;
|
|
13369
|
+
}
|
|
13037
13370
|
// ─── Datafeed ─────────────────────────────────────────────────────────────────
|
|
13038
13371
|
_buildConnector(datafeed) {
|
|
13039
13372
|
return new DatafeedConnector(datafeed, this._series, {
|
|
@@ -13090,7 +13423,7 @@ function createChart(config) {
|
|
|
13090
13423
|
if (!config.container) {
|
|
13091
13424
|
throw new Error("[ForgeCharts] createChart() requires a valid container element.");
|
|
13092
13425
|
}
|
|
13093
|
-
return new
|
|
13426
|
+
return new ForgeCharts(config);
|
|
13094
13427
|
}
|
|
13095
13428
|
|
|
13096
13429
|
// src/api/ReferenceAPI.ts
|
|
@@ -18645,10 +18978,7 @@ function useHostLicense(apiUrl, getAuthToken) {
|
|
|
18645
18978
|
function useUserPackage(apiUrl, getAuthToken) {
|
|
18646
18979
|
useEffect(() => {
|
|
18647
18980
|
const resolver3 = ChartRuntimeResolver.getInstance();
|
|
18648
|
-
if (!apiUrl || !getAuthToken)
|
|
18649
|
-
resolver3.setUserPackageFeatures(null);
|
|
18650
|
-
return;
|
|
18651
|
-
}
|
|
18981
|
+
if (!apiUrl || !getAuthToken) return;
|
|
18652
18982
|
let cancelled = false;
|
|
18653
18983
|
void (async () => {
|
|
18654
18984
|
try {
|
|
@@ -23244,6 +23574,8 @@ var ChartCanvas = forwardRef(
|
|
|
23244
23574
|
onPointerToolChange,
|
|
23245
23575
|
initialPointerTool,
|
|
23246
23576
|
initialSeriesType,
|
|
23577
|
+
initialReplay,
|
|
23578
|
+
onReplayStateChange,
|
|
23247
23579
|
initialMagnetMode,
|
|
23248
23580
|
onMagnetModeChange,
|
|
23249
23581
|
drawingFavorites: drawingFavoritesProp,
|
|
@@ -23363,6 +23695,14 @@ var ChartCanvas = forwardRef(
|
|
|
23363
23695
|
},
|
|
23364
23696
|
addIndicator: (config) => chartRef.current?.addIndicator(config) ?? null,
|
|
23365
23697
|
setSeriesType: (type) => chartRef.current?.setSeriesType(type),
|
|
23698
|
+
toggleReplay: () => {
|
|
23699
|
+
const chart = chartRef.current;
|
|
23700
|
+
if (!chart) return;
|
|
23701
|
+
const st = chart.replayState();
|
|
23702
|
+
if (st.selecting) chart.replayCancelSelection();
|
|
23703
|
+
else if (st.active) chart.replayExit();
|
|
23704
|
+
else chart.replayEnterSelection();
|
|
23705
|
+
},
|
|
23366
23706
|
removeIndicator: (id) => chartRef.current?.removeIndicator(id),
|
|
23367
23707
|
moveIndicatorToOverlay: (id) => chartRef.current?.moveIndicatorToOverlay(id),
|
|
23368
23708
|
moveIndicatorToPane: (id, targetPaneId) => chartRef.current?.moveIndicatorToPane(id, targetPaneId),
|
|
@@ -23410,7 +23750,7 @@ var ChartCanvas = forwardRef(
|
|
|
23410
23750
|
useEffect(() => {
|
|
23411
23751
|
const container = priceRef.current;
|
|
23412
23752
|
if (!container) return;
|
|
23413
|
-
const chart = new
|
|
23753
|
+
const chart = new ForgeCharts({
|
|
23414
23754
|
container,
|
|
23415
23755
|
symbol,
|
|
23416
23756
|
interval: timeframe,
|
|
@@ -23424,6 +23764,10 @@ var ChartCanvas = forwardRef(
|
|
|
23424
23764
|
for (const config of initialIndicators) {
|
|
23425
23765
|
chart.addIndicator(config);
|
|
23426
23766
|
}
|
|
23767
|
+
chart.on("replayStateChanged", (s) => {
|
|
23768
|
+
setReplayState(s.selecting || s.active ? s : null);
|
|
23769
|
+
onReplayStateChangeRef.current?.(s);
|
|
23770
|
+
});
|
|
23427
23771
|
transformRef.current = chart.getTransform();
|
|
23428
23772
|
const syncChartState = () => {
|
|
23429
23773
|
setBars([...chart.getBars()]);
|
|
@@ -24383,6 +24727,37 @@ var ChartCanvas = forwardRef(
|
|
|
24383
24727
|
selectPointerToolRef.current = handleToolSelect;
|
|
24384
24728
|
const initialPointerAppliedRef = useRef(false);
|
|
24385
24729
|
const initialSeriesAppliedRef = useRef(false);
|
|
24730
|
+
const [replayState, setReplayState] = useState(null);
|
|
24731
|
+
const [replayBarOffset, setReplayBarOffset] = useState(0);
|
|
24732
|
+
const replayDragRef = useRef(null);
|
|
24733
|
+
const onReplayStateChangeRef = useRef(onReplayStateChange);
|
|
24734
|
+
useEffect(() => {
|
|
24735
|
+
onReplayStateChangeRef.current = onReplayStateChange;
|
|
24736
|
+
}, [onReplayStateChange]);
|
|
24737
|
+
const initialReplayAppliedRef = useRef(false);
|
|
24738
|
+
useEffect(() => {
|
|
24739
|
+
if (initialReplayAppliedRef.current || !initialReplay || bars.length === 0) return;
|
|
24740
|
+
initialReplayAppliedRef.current = true;
|
|
24741
|
+
chartRef.current?.replayRestore(initialReplay.cutoffTime, initialReplay.speed);
|
|
24742
|
+
}, [initialReplay, bars]);
|
|
24743
|
+
useEffect(() => {
|
|
24744
|
+
const move = (e) => {
|
|
24745
|
+
const d = replayDragRef.current;
|
|
24746
|
+
if (!d) return;
|
|
24747
|
+
const host = outerRef.current;
|
|
24748
|
+
const max = host ? Math.max(0, host.clientHeight - 80) : 400;
|
|
24749
|
+
setReplayBarOffset(Math.min(max, Math.max(0, d.startOffset + (d.startY - e.clientY))));
|
|
24750
|
+
};
|
|
24751
|
+
const up = () => {
|
|
24752
|
+
replayDragRef.current = null;
|
|
24753
|
+
};
|
|
24754
|
+
window.addEventListener("pointermove", move);
|
|
24755
|
+
window.addEventListener("pointerup", up);
|
|
24756
|
+
return () => {
|
|
24757
|
+
window.removeEventListener("pointermove", move);
|
|
24758
|
+
window.removeEventListener("pointerup", up);
|
|
24759
|
+
};
|
|
24760
|
+
}, []);
|
|
24386
24761
|
useEffect(() => {
|
|
24387
24762
|
if (!initialSeriesAppliedRef.current && initialSeriesType && chartRef.current) {
|
|
24388
24763
|
initialSeriesAppliedRef.current = true;
|
|
@@ -24391,7 +24766,7 @@ var ChartCanvas = forwardRef(
|
|
|
24391
24766
|
if (initialPointerAppliedRef.current || !initialPointerTool) return;
|
|
24392
24767
|
initialPointerAppliedRef.current = true;
|
|
24393
24768
|
selectPointerToolRef.current(initialPointerTool);
|
|
24394
|
-
}, [initialPointerTool]);
|
|
24769
|
+
}, [initialPointerTool, initialSeriesType]);
|
|
24395
24770
|
const handleMagnetModeChange = useCallback((mode) => {
|
|
24396
24771
|
setMagnetMode(mode);
|
|
24397
24772
|
chartRef.current?.setMagnetMode(mode);
|
|
@@ -24487,6 +24862,124 @@ var ChartCanvas = forwardRef(
|
|
|
24487
24862
|
crosshairXRef.current = null;
|
|
24488
24863
|
},
|
|
24489
24864
|
children: [
|
|
24865
|
+
replayState && (() => {
|
|
24866
|
+
const dark = effectiveTheme !== "light";
|
|
24867
|
+
const bg = dark ? "#000000" : "#ffffff";
|
|
24868
|
+
const fg = dark ? "#ffffff" : "#000000";
|
|
24869
|
+
const line = dark ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.22)";
|
|
24870
|
+
const btn = {
|
|
24871
|
+
background: "transparent",
|
|
24872
|
+
border: "none",
|
|
24873
|
+
color: fg,
|
|
24874
|
+
cursor: "pointer",
|
|
24875
|
+
padding: "6px 10px",
|
|
24876
|
+
borderRadius: 6,
|
|
24877
|
+
fontSize: 12,
|
|
24878
|
+
display: "inline-flex",
|
|
24879
|
+
alignItems: "center",
|
|
24880
|
+
gap: 5,
|
|
24881
|
+
lineHeight: 1
|
|
24882
|
+
};
|
|
24883
|
+
const sep = /* @__PURE__ */ jsx("span", { style: { width: 1, alignSelf: "stretch", background: line, margin: "6px 4px" } });
|
|
24884
|
+
const call = (fn) => () => {
|
|
24885
|
+
if (chartRef.current) fn(chartRef.current);
|
|
24886
|
+
};
|
|
24887
|
+
return /* @__PURE__ */ jsxs("div", { style: {
|
|
24888
|
+
position: "absolute",
|
|
24889
|
+
left: 0,
|
|
24890
|
+
right: 0,
|
|
24891
|
+
bottom: replayBarOffset,
|
|
24892
|
+
zIndex: 8,
|
|
24893
|
+
display: "flex",
|
|
24894
|
+
alignItems: "center",
|
|
24895
|
+
gap: 2,
|
|
24896
|
+
height: 38,
|
|
24897
|
+
padding: "0 8px",
|
|
24898
|
+
boxSizing: "border-box",
|
|
24899
|
+
background: bg,
|
|
24900
|
+
color: fg,
|
|
24901
|
+
borderTop: `1px solid ${line}`,
|
|
24902
|
+
borderBottom: `1px solid ${line}`,
|
|
24903
|
+
userSelect: "none"
|
|
24904
|
+
}, children: [
|
|
24905
|
+
/* @__PURE__ */ jsx(
|
|
24906
|
+
"span",
|
|
24907
|
+
{
|
|
24908
|
+
title: "Drag to move",
|
|
24909
|
+
onPointerDown: (e) => {
|
|
24910
|
+
e.preventDefault();
|
|
24911
|
+
replayDragRef.current = { startY: e.clientY, startOffset: replayBarOffset };
|
|
24912
|
+
},
|
|
24913
|
+
style: { cursor: "ns-resize", padding: "6px 6px", color: fg, opacity: 0.55, fontSize: 12, letterSpacing: 1 },
|
|
24914
|
+
children: "\u2059\u2059"
|
|
24915
|
+
}
|
|
24916
|
+
),
|
|
24917
|
+
sep,
|
|
24918
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 600, letterSpacing: 0.3, padding: "0 6px" }, children: "Replay" }),
|
|
24919
|
+
sep,
|
|
24920
|
+
replayState.selecting ? /* @__PURE__ */ jsx("span", { style: { fontSize: 12, padding: "0 8px", opacity: 0.85 }, children: "Click a bar to start replay from there" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24921
|
+
/* @__PURE__ */ jsx(
|
|
24922
|
+
"button",
|
|
24923
|
+
{
|
|
24924
|
+
style: btn,
|
|
24925
|
+
title: "Pick a new starting bar",
|
|
24926
|
+
onClick: call((c) => c.replayEnterSelection()),
|
|
24927
|
+
children: "\u2506\u2190 Select bar"
|
|
24928
|
+
}
|
|
24929
|
+
),
|
|
24930
|
+
sep,
|
|
24931
|
+
/* @__PURE__ */ jsx(
|
|
24932
|
+
"button",
|
|
24933
|
+
{
|
|
24934
|
+
style: btn,
|
|
24935
|
+
title: "Rewind 10 bars",
|
|
24936
|
+
onClick: call((c) => c.replayRewind(10)),
|
|
24937
|
+
children: "\u23EA"
|
|
24938
|
+
}
|
|
24939
|
+
),
|
|
24940
|
+
/* @__PURE__ */ jsx(
|
|
24941
|
+
"button",
|
|
24942
|
+
{
|
|
24943
|
+
style: btn,
|
|
24944
|
+
title: replayState.playing ? "Pause" : "Play",
|
|
24945
|
+
onClick: call((c) => replayState.playing ? c.replayPause() : c.replayPlay()),
|
|
24946
|
+
children: replayState.playing ? "\u23F8" : "\u25B6"
|
|
24947
|
+
}
|
|
24948
|
+
),
|
|
24949
|
+
/* @__PURE__ */ jsx(
|
|
24950
|
+
"button",
|
|
24951
|
+
{
|
|
24952
|
+
style: btn,
|
|
24953
|
+
title: "Forward one bar",
|
|
24954
|
+
onClick: call((c) => c.replayStepForward(1)),
|
|
24955
|
+
children: "\u23E9"
|
|
24956
|
+
}
|
|
24957
|
+
),
|
|
24958
|
+
/* @__PURE__ */ jsxs(
|
|
24959
|
+
"button",
|
|
24960
|
+
{
|
|
24961
|
+
style: { ...btn, fontVariantNumeric: "tabular-nums", minWidth: 44, justifyContent: "center" },
|
|
24962
|
+
title: "Playback speed (0.5\u201320 bars per second)",
|
|
24963
|
+
onClick: call((c) => c.replayCycleSpeed()),
|
|
24964
|
+
children: [
|
|
24965
|
+
replayState.speed,
|
|
24966
|
+
"x"
|
|
24967
|
+
]
|
|
24968
|
+
}
|
|
24969
|
+
)
|
|
24970
|
+
] }),
|
|
24971
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
|
|
24972
|
+
/* @__PURE__ */ jsx(
|
|
24973
|
+
"button",
|
|
24974
|
+
{
|
|
24975
|
+
style: btn,
|
|
24976
|
+
title: replayState.selecting ? "Cancel selection" : "Exit replay",
|
|
24977
|
+
onClick: call((c) => replayState.selecting ? c.replayCancelSelection() : c.replayExit()),
|
|
24978
|
+
children: "\u2715"
|
|
24979
|
+
}
|
|
24980
|
+
)
|
|
24981
|
+
] });
|
|
24982
|
+
})(),
|
|
24490
24983
|
/* @__PURE__ */ jsx(
|
|
24491
24984
|
"div",
|
|
24492
24985
|
{
|
|
@@ -24574,7 +25067,7 @@ var ChartCanvas = forwardRef(
|
|
|
24574
25067
|
symbol,
|
|
24575
25068
|
timeframe,
|
|
24576
25069
|
bars,
|
|
24577
|
-
theme,
|
|
25070
|
+
theme: effectiveTheme,
|
|
24578
25071
|
indicators,
|
|
24579
25072
|
overlayColors: OVERLAY_COLORS,
|
|
24580
25073
|
onRemove: handleRemoveIndicator,
|
|
@@ -25630,7 +26123,7 @@ var demonstrationTool = {
|
|
|
25630
26123
|
};
|
|
25631
26124
|
|
|
25632
26125
|
// src/version.ts
|
|
25633
|
-
var FORGECHARTS_VERSION = "1.5.
|
|
26126
|
+
var FORGECHARTS_VERSION = "1.5.84" ;
|
|
25634
26127
|
|
|
25635
26128
|
// src/compatibility.ts
|
|
25636
26129
|
var MIN_KIT_API = 1;
|
|
@@ -25687,6 +26180,6 @@ function checkKitCompatibility(kit) {
|
|
|
25687
26180
|
return { ...base, level: "ok", message: `SDK ${sdkVersion} matches the Kit.` };
|
|
25688
26181
|
}
|
|
25689
26182
|
|
|
25690
|
-
export { CROSSHAIR_LABEL, CROSSHAIR_STYLE, CURRENT_SCHEMA_VERSION, CURSOR_LABEL, CURSOR_STYLE, CandleEngine, Chart, ChartRuntimeResolver, CoordTransform, Crosshair, DEFAULT_SYNC_OPTIONS, DEMONSTRATION_COLOR, DEMONSTRATION_FILL, DEMONSTRATION_LABEL, DEMONSTRATION_RADIUS, DEMONSTRATION_STROKE, DEMONSTRATION_STYLE, DOT_COLOR, DOT_LABEL, DOT_RADIUS, DOT_STYLE, DatafeedConnector, DirtyFlags, ForgeScriptIndicator, ForgeScriptRuntime, Series2 as ForgeScriptSeries, GridChartContainer, GridSyncProvider, IndicatorDAG, InteractionManager, KIT_FEATURE_TO_CAPABILITY, LayerName, LayoutTemplateSelector, LicenseManager, MAX_KIT_API, MIN_KIT_API, ManagedTradingController, PACKAGE_GATED_CAPABILITIES, PRODUCT_TIERS, PaneManager, PixiBenchmark, PixiChart, PixiLayerManager, PriceScale, ReferenceAPI, Series, TChart, TimeScale, TradingOverlayStore, UNMAPPED_KIT_FEATURES, UnmanagedIngestion, assertCanPlaceOrders, assertCanUseBrackets, assertCanUseDraggableOrders, assertCanUseManagedTrading, assertManagedMode, canPlaceBrackets, canPlaceOrders, canRenderBracketControls, canRenderBuySellButtons, canRenderCandles, canRenderDrawings, canRenderExternalOverlayOnlyMode, canRenderFills, canRenderIndicators, canRenderManagedTradingControls, canRenderOrderEntry, canRenderOrderModificationControls, canRenderOrderTicket, canRenderOverlays, canRenderPositions, canUseAiAgent, canUseAlerts, canUseBarReplay, canUseBracketOrders, canUseChartTypes, canUseCustomIndicators, canUseCustomTimeframes, canUseDataExport, canUseDraggable, canUseDraggableOrders, canUseDrawingTools, canUseExtendedDrawings, canUseExternalIngestion, canUseForgeScript, canUseHistoricalData, canUseIndicators, canUseManagedTrading, canUseManagedTradingHook, canUseMultiChartLayout, canUseMultiPane, canUseMultipleProviders, canUseMultipleWorkspaces, canUseOrderEntry, canUsePositionsOverlay, canUseRealtimeData, canUseSavedLayouts, canUseTrailingStops, canUseWatchlists, checkKitCompatibility, clearTelemetryListeners, computeEMA, computeEMAFromSeries, computeMACD, computeRSI, computeSMA, computeSMAFromSeries, computeVolume, computeWMAFromSeries, createChart, crosshairTool, cursorTool, demonstrationTool, detectLanguage, detectLanguageWithFallback, dotTool, evaluateSaveGate, exchangeNow, extractField, getBucketStart2 as getBucketStart, getCapabilities, getDefaultCapabilities, getDefaultStyle, getGridTemplate, getGroupedTemplates, getMissingBarCount, getStyleSlots, hasFeature, initServerClock, isManagedCapable, isManagedMode, isUnmanagedMode, isValidCombination, lineStyleToDash, mergeBars, migrateLegacyPayload, onConversionEvent, packageAllows, resolveStyle, runSandbox, serverClockOffset, serverNow, timeframeToMs2 as timeframeToMs, toCapabilityFlags, useGridSync, validateForgeScript, validateLicensePolicy };
|
|
26183
|
+
export { CROSSHAIR_LABEL, CROSSHAIR_STYLE, CURRENT_SCHEMA_VERSION, CURSOR_LABEL, CURSOR_STYLE, CandleEngine, Chart, ChartRuntimeResolver, CoordTransform, Crosshair, DEFAULT_SYNC_OPTIONS, DEMONSTRATION_COLOR, DEMONSTRATION_FILL, DEMONSTRATION_LABEL, DEMONSTRATION_RADIUS, DEMONSTRATION_STROKE, DEMONSTRATION_STYLE, DOT_COLOR, DOT_LABEL, DOT_RADIUS, DOT_STYLE, DatafeedConnector, DirtyFlags, ForgeCharts, ForgeScriptIndicator, ForgeScriptRuntime, Series2 as ForgeScriptSeries, GridChartContainer, GridSyncProvider, IndicatorDAG, InteractionManager, KIT_FEATURE_TO_CAPABILITY, LayerName, LayoutTemplateSelector, LicenseManager, MAX_KIT_API, MIN_KIT_API, ManagedTradingController, PACKAGE_GATED_CAPABILITIES, PRODUCT_TIERS, PaneManager, PixiBenchmark, PixiChart, PixiLayerManager, PriceScale, ReferenceAPI, Series, ForgeCharts as TChart, TimeScale, TradingOverlayStore, UNMAPPED_KIT_FEATURES, UnmanagedIngestion, assertCanPlaceOrders, assertCanUseBrackets, assertCanUseDraggableOrders, assertCanUseManagedTrading, assertManagedMode, canPlaceBrackets, canPlaceOrders, canRenderBracketControls, canRenderBuySellButtons, canRenderCandles, canRenderDrawings, canRenderExternalOverlayOnlyMode, canRenderFills, canRenderIndicators, canRenderManagedTradingControls, canRenderOrderEntry, canRenderOrderModificationControls, canRenderOrderTicket, canRenderOverlays, canRenderPositions, canUseAiAgent, canUseAlerts, canUseBarReplay, canUseBracketOrders, canUseChartTypes, canUseCustomIndicators, canUseCustomTimeframes, canUseDataExport, canUseDraggable, canUseDraggableOrders, canUseDrawingTools, canUseExtendedDrawings, canUseExternalIngestion, canUseForgeScript, canUseHistoricalData, canUseIndicators, canUseManagedTrading, canUseManagedTradingHook, canUseMultiChartLayout, canUseMultiPane, canUseMultipleProviders, canUseMultipleWorkspaces, canUseOrderEntry, canUsePositionsOverlay, canUseRealtimeData, canUseSavedLayouts, canUseTrailingStops, canUseWatchlists, checkKitCompatibility, clearTelemetryListeners, computeEMA, computeEMAFromSeries, computeMACD, computeRSI, computeSMA, computeSMAFromSeries, computeVolume, computeWMAFromSeries, createChart, crosshairTool, cursorTool, demonstrationTool, detectLanguage, detectLanguageWithFallback, dotTool, evaluateSaveGate, exchangeNow, extractField, getBucketStart2 as getBucketStart, getCapabilities, getDefaultCapabilities, getDefaultStyle, getGridTemplate, getGroupedTemplates, getMissingBarCount, getStyleSlots, hasFeature, initServerClock, isManagedCapable, isManagedMode, isUnmanagedMode, isValidCombination, lineStyleToDash, mergeBars, migrateLegacyPayload, onConversionEvent, packageAllows, resolveStyle, runSandbox, serverClockOffset, serverNow, timeframeToMs2 as timeframeToMs, toCapabilityFlags, useGridSync, validateForgeScript, validateLicensePolicy };
|
|
25691
26184
|
//# sourceMappingURL=internal.js.map
|
|
25692
26185
|
//# sourceMappingURL=internal.js.map
|