@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/index.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. */
|
|
@@ -6104,9 +6141,17 @@ var PixiCandlestickRenderer = class {
|
|
|
6104
6141
|
this._gfx = new Graphics();
|
|
6105
6142
|
layer.addChild(this._gfx);
|
|
6106
6143
|
}
|
|
6144
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
6145
|
+
clear() {
|
|
6146
|
+
this._gfx.clear();
|
|
6147
|
+
}
|
|
6107
6148
|
draw(bars, transform, opts) {
|
|
6108
6149
|
const gfx = this._gfx;
|
|
6109
6150
|
gfx.clear();
|
|
6151
|
+
if (opts?.type === "bar") {
|
|
6152
|
+
this._drawBars(bars, transform, opts);
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6110
6155
|
if (bars.length === 0) return;
|
|
6111
6156
|
const { plotWidth: pw, plotHeight: ph } = transform;
|
|
6112
6157
|
const upColor = hexToNum(opts && "upColor" in opts ? opts.upColor : void 0, UP_COLOR);
|
|
@@ -6237,6 +6282,36 @@ var PixiCandlestickRenderer = class {
|
|
|
6237
6282
|
/**
|
|
6238
6283
|
* Converts OHLCV bars to Heikin-Ashi values before drawing.
|
|
6239
6284
|
*/
|
|
6285
|
+
/** Classic OHLC bars: high-low spine, open tick left, close tick right. */
|
|
6286
|
+
_drawBars(bars, transform, opts) {
|
|
6287
|
+
const gfx = this._gfx;
|
|
6288
|
+
if (bars.length === 0) return;
|
|
6289
|
+
const upColor = hexToNum(opts && "upColor" in opts ? opts.upColor : void 0, UP_COLOR);
|
|
6290
|
+
const downColor = hexToNum(opts && "downColor" in opts ? opts.downColor : void 0, DOWN_COLOR);
|
|
6291
|
+
const { plotWidth: pw } = transform;
|
|
6292
|
+
let barPitch = pw / Math.max(1, bars.length);
|
|
6293
|
+
if (bars.length >= 2) {
|
|
6294
|
+
const dx = Math.abs(transform.timeToX(bars[1].time) - transform.timeToX(bars[0].time));
|
|
6295
|
+
if (dx > 0) barPitch = dx;
|
|
6296
|
+
}
|
|
6297
|
+
const tick = Math.max(1.5, Math.min(barPitch * 0.35, 6));
|
|
6298
|
+
const lineW = barPitch < 3 ? 1 : 1.5;
|
|
6299
|
+
for (const bar of bars) {
|
|
6300
|
+
const x = transform.timeToX(bar.time);
|
|
6301
|
+
if (x < -barPitch || x > pw + barPitch) continue;
|
|
6302
|
+
const yHigh = transform.priceToY(bar.high);
|
|
6303
|
+
const yLow = transform.priceToY(bar.low);
|
|
6304
|
+
const yOpen = transform.priceToY(bar.open);
|
|
6305
|
+
const yClose = transform.priceToY(bar.close);
|
|
6306
|
+
const color = bar.close >= bar.open ? upColor : downColor;
|
|
6307
|
+
gfx.moveTo(x, yHigh).lineTo(x, yLow);
|
|
6308
|
+
if (barPitch >= 3) {
|
|
6309
|
+
gfx.moveTo(x - tick, yOpen).lineTo(x, yOpen);
|
|
6310
|
+
gfx.moveTo(x, yClose).lineTo(x + tick, yClose);
|
|
6311
|
+
}
|
|
6312
|
+
gfx.stroke({ color, width: lineW });
|
|
6313
|
+
}
|
|
6314
|
+
}
|
|
6240
6315
|
drawHeikinAshi(bars, transform, opts) {
|
|
6241
6316
|
const first = bars[0];
|
|
6242
6317
|
const last = bars[bars.length - 1];
|
|
@@ -7559,6 +7634,10 @@ var PixiLineRenderer = class {
|
|
|
7559
7634
|
this._gradientCache = null;
|
|
7560
7635
|
this._gfx.destroy(true);
|
|
7561
7636
|
}
|
|
7637
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
7638
|
+
clear() {
|
|
7639
|
+
this._gfx.clear();
|
|
7640
|
+
}
|
|
7562
7641
|
draw(bars, transform, options) {
|
|
7563
7642
|
const gfx = this._gfx;
|
|
7564
7643
|
gfx.clear();
|
|
@@ -7653,6 +7732,10 @@ var PixiHistogramRenderer = class {
|
|
|
7653
7732
|
destroy() {
|
|
7654
7733
|
this._gfx.destroy(true);
|
|
7655
7734
|
}
|
|
7735
|
+
/** Clear this renderer's graphics — used when another style takes over. */
|
|
7736
|
+
clear() {
|
|
7737
|
+
this._gfx.clear();
|
|
7738
|
+
}
|
|
7656
7739
|
draw(bars, transform) {
|
|
7657
7740
|
const gfx = this._gfx;
|
|
7658
7741
|
gfx.clear();
|
|
@@ -8632,7 +8715,7 @@ var PixiChart = class {
|
|
|
8632
8715
|
/** Fired when an EXISTING drawing is modified via drag (handle or body move). */
|
|
8633
8716
|
onDrawingEdited;
|
|
8634
8717
|
_drawingEditDirty = false;
|
|
8635
|
-
/** Ctrl+Z / Ctrl+Y — drawing history is owned by
|
|
8718
|
+
/** Ctrl+Z / Ctrl+Y — drawing history is owned by ForgeCharts. */
|
|
8636
8719
|
onUndoRequest;
|
|
8637
8720
|
onRedoRequest;
|
|
8638
8721
|
/** Called whenever a drawing is deleted. */
|
|
@@ -8647,7 +8730,7 @@ var PixiChart = class {
|
|
|
8647
8730
|
onDrawingContextMenu;
|
|
8648
8731
|
/** Called when the user double-clicks a drawing. */
|
|
8649
8732
|
onDrawingDoubleClick;
|
|
8650
|
-
/** Called after every pan/zoom so
|
|
8733
|
+
/** Called after every pan/zoom so ForgeCharts can trigger lazy history loading. */
|
|
8651
8734
|
onViewportChanged;
|
|
8652
8735
|
constructor(container, options = {}) {
|
|
8653
8736
|
this._container = container;
|
|
@@ -8754,6 +8837,12 @@ var PixiChart = class {
|
|
|
8754
8837
|
this.onViewportChanged?.();
|
|
8755
8838
|
},
|
|
8756
8839
|
onCrosshairMove: (x, y) => {
|
|
8840
|
+
if (this._replaySelect) {
|
|
8841
|
+
const t = this._cursorBucketTime(x);
|
|
8842
|
+
this._replayHoverTime = t;
|
|
8843
|
+
this._replaySelect.onHover(t);
|
|
8844
|
+
this._drawReplayDim(x);
|
|
8845
|
+
}
|
|
8757
8846
|
if (!this._crosshairEnabled) return;
|
|
8758
8847
|
if (this._magnetMode === "off") {
|
|
8759
8848
|
this._crosshairRenderer.update(x, y, this._cursorBucketTime(x));
|
|
@@ -9043,7 +9132,7 @@ var PixiChart = class {
|
|
|
9043
9132
|
}).catch(() => {
|
|
9044
9133
|
});
|
|
9045
9134
|
}
|
|
9046
|
-
// ─── Drawing objects (used by PixiChart directly;
|
|
9135
|
+
// ─── Drawing objects (used by PixiChart directly; ForgeCharts uses DrawingManager) ─
|
|
9047
9136
|
/** @internal Used by PixiChart when DrawingManager pushes an update. */
|
|
9048
9137
|
setDrawings(drawings) {
|
|
9049
9138
|
this._drawings = [...drawings];
|
|
@@ -9052,6 +9141,47 @@ var PixiChart = class {
|
|
|
9052
9141
|
// ─── Rendering ───────────────────────────────────────────────────────────────
|
|
9053
9142
|
/** Styles whose renderer has already logged a failure this session. */
|
|
9054
9143
|
_renderErrorLogged = /* @__PURE__ */ new Set();
|
|
9144
|
+
// ── Bar-replay anchor selection ─────────────────────────────────────────
|
|
9145
|
+
_replaySelect = null;
|
|
9146
|
+
_replayHoverTime = null;
|
|
9147
|
+
_replayDimGfx = null;
|
|
9148
|
+
_replayClickHandler = null;
|
|
9149
|
+
setReplaySelect(cb) {
|
|
9150
|
+
this._replaySelect = cb;
|
|
9151
|
+
this._replayHoverTime = null;
|
|
9152
|
+
if (cb) {
|
|
9153
|
+
this._replayClickHandler = () => {
|
|
9154
|
+
if (this._replayHoverTime !== null) this._replaySelect?.onCommit(this._replayHoverTime);
|
|
9155
|
+
};
|
|
9156
|
+
this._app.canvas.addEventListener("click", this._replayClickHandler);
|
|
9157
|
+
this._app.canvas.style.cursor = "crosshair";
|
|
9158
|
+
} else {
|
|
9159
|
+
if (this._replayClickHandler) {
|
|
9160
|
+
this._app.canvas.removeEventListener("click", this._replayClickHandler);
|
|
9161
|
+
this._replayClickHandler = null;
|
|
9162
|
+
}
|
|
9163
|
+
this._app.canvas.style.cursor = "";
|
|
9164
|
+
if (this._replayDimGfx) {
|
|
9165
|
+
this._replayDimGfx.clear();
|
|
9166
|
+
this._replayDimGfx.destroy();
|
|
9167
|
+
this._replayDimGfx = null;
|
|
9168
|
+
}
|
|
9169
|
+
}
|
|
9170
|
+
}
|
|
9171
|
+
/** Translucent veil over the bars a replay-anchor click would remove. */
|
|
9172
|
+
_drawReplayDim(x) {
|
|
9173
|
+
if (!this._replayDimGfx) {
|
|
9174
|
+
this._replayDimGfx = new Graphics();
|
|
9175
|
+
this._layers.get(5 /* Interaction */).addChildAt(this._replayDimGfx, 0);
|
|
9176
|
+
}
|
|
9177
|
+
const gfx = this._replayDimGfx;
|
|
9178
|
+
const { plotWidth, plotHeight } = this._transform;
|
|
9179
|
+
gfx.clear();
|
|
9180
|
+
if (x >= 0 && x < plotWidth) {
|
|
9181
|
+
gfx.rect(x, 0, plotWidth - x, plotHeight).fill({ color: 8421520, alpha: 0.35 });
|
|
9182
|
+
}
|
|
9183
|
+
this._layers.dirty.mark(5 /* Interaction */);
|
|
9184
|
+
}
|
|
9055
9185
|
_renderFrame() {
|
|
9056
9186
|
if (!this._ready || this._destroyed) return;
|
|
9057
9187
|
const t = this._transform;
|
|
@@ -9061,6 +9191,9 @@ var PixiChart = class {
|
|
|
9061
9191
|
if (dirty.isDirty(1 /* PriceSeries */)) {
|
|
9062
9192
|
this._autoFitPriceRange();
|
|
9063
9193
|
dirty.mark(0 /* Background */);
|
|
9194
|
+
this._candleRenderer.clear();
|
|
9195
|
+
this._lineRenderer.clear();
|
|
9196
|
+
this._histogramRenderer.clear();
|
|
9064
9197
|
for (const series of this._series) {
|
|
9065
9198
|
const opts = series.options();
|
|
9066
9199
|
if (opts.visible === false) continue;
|
|
@@ -9273,6 +9406,16 @@ var PixiChart = class {
|
|
|
9273
9406
|
}
|
|
9274
9407
|
this._markViewportDirty();
|
|
9275
9408
|
}
|
|
9409
|
+
/**
|
|
9410
|
+
* Pans the viewport so the bar at `time` sits at the horizontal center.
|
|
9411
|
+
* Used by bar replay: the anchor candle the trader picked becomes the
|
|
9412
|
+
* chart's center, with the (empty, dimmed-away) future to its right.
|
|
9413
|
+
*/
|
|
9414
|
+
centerOnTime(time) {
|
|
9415
|
+
const px = this._transform.timeToX(time);
|
|
9416
|
+
this._transform.pan(-(px - this._transform.plotWidth / 2), 0);
|
|
9417
|
+
this._markViewportDirty();
|
|
9418
|
+
}
|
|
9276
9419
|
/** Pans the viewport so the latest bar sits near the right edge. */
|
|
9277
9420
|
_scrollToLatestBar() {
|
|
9278
9421
|
let latestTime = -Infinity;
|
|
@@ -11197,8 +11340,10 @@ var KIT_FEATURE_TO_CAPABILITY = {
|
|
|
11197
11340
|
multi_chart_layout: "multiChartLayout"
|
|
11198
11341
|
};
|
|
11199
11342
|
var UNMAPPED_KIT_FEATURES = [
|
|
11200
|
-
"delayed_data"
|
|
11201
|
-
|
|
11343
|
+
"delayed_data"
|
|
11344
|
+
// 'ai_script_conversion' (deleted in migration 028) and 'agent' (the
|
|
11345
|
+
// ai_agent duplicate, deleted in migration 052) used to sit here; a key
|
|
11346
|
+
// that no longer exists in the catalog needs no unmapped entry.
|
|
11202
11347
|
];
|
|
11203
11348
|
var PACKAGE_GATED_CAPABILITIES = new Set(
|
|
11204
11349
|
Object.values(KIT_FEATURE_TO_CAPABILITY)
|
|
@@ -12008,8 +12153,8 @@ var ManagedTradingController = class {
|
|
|
12008
12153
|
}
|
|
12009
12154
|
};
|
|
12010
12155
|
|
|
12011
|
-
// src/api/
|
|
12012
|
-
var
|
|
12156
|
+
// src/api/ForgeCharts.ts
|
|
12157
|
+
var ForgeCharts = class _ForgeCharts {
|
|
12013
12158
|
_core;
|
|
12014
12159
|
_bus;
|
|
12015
12160
|
_indicators;
|
|
@@ -12400,7 +12545,7 @@ var TChart = class _TChart {
|
|
|
12400
12545
|
"[ForgeCharts] ForgeScript indicators are not enabled on the active license. Contact your license provider to enable the forgeScript feature."
|
|
12401
12546
|
);
|
|
12402
12547
|
}
|
|
12403
|
-
let finalConfig =
|
|
12548
|
+
let finalConfig = _ForgeCharts.OVERLAY_ONLY.has(config.type) && config.overlay !== true ? { ...config, overlay: true } : config;
|
|
12404
12549
|
if (finalConfig.overlay !== true && !canUseMultiPane()) {
|
|
12405
12550
|
console.warn("[ForgeCharts] multiPane is not enabled on the active license \u2014 indicator added as a price-pane overlay instead.");
|
|
12406
12551
|
finalConfig = { ...finalConfig, overlay: true };
|
|
@@ -12578,7 +12723,7 @@ var TChart = class _TChart {
|
|
|
12578
12723
|
*/
|
|
12579
12724
|
startDrawingTool(type) {
|
|
12580
12725
|
this._assertAlive();
|
|
12581
|
-
if (
|
|
12726
|
+
if (_ForgeCharts.EXTENDED_DRAWING_TOOLS.has(type) && !canUseExtendedDrawings()) {
|
|
12582
12727
|
console.warn(`[ForgeCharts] Drawing tool '${type}' requires the extendedDrawings feature, which is not enabled on the active license.`);
|
|
12583
12728
|
return;
|
|
12584
12729
|
}
|
|
@@ -12616,6 +12761,14 @@ var TChart = class _TChart {
|
|
|
12616
12761
|
/** Set contract switch roll markers for continuous futures. */
|
|
12617
12762
|
setContractSwitches(switches) {
|
|
12618
12763
|
this._assertAlive();
|
|
12764
|
+
if (!canRenderOverlays()) {
|
|
12765
|
+
if (switches.length > 0) {
|
|
12766
|
+
console.warn("[ForgeCharts] Overlay rendering (overlays) is not enabled on the active plan \u2014 contract switch markers suppressed.");
|
|
12767
|
+
}
|
|
12768
|
+
this._core.setContractSwitches([]);
|
|
12769
|
+
this._core.markDirty();
|
|
12770
|
+
return;
|
|
12771
|
+
}
|
|
12619
12772
|
this._core.setContractSwitches(switches);
|
|
12620
12773
|
this._core.markDirty();
|
|
12621
12774
|
}
|
|
@@ -12659,7 +12812,7 @@ var TChart = class _TChart {
|
|
|
12659
12812
|
const snap = this._drawings.all().map((d) => ({ ...d, points: [...d.points] }));
|
|
12660
12813
|
this._drawHistory.splice(this._drawHistIdx + 1);
|
|
12661
12814
|
this._drawHistory.push(snap);
|
|
12662
|
-
if (this._drawHistory.length >
|
|
12815
|
+
if (this._drawHistory.length > _ForgeCharts._HIST_MAX) this._drawHistory.shift();
|
|
12663
12816
|
this._drawHistIdx = this._drawHistory.length - 1;
|
|
12664
12817
|
}
|
|
12665
12818
|
/** Steps drawing state one edit back (Ctrl+Z). */
|
|
@@ -13024,6 +13177,186 @@ var TChart = class _TChart {
|
|
|
13024
13177
|
}
|
|
13025
13178
|
return this._unmanagedIngestion;
|
|
13026
13179
|
}
|
|
13180
|
+
// ─── Bar replay ───────────────────────────────────────────────────────────────
|
|
13181
|
+
//
|
|
13182
|
+
// Replay is a display cutoff on the primary series (Series.setCutoffTime)
|
|
13183
|
+
// plus this controller moving it. The full tape keeps flowing underneath —
|
|
13184
|
+
// live bars land in fullData() and stay hidden until stepped over or the
|
|
13185
|
+
// replay exits — so no datafeed, indicator, or renderer knows replay
|
|
13186
|
+
// exists. Selection (the hover shadow of what a click would remove) is a
|
|
13187
|
+
// backend surface only Pixi implements; ForgeCharts refuses replay elsewhere.
|
|
13188
|
+
/** Playback speeds, in bars per second. */
|
|
13189
|
+
static REPLAY_SPEEDS = [0.5, 1, 2, 5, 10, 15, 20];
|
|
13190
|
+
_replay = {
|
|
13191
|
+
selecting: false,
|
|
13192
|
+
active: false,
|
|
13193
|
+
playing: false,
|
|
13194
|
+
speedIdx: 1,
|
|
13195
|
+
timer: null
|
|
13196
|
+
};
|
|
13197
|
+
_emitReplayState() {
|
|
13198
|
+
this._bus.emit("replayStateChanged", {
|
|
13199
|
+
selecting: this._replay.selecting,
|
|
13200
|
+
active: this._replay.active,
|
|
13201
|
+
playing: this._replay.playing,
|
|
13202
|
+
speed: _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx],
|
|
13203
|
+
cutoffTime: this._series.cutoffTime()
|
|
13204
|
+
});
|
|
13205
|
+
}
|
|
13206
|
+
/** Current replay state — the control strip's render source. */
|
|
13207
|
+
replayState() {
|
|
13208
|
+
return {
|
|
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
|
+
/**
|
|
13217
|
+
* Enter replay-anchor selection: the cursor shadows everything a click
|
|
13218
|
+
* would remove; clicking commits that bucket as the replay head. Returns
|
|
13219
|
+
* false (with a warning) when the plan lacks bar_replay or the backend
|
|
13220
|
+
* has no selection surface.
|
|
13221
|
+
*/
|
|
13222
|
+
replayEnterSelection() {
|
|
13223
|
+
this._assertAlive();
|
|
13224
|
+
if (!canUseBarReplay()) {
|
|
13225
|
+
console.warn("[ForgeCharts] Bar replay (bar_replay) is not enabled on the active plan.");
|
|
13226
|
+
return false;
|
|
13227
|
+
}
|
|
13228
|
+
if (!this._core.setReplaySelect) {
|
|
13229
|
+
console.warn("[ForgeCharts] Bar replay requires the Pixi render backend.");
|
|
13230
|
+
return false;
|
|
13231
|
+
}
|
|
13232
|
+
this._replayStopTimer();
|
|
13233
|
+
this._replay.selecting = true;
|
|
13234
|
+
this._replay.playing = false;
|
|
13235
|
+
this._core.setReplaySelect({
|
|
13236
|
+
onHover: () => {
|
|
13237
|
+
},
|
|
13238
|
+
onCommit: (time) => this._replayCommit(time)
|
|
13239
|
+
});
|
|
13240
|
+
this._emitReplayState();
|
|
13241
|
+
return true;
|
|
13242
|
+
}
|
|
13243
|
+
/** Leave selection without committing (existing replay, if any, survives). */
|
|
13244
|
+
replayCancelSelection() {
|
|
13245
|
+
this._assertAlive();
|
|
13246
|
+
if (!this._replay.selecting) return;
|
|
13247
|
+
this._replay.selecting = false;
|
|
13248
|
+
this._core.setReplaySelect?.(null);
|
|
13249
|
+
this._emitReplayState();
|
|
13250
|
+
}
|
|
13251
|
+
_replayCommit(time) {
|
|
13252
|
+
this._replay.selecting = false;
|
|
13253
|
+
this._core.setReplaySelect?.(null);
|
|
13254
|
+
this._series.setCutoffTime(time);
|
|
13255
|
+
this._replay.active = true;
|
|
13256
|
+
this._replay.playing = false;
|
|
13257
|
+
this._core.centerOnTime?.(time);
|
|
13258
|
+
this._core.markDirty();
|
|
13259
|
+
this._emitReplayState();
|
|
13260
|
+
}
|
|
13261
|
+
replayPlay() {
|
|
13262
|
+
this._assertAlive();
|
|
13263
|
+
if (!this._replay.active || this._replay.playing) return;
|
|
13264
|
+
this._replay.playing = true;
|
|
13265
|
+
this._replayStartTimer();
|
|
13266
|
+
this._emitReplayState();
|
|
13267
|
+
}
|
|
13268
|
+
replayPause() {
|
|
13269
|
+
this._assertAlive();
|
|
13270
|
+
if (!this._replay.playing) return;
|
|
13271
|
+
this._replay.playing = false;
|
|
13272
|
+
this._replayStopTimer();
|
|
13273
|
+
this._emitReplayState();
|
|
13274
|
+
}
|
|
13275
|
+
/** Advance the replay head n bars. Pauses at the end of the tape. */
|
|
13276
|
+
replayStepForward(n = 1) {
|
|
13277
|
+
this._assertAlive();
|
|
13278
|
+
if (!this._replay.active) return;
|
|
13279
|
+
const full = this._series.fullData();
|
|
13280
|
+
const shown = this._series.data().length;
|
|
13281
|
+
const nextIdx = Math.min(shown + n, full.length) - 1;
|
|
13282
|
+
if (nextIdx < shown) {
|
|
13283
|
+
this.replayPause();
|
|
13284
|
+
return;
|
|
13285
|
+
}
|
|
13286
|
+
this._series.setCutoffTime(full[nextIdx].time);
|
|
13287
|
+
this._core.markDirty();
|
|
13288
|
+
if (nextIdx >= full.length - 1) this.replayPause();
|
|
13289
|
+
this._emitReplayState();
|
|
13290
|
+
}
|
|
13291
|
+
/** Rewind the replay head n bars back in time (default 10). */
|
|
13292
|
+
replayRewind(n = 10) {
|
|
13293
|
+
this._assertAlive();
|
|
13294
|
+
if (!this._replay.active) return;
|
|
13295
|
+
const full = this._series.fullData();
|
|
13296
|
+
const shown = this._series.data().length;
|
|
13297
|
+
const idx = Math.max(shown - 1 - n, 0);
|
|
13298
|
+
if (full.length === 0) return;
|
|
13299
|
+
this._series.setCutoffTime(full[idx].time);
|
|
13300
|
+
this._core.markDirty();
|
|
13301
|
+
this._emitReplayState();
|
|
13302
|
+
}
|
|
13303
|
+
/** Set an exact playback speed (nearest catalogued value). */
|
|
13304
|
+
replaySetSpeed(speed) {
|
|
13305
|
+
this._assertAlive();
|
|
13306
|
+
let best = 0;
|
|
13307
|
+
for (let i = 0; i < _ForgeCharts.REPLAY_SPEEDS.length; i++) {
|
|
13308
|
+
if (Math.abs(_ForgeCharts.REPLAY_SPEEDS[i] - speed) < Math.abs(_ForgeCharts.REPLAY_SPEEDS[best] - speed)) best = i;
|
|
13309
|
+
}
|
|
13310
|
+
this._replay.speedIdx = best;
|
|
13311
|
+
if (this._replay.playing) this._replayStartTimer();
|
|
13312
|
+
this._emitReplayState();
|
|
13313
|
+
}
|
|
13314
|
+
/**
|
|
13315
|
+
* Restore a persisted replay session (browser refresh mid-replay). Applies
|
|
13316
|
+
* the same gate as entering selection; the cutoff simply lands where it
|
|
13317
|
+
* was, paused, with the anchor centered. A cutoff at or beyond the tape's
|
|
13318
|
+
* head means the replay had effectively finished — nothing is restored.
|
|
13319
|
+
*/
|
|
13320
|
+
replayRestore(cutoffTime, speed) {
|
|
13321
|
+
this._assertAlive();
|
|
13322
|
+
if (!canUseBarReplay()) return false;
|
|
13323
|
+
const full = this._series.fullData();
|
|
13324
|
+
const last = full[full.length - 1];
|
|
13325
|
+
if (!last || cutoffTime >= last.time) return false;
|
|
13326
|
+
if (speed !== void 0) this.replaySetSpeed(speed);
|
|
13327
|
+
this._replayCommit(cutoffTime);
|
|
13328
|
+
return true;
|
|
13329
|
+
}
|
|
13330
|
+
/** Cycle to the next playback speed; restarts the timer when playing. */
|
|
13331
|
+
replayCycleSpeed() {
|
|
13332
|
+
this._assertAlive();
|
|
13333
|
+
this._replay.speedIdx = (this._replay.speedIdx + 1) % _ForgeCharts.REPLAY_SPEEDS.length;
|
|
13334
|
+
if (this._replay.playing) this._replayStartTimer();
|
|
13335
|
+
this._emitReplayState();
|
|
13336
|
+
return _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx];
|
|
13337
|
+
}
|
|
13338
|
+
/** Exit replay entirely: the full tape (live head included) returns. */
|
|
13339
|
+
replayExit() {
|
|
13340
|
+
this._assertAlive();
|
|
13341
|
+
this._replayStopTimer();
|
|
13342
|
+
this._replay.selecting = false;
|
|
13343
|
+
this._replay.active = false;
|
|
13344
|
+
this._replay.playing = false;
|
|
13345
|
+
this._core.setReplaySelect?.(null);
|
|
13346
|
+
this._series.setCutoffTime(null);
|
|
13347
|
+
this._core.markDirty();
|
|
13348
|
+
this._core.scrollToEnd();
|
|
13349
|
+
this._emitReplayState();
|
|
13350
|
+
}
|
|
13351
|
+
_replayStartTimer() {
|
|
13352
|
+
this._replayStopTimer();
|
|
13353
|
+
const speed = _ForgeCharts.REPLAY_SPEEDS[this._replay.speedIdx];
|
|
13354
|
+
this._replay.timer = setInterval(() => this.replayStepForward(1), Math.max(1e3 / speed, 16));
|
|
13355
|
+
}
|
|
13356
|
+
_replayStopTimer() {
|
|
13357
|
+
if (this._replay.timer) clearInterval(this._replay.timer);
|
|
13358
|
+
this._replay.timer = null;
|
|
13359
|
+
}
|
|
13027
13360
|
// ─── Datafeed ─────────────────────────────────────────────────────────────────
|
|
13028
13361
|
_buildConnector(datafeed) {
|
|
13029
13362
|
return new DatafeedConnector(datafeed, this._series, {
|
|
@@ -13080,7 +13413,7 @@ function createChart(config) {
|
|
|
13080
13413
|
if (!config.container) {
|
|
13081
13414
|
throw new Error("[ForgeCharts] createChart() requires a valid container element.");
|
|
13082
13415
|
}
|
|
13083
|
-
return new
|
|
13416
|
+
return new ForgeCharts(config);
|
|
13084
13417
|
}
|
|
13085
13418
|
|
|
13086
13419
|
// src/api/ReferenceAPI.ts
|
|
@@ -18635,10 +18968,7 @@ function useHostLicense(apiUrl, getAuthToken) {
|
|
|
18635
18968
|
function useUserPackage(apiUrl, getAuthToken) {
|
|
18636
18969
|
useEffect(() => {
|
|
18637
18970
|
const resolver3 = ChartRuntimeResolver.getInstance();
|
|
18638
|
-
if (!apiUrl || !getAuthToken)
|
|
18639
|
-
resolver3.setUserPackageFeatures(null);
|
|
18640
|
-
return;
|
|
18641
|
-
}
|
|
18971
|
+
if (!apiUrl || !getAuthToken) return;
|
|
18642
18972
|
let cancelled = false;
|
|
18643
18973
|
void (async () => {
|
|
18644
18974
|
try {
|
|
@@ -23234,6 +23564,8 @@ var ChartCanvas = forwardRef(
|
|
|
23234
23564
|
onPointerToolChange,
|
|
23235
23565
|
initialPointerTool,
|
|
23236
23566
|
initialSeriesType,
|
|
23567
|
+
initialReplay,
|
|
23568
|
+
onReplayStateChange,
|
|
23237
23569
|
initialMagnetMode,
|
|
23238
23570
|
onMagnetModeChange,
|
|
23239
23571
|
drawingFavorites: drawingFavoritesProp,
|
|
@@ -23353,6 +23685,14 @@ var ChartCanvas = forwardRef(
|
|
|
23353
23685
|
},
|
|
23354
23686
|
addIndicator: (config) => chartRef.current?.addIndicator(config) ?? null,
|
|
23355
23687
|
setSeriesType: (type) => chartRef.current?.setSeriesType(type),
|
|
23688
|
+
toggleReplay: () => {
|
|
23689
|
+
const chart = chartRef.current;
|
|
23690
|
+
if (!chart) return;
|
|
23691
|
+
const st = chart.replayState();
|
|
23692
|
+
if (st.selecting) chart.replayCancelSelection();
|
|
23693
|
+
else if (st.active) chart.replayExit();
|
|
23694
|
+
else chart.replayEnterSelection();
|
|
23695
|
+
},
|
|
23356
23696
|
removeIndicator: (id) => chartRef.current?.removeIndicator(id),
|
|
23357
23697
|
moveIndicatorToOverlay: (id) => chartRef.current?.moveIndicatorToOverlay(id),
|
|
23358
23698
|
moveIndicatorToPane: (id, targetPaneId) => chartRef.current?.moveIndicatorToPane(id, targetPaneId),
|
|
@@ -23400,7 +23740,7 @@ var ChartCanvas = forwardRef(
|
|
|
23400
23740
|
useEffect(() => {
|
|
23401
23741
|
const container = priceRef.current;
|
|
23402
23742
|
if (!container) return;
|
|
23403
|
-
const chart = new
|
|
23743
|
+
const chart = new ForgeCharts({
|
|
23404
23744
|
container,
|
|
23405
23745
|
symbol,
|
|
23406
23746
|
interval: timeframe,
|
|
@@ -23414,6 +23754,10 @@ var ChartCanvas = forwardRef(
|
|
|
23414
23754
|
for (const config of initialIndicators) {
|
|
23415
23755
|
chart.addIndicator(config);
|
|
23416
23756
|
}
|
|
23757
|
+
chart.on("replayStateChanged", (s) => {
|
|
23758
|
+
setReplayState(s.selecting || s.active ? s : null);
|
|
23759
|
+
onReplayStateChangeRef.current?.(s);
|
|
23760
|
+
});
|
|
23417
23761
|
transformRef.current = chart.getTransform();
|
|
23418
23762
|
const syncChartState = () => {
|
|
23419
23763
|
setBars([...chart.getBars()]);
|
|
@@ -24373,6 +24717,37 @@ var ChartCanvas = forwardRef(
|
|
|
24373
24717
|
selectPointerToolRef.current = handleToolSelect;
|
|
24374
24718
|
const initialPointerAppliedRef = useRef(false);
|
|
24375
24719
|
const initialSeriesAppliedRef = useRef(false);
|
|
24720
|
+
const [replayState, setReplayState] = useState(null);
|
|
24721
|
+
const [replayBarOffset, setReplayBarOffset] = useState(0);
|
|
24722
|
+
const replayDragRef = useRef(null);
|
|
24723
|
+
const onReplayStateChangeRef = useRef(onReplayStateChange);
|
|
24724
|
+
useEffect(() => {
|
|
24725
|
+
onReplayStateChangeRef.current = onReplayStateChange;
|
|
24726
|
+
}, [onReplayStateChange]);
|
|
24727
|
+
const initialReplayAppliedRef = useRef(false);
|
|
24728
|
+
useEffect(() => {
|
|
24729
|
+
if (initialReplayAppliedRef.current || !initialReplay || bars.length === 0) return;
|
|
24730
|
+
initialReplayAppliedRef.current = true;
|
|
24731
|
+
chartRef.current?.replayRestore(initialReplay.cutoffTime, initialReplay.speed);
|
|
24732
|
+
}, [initialReplay, bars]);
|
|
24733
|
+
useEffect(() => {
|
|
24734
|
+
const move = (e) => {
|
|
24735
|
+
const d = replayDragRef.current;
|
|
24736
|
+
if (!d) return;
|
|
24737
|
+
const host = outerRef.current;
|
|
24738
|
+
const max = host ? Math.max(0, host.clientHeight - 80) : 400;
|
|
24739
|
+
setReplayBarOffset(Math.min(max, Math.max(0, d.startOffset + (d.startY - e.clientY))));
|
|
24740
|
+
};
|
|
24741
|
+
const up = () => {
|
|
24742
|
+
replayDragRef.current = null;
|
|
24743
|
+
};
|
|
24744
|
+
window.addEventListener("pointermove", move);
|
|
24745
|
+
window.addEventListener("pointerup", up);
|
|
24746
|
+
return () => {
|
|
24747
|
+
window.removeEventListener("pointermove", move);
|
|
24748
|
+
window.removeEventListener("pointerup", up);
|
|
24749
|
+
};
|
|
24750
|
+
}, []);
|
|
24376
24751
|
useEffect(() => {
|
|
24377
24752
|
if (!initialSeriesAppliedRef.current && initialSeriesType && chartRef.current) {
|
|
24378
24753
|
initialSeriesAppliedRef.current = true;
|
|
@@ -24381,7 +24756,7 @@ var ChartCanvas = forwardRef(
|
|
|
24381
24756
|
if (initialPointerAppliedRef.current || !initialPointerTool) return;
|
|
24382
24757
|
initialPointerAppliedRef.current = true;
|
|
24383
24758
|
selectPointerToolRef.current(initialPointerTool);
|
|
24384
|
-
}, [initialPointerTool]);
|
|
24759
|
+
}, [initialPointerTool, initialSeriesType]);
|
|
24385
24760
|
const handleMagnetModeChange = useCallback((mode) => {
|
|
24386
24761
|
setMagnetMode(mode);
|
|
24387
24762
|
chartRef.current?.setMagnetMode(mode);
|
|
@@ -24477,6 +24852,124 @@ var ChartCanvas = forwardRef(
|
|
|
24477
24852
|
crosshairXRef.current = null;
|
|
24478
24853
|
},
|
|
24479
24854
|
children: [
|
|
24855
|
+
replayState && (() => {
|
|
24856
|
+
const dark = effectiveTheme !== "light";
|
|
24857
|
+
const bg = dark ? "#000000" : "#ffffff";
|
|
24858
|
+
const fg = dark ? "#ffffff" : "#000000";
|
|
24859
|
+
const line = dark ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.22)";
|
|
24860
|
+
const btn = {
|
|
24861
|
+
background: "transparent",
|
|
24862
|
+
border: "none",
|
|
24863
|
+
color: fg,
|
|
24864
|
+
cursor: "pointer",
|
|
24865
|
+
padding: "6px 10px",
|
|
24866
|
+
borderRadius: 6,
|
|
24867
|
+
fontSize: 12,
|
|
24868
|
+
display: "inline-flex",
|
|
24869
|
+
alignItems: "center",
|
|
24870
|
+
gap: 5,
|
|
24871
|
+
lineHeight: 1
|
|
24872
|
+
};
|
|
24873
|
+
const sep = /* @__PURE__ */ jsx("span", { style: { width: 1, alignSelf: "stretch", background: line, margin: "6px 4px" } });
|
|
24874
|
+
const call = (fn) => () => {
|
|
24875
|
+
if (chartRef.current) fn(chartRef.current);
|
|
24876
|
+
};
|
|
24877
|
+
return /* @__PURE__ */ jsxs("div", { style: {
|
|
24878
|
+
position: "absolute",
|
|
24879
|
+
left: 0,
|
|
24880
|
+
right: 0,
|
|
24881
|
+
bottom: replayBarOffset,
|
|
24882
|
+
zIndex: 8,
|
|
24883
|
+
display: "flex",
|
|
24884
|
+
alignItems: "center",
|
|
24885
|
+
gap: 2,
|
|
24886
|
+
height: 38,
|
|
24887
|
+
padding: "0 8px",
|
|
24888
|
+
boxSizing: "border-box",
|
|
24889
|
+
background: bg,
|
|
24890
|
+
color: fg,
|
|
24891
|
+
borderTop: `1px solid ${line}`,
|
|
24892
|
+
borderBottom: `1px solid ${line}`,
|
|
24893
|
+
userSelect: "none"
|
|
24894
|
+
}, children: [
|
|
24895
|
+
/* @__PURE__ */ jsx(
|
|
24896
|
+
"span",
|
|
24897
|
+
{
|
|
24898
|
+
title: "Drag to move",
|
|
24899
|
+
onPointerDown: (e) => {
|
|
24900
|
+
e.preventDefault();
|
|
24901
|
+
replayDragRef.current = { startY: e.clientY, startOffset: replayBarOffset };
|
|
24902
|
+
},
|
|
24903
|
+
style: { cursor: "ns-resize", padding: "6px 6px", color: fg, opacity: 0.55, fontSize: 12, letterSpacing: 1 },
|
|
24904
|
+
children: "\u2059\u2059"
|
|
24905
|
+
}
|
|
24906
|
+
),
|
|
24907
|
+
sep,
|
|
24908
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 600, letterSpacing: 0.3, padding: "0 6px" }, children: "Replay" }),
|
|
24909
|
+
sep,
|
|
24910
|
+
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: [
|
|
24911
|
+
/* @__PURE__ */ jsx(
|
|
24912
|
+
"button",
|
|
24913
|
+
{
|
|
24914
|
+
style: btn,
|
|
24915
|
+
title: "Pick a new starting bar",
|
|
24916
|
+
onClick: call((c) => c.replayEnterSelection()),
|
|
24917
|
+
children: "\u2506\u2190 Select bar"
|
|
24918
|
+
}
|
|
24919
|
+
),
|
|
24920
|
+
sep,
|
|
24921
|
+
/* @__PURE__ */ jsx(
|
|
24922
|
+
"button",
|
|
24923
|
+
{
|
|
24924
|
+
style: btn,
|
|
24925
|
+
title: "Rewind 10 bars",
|
|
24926
|
+
onClick: call((c) => c.replayRewind(10)),
|
|
24927
|
+
children: "\u23EA"
|
|
24928
|
+
}
|
|
24929
|
+
),
|
|
24930
|
+
/* @__PURE__ */ jsx(
|
|
24931
|
+
"button",
|
|
24932
|
+
{
|
|
24933
|
+
style: btn,
|
|
24934
|
+
title: replayState.playing ? "Pause" : "Play",
|
|
24935
|
+
onClick: call((c) => replayState.playing ? c.replayPause() : c.replayPlay()),
|
|
24936
|
+
children: replayState.playing ? "\u23F8" : "\u25B6"
|
|
24937
|
+
}
|
|
24938
|
+
),
|
|
24939
|
+
/* @__PURE__ */ jsx(
|
|
24940
|
+
"button",
|
|
24941
|
+
{
|
|
24942
|
+
style: btn,
|
|
24943
|
+
title: "Forward one bar",
|
|
24944
|
+
onClick: call((c) => c.replayStepForward(1)),
|
|
24945
|
+
children: "\u23E9"
|
|
24946
|
+
}
|
|
24947
|
+
),
|
|
24948
|
+
/* @__PURE__ */ jsxs(
|
|
24949
|
+
"button",
|
|
24950
|
+
{
|
|
24951
|
+
style: { ...btn, fontVariantNumeric: "tabular-nums", minWidth: 44, justifyContent: "center" },
|
|
24952
|
+
title: "Playback speed (0.5\u201320 bars per second)",
|
|
24953
|
+
onClick: call((c) => c.replayCycleSpeed()),
|
|
24954
|
+
children: [
|
|
24955
|
+
replayState.speed,
|
|
24956
|
+
"x"
|
|
24957
|
+
]
|
|
24958
|
+
}
|
|
24959
|
+
)
|
|
24960
|
+
] }),
|
|
24961
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
|
|
24962
|
+
/* @__PURE__ */ jsx(
|
|
24963
|
+
"button",
|
|
24964
|
+
{
|
|
24965
|
+
style: btn,
|
|
24966
|
+
title: replayState.selecting ? "Cancel selection" : "Exit replay",
|
|
24967
|
+
onClick: call((c) => replayState.selecting ? c.replayCancelSelection() : c.replayExit()),
|
|
24968
|
+
children: "\u2715"
|
|
24969
|
+
}
|
|
24970
|
+
)
|
|
24971
|
+
] });
|
|
24972
|
+
})(),
|
|
24480
24973
|
/* @__PURE__ */ jsx(
|
|
24481
24974
|
"div",
|
|
24482
24975
|
{
|
|
@@ -24564,7 +25057,7 @@ var ChartCanvas = forwardRef(
|
|
|
24564
25057
|
symbol,
|
|
24565
25058
|
timeframe,
|
|
24566
25059
|
bars,
|
|
24567
|
-
theme,
|
|
25060
|
+
theme: effectiveTheme,
|
|
24568
25061
|
indicators,
|
|
24569
25062
|
overlayColors: OVERLAY_COLORS,
|
|
24570
25063
|
onRemove: handleRemoveIndicator,
|
|
@@ -25620,7 +26113,7 @@ var demonstrationTool = {
|
|
|
25620
26113
|
};
|
|
25621
26114
|
|
|
25622
26115
|
// src/version.ts
|
|
25623
|
-
var FORGECHARTS_VERSION = "1.5.
|
|
26116
|
+
var FORGECHARTS_VERSION = "1.5.84" ;
|
|
25624
26117
|
|
|
25625
26118
|
// src/compatibility.ts
|
|
25626
26119
|
var MIN_KIT_API = 1;
|
|
@@ -25677,6 +26170,6 @@ function checkKitCompatibility(kit) {
|
|
|
25677
26170
|
return { ...base, level: "ok", message: `SDK ${sdkVersion} matches the Kit.` };
|
|
25678
26171
|
}
|
|
25679
26172
|
|
|
25680
|
-
export { CROSSHAIR_LABEL, CROSSHAIR_STYLE, CURRENT_SCHEMA_VERSION, CURSOR_LABEL, CURSOR_STYLE, CandleEngine, ChartRuntimeResolver, CoordTransform, DEFAULT_SYNC_OPTIONS, DEMONSTRATION_COLOR, DEMONSTRATION_FILL, DEMONSTRATION_LABEL, DEMONSTRATION_RADIUS, DEMONSTRATION_STROKE, DEMONSTRATION_STYLE, DOT_COLOR, DOT_LABEL, DOT_RADIUS, DOT_STYLE, DatafeedConnector, ForgeScriptIndicator, ForgeScriptRuntime, Series2 as ForgeScriptSeries, GridChartContainer, GridSyncProvider, IndicatorDAG, KIT_FEATURE_TO_CAPABILITY, LayoutTemplateSelector, LicenseManager, MAX_KIT_API, MIN_KIT_API, ManagedTradingController, PACKAGE_GATED_CAPABILITIES, PRODUCT_TIERS, PaneManager, ReferenceAPI, TChart, 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 };
|
|
26173
|
+
export { CROSSHAIR_LABEL, CROSSHAIR_STYLE, CURRENT_SCHEMA_VERSION, CURSOR_LABEL, CURSOR_STYLE, CandleEngine, ChartRuntimeResolver, CoordTransform, DEFAULT_SYNC_OPTIONS, DEMONSTRATION_COLOR, DEMONSTRATION_FILL, DEMONSTRATION_LABEL, DEMONSTRATION_RADIUS, DEMONSTRATION_STROKE, DEMONSTRATION_STYLE, DOT_COLOR, DOT_LABEL, DOT_RADIUS, DOT_STYLE, DatafeedConnector, ForgeCharts, ForgeScriptIndicator, ForgeScriptRuntime, Series2 as ForgeScriptSeries, GridChartContainer, GridSyncProvider, IndicatorDAG, KIT_FEATURE_TO_CAPABILITY, LayoutTemplateSelector, LicenseManager, MAX_KIT_API, MIN_KIT_API, ManagedTradingController, PACKAGE_GATED_CAPABILITIES, PRODUCT_TIERS, PaneManager, ReferenceAPI, ForgeCharts as TChart, 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 };
|
|
25681
26174
|
//# sourceMappingURL=index.js.map
|
|
25682
26175
|
//# sourceMappingURL=index.js.map
|