@forgecharts/sdk 1.5.83 → 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/ForgeCharts.d.ts +9 -0
- package/dist/api/ForgeCharts.d.ts.map +1 -1
- package/dist/index.js +106 -18
- package/dist/index.js.map +1 -1
- package/dist/internal.js +106 -18
- package/dist/internal.js.map +1 -1
- package/dist/pixi/PixiChart.d.ts +6 -0
- package/dist/pixi/PixiChart.d.ts.map +1 -1
- package/dist/react/canvas/ChartCanvas.d.ts +13 -0
- package/dist/react/canvas/ChartCanvas.d.ts.map +1 -1
- package/dist/react/index.js +106 -18
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +106 -18
- package/dist/react/internal.js.map +1 -1
- package/dist/types/ChartBackend.d.ts +2 -0
- package/dist/types/ChartBackend.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/react/internal.js
CHANGED
|
@@ -9379,6 +9379,16 @@ var PixiChart = class {
|
|
|
9379
9379
|
}
|
|
9380
9380
|
this._markViewportDirty();
|
|
9381
9381
|
}
|
|
9382
|
+
/**
|
|
9383
|
+
* Pans the viewport so the bar at `time` sits at the horizontal center.
|
|
9384
|
+
* Used by bar replay: the anchor candle the trader picked becomes the
|
|
9385
|
+
* chart's center, with the (empty, dimmed-away) future to its right.
|
|
9386
|
+
*/
|
|
9387
|
+
centerOnTime(time) {
|
|
9388
|
+
const px = this._transform.timeToX(time);
|
|
9389
|
+
this._transform.pan(-(px - this._transform.plotWidth / 2), 0);
|
|
9390
|
+
this._markViewportDirty();
|
|
9391
|
+
}
|
|
9382
9392
|
/** Pans the viewport so the latest bar sits near the right edge. */
|
|
9383
9393
|
_scrollToLatestBar() {
|
|
9384
9394
|
let latestTime = -Infinity;
|
|
@@ -13080,7 +13090,7 @@ var ForgeCharts = class _ForgeCharts {
|
|
|
13080
13090
|
// exists. Selection (the hover shadow of what a click would remove) is a
|
|
13081
13091
|
// backend surface only Pixi implements; ForgeCharts refuses replay elsewhere.
|
|
13082
13092
|
/** Playback speeds, in bars per second. */
|
|
13083
|
-
static REPLAY_SPEEDS = [0.5, 1, 2, 5, 10];
|
|
13093
|
+
static REPLAY_SPEEDS = [0.5, 1, 2, 5, 10, 15, 20];
|
|
13084
13094
|
_replay = {
|
|
13085
13095
|
selecting: false,
|
|
13086
13096
|
active: false,
|
|
@@ -13148,6 +13158,7 @@ var ForgeCharts = class _ForgeCharts {
|
|
|
13148
13158
|
this._series.setCutoffTime(time);
|
|
13149
13159
|
this._replay.active = true;
|
|
13150
13160
|
this._replay.playing = false;
|
|
13161
|
+
this._core.centerOnTime?.(time);
|
|
13151
13162
|
this._core.markDirty();
|
|
13152
13163
|
this._emitReplayState();
|
|
13153
13164
|
}
|
|
@@ -13193,6 +13204,33 @@ var ForgeCharts = class _ForgeCharts {
|
|
|
13193
13204
|
this._core.markDirty();
|
|
13194
13205
|
this._emitReplayState();
|
|
13195
13206
|
}
|
|
13207
|
+
/** Set an exact playback speed (nearest catalogued value). */
|
|
13208
|
+
replaySetSpeed(speed) {
|
|
13209
|
+
this._assertAlive();
|
|
13210
|
+
let best = 0;
|
|
13211
|
+
for (let i = 0; i < _ForgeCharts.REPLAY_SPEEDS.length; i++) {
|
|
13212
|
+
if (Math.abs(_ForgeCharts.REPLAY_SPEEDS[i] - speed) < Math.abs(_ForgeCharts.REPLAY_SPEEDS[best] - speed)) best = i;
|
|
13213
|
+
}
|
|
13214
|
+
this._replay.speedIdx = best;
|
|
13215
|
+
if (this._replay.playing) this._replayStartTimer();
|
|
13216
|
+
this._emitReplayState();
|
|
13217
|
+
}
|
|
13218
|
+
/**
|
|
13219
|
+
* Restore a persisted replay session (browser refresh mid-replay). Applies
|
|
13220
|
+
* the same gate as entering selection; the cutoff simply lands where it
|
|
13221
|
+
* was, paused, with the anchor centered. A cutoff at or beyond the tape's
|
|
13222
|
+
* head means the replay had effectively finished — nothing is restored.
|
|
13223
|
+
*/
|
|
13224
|
+
replayRestore(cutoffTime, speed) {
|
|
13225
|
+
this._assertAlive();
|
|
13226
|
+
if (!canUseBarReplay()) return false;
|
|
13227
|
+
const full = this._series.fullData();
|
|
13228
|
+
const last = full[full.length - 1];
|
|
13229
|
+
if (!last || cutoffTime >= last.time) return false;
|
|
13230
|
+
if (speed !== void 0) this.replaySetSpeed(speed);
|
|
13231
|
+
this._replayCommit(cutoffTime);
|
|
13232
|
+
return true;
|
|
13233
|
+
}
|
|
13196
13234
|
/** Cycle to the next playback speed; restarts the timer when playing. */
|
|
13197
13235
|
replayCycleSpeed() {
|
|
13198
13236
|
this._assertAlive();
|
|
@@ -18664,7 +18702,7 @@ var DEMONSTRATION_STROKE = "rgba(255, 200, 50, 0.7)";
|
|
|
18664
18702
|
var DEMONSTRATION_COLOR = "var(--crosshair-overlay, rgba(255,255,255,0.75))";
|
|
18665
18703
|
|
|
18666
18704
|
// src/version.ts
|
|
18667
|
-
var FORGECHARTS_VERSION = "1.5.
|
|
18705
|
+
var FORGECHARTS_VERSION = "1.5.84" ;
|
|
18668
18706
|
function applyRuntimeConfig(caps, config) {
|
|
18669
18707
|
if (!config) return caps;
|
|
18670
18708
|
const orderEntry = config.enableOrderEntry === false ? false : caps.orderEntry;
|
|
@@ -23506,6 +23544,8 @@ var ChartCanvas = forwardRef(
|
|
|
23506
23544
|
onPointerToolChange,
|
|
23507
23545
|
initialPointerTool,
|
|
23508
23546
|
initialSeriesType,
|
|
23547
|
+
initialReplay,
|
|
23548
|
+
onReplayStateChange,
|
|
23509
23549
|
initialMagnetMode,
|
|
23510
23550
|
onMagnetModeChange,
|
|
23511
23551
|
drawingFavorites: drawingFavoritesProp,
|
|
@@ -23696,6 +23736,7 @@ var ChartCanvas = forwardRef(
|
|
|
23696
23736
|
}
|
|
23697
23737
|
chart.on("replayStateChanged", (s) => {
|
|
23698
23738
|
setReplayState(s.selecting || s.active ? s : null);
|
|
23739
|
+
onReplayStateChangeRef.current?.(s);
|
|
23699
23740
|
});
|
|
23700
23741
|
transformRef.current = chart.getTransform();
|
|
23701
23742
|
const syncChartState = () => {
|
|
@@ -24657,6 +24698,36 @@ var ChartCanvas = forwardRef(
|
|
|
24657
24698
|
const initialPointerAppliedRef = useRef(false);
|
|
24658
24699
|
const initialSeriesAppliedRef = useRef(false);
|
|
24659
24700
|
const [replayState, setReplayState] = useState(null);
|
|
24701
|
+
const [replayBarOffset, setReplayBarOffset] = useState(0);
|
|
24702
|
+
const replayDragRef = useRef(null);
|
|
24703
|
+
const onReplayStateChangeRef = useRef(onReplayStateChange);
|
|
24704
|
+
useEffect(() => {
|
|
24705
|
+
onReplayStateChangeRef.current = onReplayStateChange;
|
|
24706
|
+
}, [onReplayStateChange]);
|
|
24707
|
+
const initialReplayAppliedRef = useRef(false);
|
|
24708
|
+
useEffect(() => {
|
|
24709
|
+
if (initialReplayAppliedRef.current || !initialReplay || bars.length === 0) return;
|
|
24710
|
+
initialReplayAppliedRef.current = true;
|
|
24711
|
+
chartRef.current?.replayRestore(initialReplay.cutoffTime, initialReplay.speed);
|
|
24712
|
+
}, [initialReplay, bars]);
|
|
24713
|
+
useEffect(() => {
|
|
24714
|
+
const move = (e) => {
|
|
24715
|
+
const d = replayDragRef.current;
|
|
24716
|
+
if (!d) return;
|
|
24717
|
+
const host = outerRef.current;
|
|
24718
|
+
const max = host ? Math.max(0, host.clientHeight - 80) : 400;
|
|
24719
|
+
setReplayBarOffset(Math.min(max, Math.max(0, d.startOffset + (d.startY - e.clientY))));
|
|
24720
|
+
};
|
|
24721
|
+
const up = () => {
|
|
24722
|
+
replayDragRef.current = null;
|
|
24723
|
+
};
|
|
24724
|
+
window.addEventListener("pointermove", move);
|
|
24725
|
+
window.addEventListener("pointerup", up);
|
|
24726
|
+
return () => {
|
|
24727
|
+
window.removeEventListener("pointermove", move);
|
|
24728
|
+
window.removeEventListener("pointerup", up);
|
|
24729
|
+
};
|
|
24730
|
+
}, []);
|
|
24660
24731
|
useEffect(() => {
|
|
24661
24732
|
if (!initialSeriesAppliedRef.current && initialSeriesType && chartRef.current) {
|
|
24662
24733
|
initialSeriesAppliedRef.current = true;
|
|
@@ -24763,15 +24834,15 @@ var ChartCanvas = forwardRef(
|
|
|
24763
24834
|
children: [
|
|
24764
24835
|
replayState && (() => {
|
|
24765
24836
|
const dark = effectiveTheme !== "light";
|
|
24766
|
-
const bg = dark ? "
|
|
24767
|
-
const fg = dark ? "#
|
|
24768
|
-
const line = dark ? "rgba(255,255,255,0.
|
|
24837
|
+
const bg = dark ? "#000000" : "#ffffff";
|
|
24838
|
+
const fg = dark ? "#ffffff" : "#000000";
|
|
24839
|
+
const line = dark ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.22)";
|
|
24769
24840
|
const btn = {
|
|
24770
24841
|
background: "transparent",
|
|
24771
24842
|
border: "none",
|
|
24772
24843
|
color: fg,
|
|
24773
24844
|
cursor: "pointer",
|
|
24774
|
-
padding: "
|
|
24845
|
+
padding: "6px 10px",
|
|
24775
24846
|
borderRadius: 6,
|
|
24776
24847
|
fontSize: 12,
|
|
24777
24848
|
display: "inline-flex",
|
|
@@ -24779,27 +24850,44 @@ var ChartCanvas = forwardRef(
|
|
|
24779
24850
|
gap: 5,
|
|
24780
24851
|
lineHeight: 1
|
|
24781
24852
|
};
|
|
24853
|
+
const sep = /* @__PURE__ */ jsx("span", { style: { width: 1, alignSelf: "stretch", background: line, margin: "6px 4px" } });
|
|
24782
24854
|
const call = (fn) => () => {
|
|
24783
24855
|
if (chartRef.current) fn(chartRef.current);
|
|
24784
24856
|
};
|
|
24785
24857
|
return /* @__PURE__ */ jsxs("div", { style: {
|
|
24786
24858
|
position: "absolute",
|
|
24787
|
-
|
|
24788
|
-
|
|
24789
|
-
|
|
24859
|
+
left: 0,
|
|
24860
|
+
right: 0,
|
|
24861
|
+
bottom: replayBarOffset,
|
|
24790
24862
|
zIndex: 8,
|
|
24791
24863
|
display: "flex",
|
|
24792
24864
|
alignItems: "center",
|
|
24793
24865
|
gap: 2,
|
|
24866
|
+
height: 38,
|
|
24867
|
+
padding: "0 8px",
|
|
24868
|
+
boxSizing: "border-box",
|
|
24794
24869
|
background: bg,
|
|
24795
24870
|
color: fg,
|
|
24796
|
-
|
|
24797
|
-
|
|
24798
|
-
padding: "2px 6px",
|
|
24799
|
-
boxShadow: "0 4px 16px rgba(0,0,0,0.25)",
|
|
24871
|
+
borderTop: `1px solid ${line}`,
|
|
24872
|
+
borderBottom: `1px solid ${line}`,
|
|
24800
24873
|
userSelect: "none"
|
|
24801
24874
|
}, children: [
|
|
24802
|
-
|
|
24875
|
+
/* @__PURE__ */ jsx(
|
|
24876
|
+
"span",
|
|
24877
|
+
{
|
|
24878
|
+
title: "Drag to move",
|
|
24879
|
+
onPointerDown: (e) => {
|
|
24880
|
+
e.preventDefault();
|
|
24881
|
+
replayDragRef.current = { startY: e.clientY, startOffset: replayBarOffset };
|
|
24882
|
+
},
|
|
24883
|
+
style: { cursor: "ns-resize", padding: "6px 6px", color: fg, opacity: 0.55, fontSize: 12, letterSpacing: 1 },
|
|
24884
|
+
children: "\u2059\u2059"
|
|
24885
|
+
}
|
|
24886
|
+
),
|
|
24887
|
+
sep,
|
|
24888
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 600, letterSpacing: 0.3, padding: "0 6px" }, children: "Replay" }),
|
|
24889
|
+
sep,
|
|
24890
|
+
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: [
|
|
24803
24891
|
/* @__PURE__ */ jsx(
|
|
24804
24892
|
"button",
|
|
24805
24893
|
{
|
|
@@ -24809,7 +24897,7 @@ var ChartCanvas = forwardRef(
|
|
|
24809
24897
|
children: "\u2506\u2190 Select bar"
|
|
24810
24898
|
}
|
|
24811
24899
|
),
|
|
24812
|
-
|
|
24900
|
+
sep,
|
|
24813
24901
|
/* @__PURE__ */ jsx(
|
|
24814
24902
|
"button",
|
|
24815
24903
|
{
|
|
@@ -24840,8 +24928,8 @@ var ChartCanvas = forwardRef(
|
|
|
24840
24928
|
/* @__PURE__ */ jsxs(
|
|
24841
24929
|
"button",
|
|
24842
24930
|
{
|
|
24843
|
-
style: { ...btn, fontVariantNumeric: "tabular-nums" },
|
|
24844
|
-
title: "Playback speed",
|
|
24931
|
+
style: { ...btn, fontVariantNumeric: "tabular-nums", minWidth: 44, justifyContent: "center" },
|
|
24932
|
+
title: "Playback speed (0.5\u201320 bars per second)",
|
|
24845
24933
|
onClick: call((c) => c.replayCycleSpeed()),
|
|
24846
24934
|
children: [
|
|
24847
24935
|
replayState.speed,
|
|
@@ -24850,7 +24938,7 @@ var ChartCanvas = forwardRef(
|
|
|
24850
24938
|
}
|
|
24851
24939
|
)
|
|
24852
24940
|
] }),
|
|
24853
|
-
/* @__PURE__ */ jsx("span", { style: {
|
|
24941
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
|
|
24854
24942
|
/* @__PURE__ */ jsx(
|
|
24855
24943
|
"button",
|
|
24856
24944
|
{
|