@coderyo/core 1.0.0-rc.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +48 -4
- package/dist/index.js +338 -14
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import * as _coderyo_drawings from '@coderyo/drawings';
|
|
2
2
|
import { DrawingRecord, DrawingStyleMeta } from '@coderyo/drawings';
|
|
3
3
|
import * as _coderyo_data from '@coderyo/data';
|
|
4
|
-
import { RealtimeStreamMode, Interval, DataProvider, SymbolResolver } from '@coderyo/data';
|
|
4
|
+
import { RealtimeStreamMode, Interval, DataProvider, SymbolResolver, Bar } from '@coderyo/data';
|
|
5
5
|
import { IndicatorConfig } from '@coderyo/indicators';
|
|
6
6
|
import { FetchPolicy } from '@coderyo/virtual-window';
|
|
7
|
+
import { ChartVisibleRange } from '@coderyo/renderer-lite';
|
|
8
|
+
export { ChartVisibleRange } from '@coderyo/renderer-lite';
|
|
7
9
|
import { BridgeAdapter, BridgeOutboundType } from '@coderyo/bridge';
|
|
10
|
+
export { PINE_EDITOR_DEFAULT, PINE_SAMPLE_SCRIPT, PineCompileResult, PineIrProgram, PinePlotSeries, compilePineLite, runPineLite } from '@coderyo/pine-lite';
|
|
8
11
|
|
|
9
12
|
interface ChartGapsFeatures {
|
|
10
13
|
whitespace?: boolean;
|
|
@@ -28,11 +31,15 @@ interface ChartFeatures {
|
|
|
28
31
|
/** Ease last candle OHLC + price line to new values (~150ms). */
|
|
29
32
|
smoothPriceUpdate?: boolean;
|
|
30
33
|
smoothPriceDurationMs?: number;
|
|
31
|
-
/**
|
|
34
|
+
/** Pine-lite script source (requires pineEnabled). */
|
|
35
|
+
pineScript?: string | null;
|
|
36
|
+
/** Post-1.0 hooks — default false. */
|
|
32
37
|
pineEnabled?: boolean;
|
|
33
38
|
protobuf?: boolean;
|
|
34
39
|
telemetry?: boolean;
|
|
35
40
|
tickStream?: boolean;
|
|
41
|
+
/** Run Pine-lite VM in a Web Worker when available (default true). */
|
|
42
|
+
pineWorker?: boolean;
|
|
36
43
|
}
|
|
37
44
|
interface ResolvedChartFeatures {
|
|
38
45
|
fetchPolicy: FetchPolicy;
|
|
@@ -43,10 +50,12 @@ interface ResolvedChartFeatures {
|
|
|
43
50
|
indicatorPersist: boolean;
|
|
44
51
|
smoothPriceUpdate: boolean;
|
|
45
52
|
smoothPriceDurationMs: number;
|
|
53
|
+
pineScript: string | null;
|
|
46
54
|
pineEnabled: boolean;
|
|
47
55
|
protobuf: boolean;
|
|
48
56
|
telemetry: boolean;
|
|
49
57
|
tickStream: boolean;
|
|
58
|
+
pineWorker: boolean;
|
|
50
59
|
}
|
|
51
60
|
declare const DEFAULT_CHART_FEATURES: ResolvedChartFeatures;
|
|
52
61
|
declare function resolveChartFeatures(partial?: ChartFeatures): ResolvedChartFeatures;
|
|
@@ -78,7 +87,7 @@ interface ChartOptions {
|
|
|
78
87
|
/** @deprecated Use features.indicators */
|
|
79
88
|
indicatorConfig?: IndicatorConfig;
|
|
80
89
|
}
|
|
81
|
-
type ChartEvent = 'connectionChange' | 'barUpdate' | 'error' | 'visibleRangeChange' | 'symbolChange' | 'intervalChange' | 'crosshairChange' | 'destroyed' | 'drawingSelectionChange' | 'drawingContextMenu' | 'requestCursorTool' | 'featuresChange';
|
|
90
|
+
type ChartEvent = 'connectionChange' | 'barUpdate' | 'error' | 'visibleRangeChange' | 'symbolChange' | 'intervalChange' | 'crosshairChange' | 'destroyed' | 'drawingSelectionChange' | 'drawingContextMenu' | 'requestCursorTool' | 'featuresChange' | 'telemetry';
|
|
82
91
|
type EventHandler = (payload?: unknown) => void;
|
|
83
92
|
declare class ChartController {
|
|
84
93
|
private readonly container;
|
|
@@ -97,11 +106,21 @@ declare class ChartController {
|
|
|
97
106
|
private drawingManager;
|
|
98
107
|
private offCrosshair;
|
|
99
108
|
private features;
|
|
109
|
+
private pineIr;
|
|
110
|
+
private tickAggregator;
|
|
111
|
+
private catchUpInFlight;
|
|
112
|
+
private lastCatchUpAt;
|
|
113
|
+
private offPageResume;
|
|
100
114
|
constructor(container: HTMLElement, options: ChartOptions);
|
|
101
115
|
getFeatures(): ResolvedChartFeatures;
|
|
102
116
|
setFeatures(patch: ChartFeatures): this;
|
|
103
117
|
hasActiveSymbol(): boolean;
|
|
104
118
|
private applyFeatures;
|
|
119
|
+
private recompilePine;
|
|
120
|
+
private applyPinePlots;
|
|
121
|
+
private trackTelemetry;
|
|
122
|
+
setLocale(locale: string): this;
|
|
123
|
+
subscribeBars(handler: (bar: Bar) => void): () => void;
|
|
105
124
|
/** Integrator push: update last candle close (and H/L) without WS. */
|
|
106
125
|
updateLastPrice(price: number, timeMs?: number): this;
|
|
107
126
|
private buildBarFromPrice;
|
|
@@ -133,6 +152,12 @@ declare class ChartController {
|
|
|
133
152
|
setShowGrid(show: boolean): this;
|
|
134
153
|
fitContent(): this;
|
|
135
154
|
scrollToRealtime(): this;
|
|
155
|
+
getVisibleRange(): ChartVisibleRange | null;
|
|
156
|
+
getBarSpace(): number;
|
|
157
|
+
setBarSpace(px: number): this;
|
|
158
|
+
setVisibleRange(range: ChartVisibleRange): this;
|
|
159
|
+
scrollToTimestamp(tsMs: number, animationMs?: number): this;
|
|
160
|
+
reloadHistory(): Promise<this>;
|
|
136
161
|
setLogScale(enabled: boolean): this;
|
|
137
162
|
setFullscreen(_enabled: boolean): this;
|
|
138
163
|
exportImage(opts?: {
|
|
@@ -143,6 +168,11 @@ declare class ChartController {
|
|
|
143
168
|
private isLoadGenerationCurrent;
|
|
144
169
|
private bootstrap;
|
|
145
170
|
private teardownSubscription;
|
|
171
|
+
private bindPageResumeCatchUp;
|
|
172
|
+
/**
|
|
173
|
+
* Backfill bars missed while the tab/window was backgrounded or WS delivery paused.
|
|
174
|
+
*/
|
|
175
|
+
private catchUpMissedBars;
|
|
146
176
|
private maybeLoadMore;
|
|
147
177
|
private refreshRender;
|
|
148
178
|
private emit;
|
|
@@ -161,7 +191,7 @@ interface WireChartBridgeOptions {
|
|
|
161
191
|
declare function wireChartBridge(opts: WireChartBridgeOptions): () => void;
|
|
162
192
|
|
|
163
193
|
/** Synced by scripts/sync-versions.mjs from repo VERSION file */
|
|
164
|
-
declare const TRADVIEW_VERSION: "1.0.
|
|
194
|
+
declare const TRADVIEW_VERSION: "1.0.1";
|
|
165
195
|
|
|
166
196
|
/** Playground / docs: opt-in full TV-like chart features. */
|
|
167
197
|
declare function createDemoChartFeatures(opts: {
|
|
@@ -193,6 +223,17 @@ interface IChart {
|
|
|
193
223
|
setLogScale(enabled: boolean): IChart;
|
|
194
224
|
fitContent(): IChart;
|
|
195
225
|
scrollToRealtime(): IChart;
|
|
226
|
+
/** Visible time range in ms (`fromMs` / `toMs`), or `null` if unknown. */
|
|
227
|
+
getVisibleRange(): ChartVisibleRange | null;
|
|
228
|
+
/** Bar spacing in px (zoom). Alias for LWC `barSpacing`. */
|
|
229
|
+
getBarSpace(): number;
|
|
230
|
+
setBarSpace(px: number): IChart;
|
|
231
|
+
/** Restore viewport time range after re-bootstrap. */
|
|
232
|
+
setVisibleRange(range: ChartVisibleRange): IChart;
|
|
233
|
+
/** Scroll so `tsMs` aligns to the right edge of the viewport. */
|
|
234
|
+
scrollToTimestamp(tsMs: number, animationMs?: number): IChart;
|
|
235
|
+
/** Re-fetch recent history without clearing scroll/zoom. */
|
|
236
|
+
reloadHistory(): Promise<IChart>;
|
|
196
237
|
resize(size?: {
|
|
197
238
|
width?: number;
|
|
198
239
|
height?: number;
|
|
@@ -217,6 +258,9 @@ interface IChart {
|
|
|
217
258
|
/** Integrator push: smooth-update last candle toward `price` (no WS required). */
|
|
218
259
|
updateLastPrice(price: number, timeMs?: number): IChart;
|
|
219
260
|
hasActiveSymbol(): boolean;
|
|
261
|
+
setLocale(locale: string): IChart;
|
|
262
|
+
/** Subscribe to realtime bar updates; returns unsubscribe. */
|
|
263
|
+
subscribeBars(handler: (bar: _coderyo_data.Bar) => void): () => void;
|
|
220
264
|
destroy(): void;
|
|
221
265
|
}
|
|
222
266
|
declare function createChart(target: HTMLElement | string, options: CreateChartOptions): IChart;
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "@coderyo/bridge";
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
|
-
var TRADVIEW_VERSION = "1.0.
|
|
8
|
+
var TRADVIEW_VERSION = "1.0.1";
|
|
9
9
|
|
|
10
10
|
// src/bridge-wire.ts
|
|
11
11
|
var TRADVIEW_API_VERSION = 1;
|
|
@@ -16,7 +16,8 @@ var CHART_EVENT_TO_BRIDGE = {
|
|
|
16
16
|
symbolChange: "chart.symbol",
|
|
17
17
|
intervalChange: "chart.interval",
|
|
18
18
|
crosshairChange: "chart.crosshair",
|
|
19
|
-
destroyed: "chart.destroyed"
|
|
19
|
+
destroyed: "chart.destroyed",
|
|
20
|
+
barUpdate: "chart.barUpdate"
|
|
20
21
|
};
|
|
21
22
|
function wireChartBridge(opts) {
|
|
22
23
|
const chartId = opts.chartId ?? `chart-${Date.now()}`;
|
|
@@ -104,6 +105,10 @@ function wireChartBridge(opts) {
|
|
|
104
105
|
handlers.set("destroyed", () => {
|
|
105
106
|
post("chart.destroyed", { chartId });
|
|
106
107
|
});
|
|
108
|
+
handlers.set("barUpdate", (bar) => {
|
|
109
|
+
const b = bar;
|
|
110
|
+
post("chart.barUpdate", { chartId, t: b?.t, c: b?.c });
|
|
111
|
+
});
|
|
107
112
|
for (const [ev, fn] of handlers) {
|
|
108
113
|
const bridgeType = CHART_EVENT_TO_BRIDGE[ev];
|
|
109
114
|
if (!bridgeType || shouldPost(bridgeType)) {
|
|
@@ -139,6 +144,36 @@ function wireChartBridge(opts) {
|
|
|
139
144
|
});
|
|
140
145
|
postResize();
|
|
141
146
|
break;
|
|
147
|
+
case "host.setLogScale":
|
|
148
|
+
if (typeof p.enabled === "boolean") chart.setLogScale(p.enabled);
|
|
149
|
+
break;
|
|
150
|
+
case "host.setBarSpace":
|
|
151
|
+
if (typeof p.px === "number") chart.setBarSpace(p.px);
|
|
152
|
+
break;
|
|
153
|
+
case "host.setVisibleRange":
|
|
154
|
+
if (typeof p.fromMs === "number" && typeof p.toMs === "number") {
|
|
155
|
+
chart.setVisibleRange({ fromMs: p.fromMs, toMs: p.toMs });
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
case "host.scrollToTimestamp":
|
|
159
|
+
if (typeof p.tsMs === "number") {
|
|
160
|
+
chart.scrollToTimestamp(
|
|
161
|
+
p.tsMs,
|
|
162
|
+
typeof p.animationMs === "number" ? p.animationMs : void 0
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
case "host.reloadHistory":
|
|
167
|
+
void chart.reloadHistory();
|
|
168
|
+
break;
|
|
169
|
+
case "host.setLocale":
|
|
170
|
+
if (typeof p.locale === "string") chart.setLocale(p.locale);
|
|
171
|
+
break;
|
|
172
|
+
case "host.setFeatures":
|
|
173
|
+
if (p.features && typeof p.features === "object") {
|
|
174
|
+
chart.setFeatures(p.features);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
142
177
|
case "host.destroy":
|
|
143
178
|
chart.destroy();
|
|
144
179
|
break;
|
|
@@ -154,11 +189,51 @@ function wireChartBridge(opts) {
|
|
|
154
189
|
}
|
|
155
190
|
|
|
156
191
|
// src/chart-controller.ts
|
|
157
|
-
import { floorBarOpenTime } from "@coderyo/data";
|
|
192
|
+
import { floorBarOpenTime, intervalMs as intervalMs2 } from "@coderyo/data";
|
|
158
193
|
import { parseInterval } from "@coderyo/data";
|
|
159
|
-
import { BarStore } from "@coderyo/series";
|
|
194
|
+
import { BarStore, computeGapStartTimes, TickAggregator } from "@coderyo/series";
|
|
195
|
+
import { setLocale as setI18nLocale } from "@coderyo/i18n";
|
|
196
|
+
|
|
197
|
+
// src/fetch-chart-history.ts
|
|
198
|
+
import { intervalMs } from "@coderyo/data";
|
|
199
|
+
async function fetchChartHistory(provider, query) {
|
|
200
|
+
const caps = await provider.getCapabilities?.();
|
|
201
|
+
if (caps?.wsHistory && provider.requestWsHistory) {
|
|
202
|
+
try {
|
|
203
|
+
if (query.mode === "range") {
|
|
204
|
+
const bars = await provider.requestWsHistory({
|
|
205
|
+
symbol: query.symbol,
|
|
206
|
+
interval: query.interval,
|
|
207
|
+
from: query.from,
|
|
208
|
+
to: query.to
|
|
209
|
+
});
|
|
210
|
+
return { bars, hasMore: false };
|
|
211
|
+
}
|
|
212
|
+
if (query.mode === "loadMore") {
|
|
213
|
+
const ms = intervalMs(query.interval);
|
|
214
|
+
const from = query.endTime - ms * query.limit;
|
|
215
|
+
const bars = await provider.requestWsHistory({
|
|
216
|
+
symbol: query.symbol,
|
|
217
|
+
interval: query.interval,
|
|
218
|
+
from,
|
|
219
|
+
to: query.endTime
|
|
220
|
+
});
|
|
221
|
+
return { bars, hasMore: false };
|
|
222
|
+
}
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return provider.getHistory(query);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/chart-controller.ts
|
|
160
230
|
import { VirtualWindow } from "@coderyo/virtual-window";
|
|
161
231
|
import { DrawingManager } from "@coderyo/drawings";
|
|
232
|
+
import {
|
|
233
|
+
compilePineLite,
|
|
234
|
+
runPineLiteAsync,
|
|
235
|
+
terminatePineWorker
|
|
236
|
+
} from "@coderyo/pine-lite";
|
|
162
237
|
import { PaneOrchestrator } from "@coderyo/renderer-lite";
|
|
163
238
|
|
|
164
239
|
// src/chart-features.ts
|
|
@@ -171,10 +246,12 @@ var DEFAULT_CHART_FEATURES = {
|
|
|
171
246
|
indicatorPersist: false,
|
|
172
247
|
smoothPriceUpdate: false,
|
|
173
248
|
smoothPriceDurationMs: 150,
|
|
249
|
+
pineScript: null,
|
|
174
250
|
pineEnabled: false,
|
|
175
251
|
protobuf: false,
|
|
176
252
|
telemetry: false,
|
|
177
|
-
tickStream: false
|
|
253
|
+
tickStream: false,
|
|
254
|
+
pineWorker: true
|
|
178
255
|
};
|
|
179
256
|
function resolveChartFeatures(partial) {
|
|
180
257
|
const d = DEFAULT_CHART_FEATURES;
|
|
@@ -193,10 +270,12 @@ function resolveChartFeatures(partial) {
|
|
|
193
270
|
indicatorPersist: partial?.indicatorPersist ?? d.indicatorPersist,
|
|
194
271
|
smoothPriceUpdate: partial?.smoothPriceUpdate ?? d.smoothPriceUpdate,
|
|
195
272
|
smoothPriceDurationMs: partial?.smoothPriceDurationMs ?? d.smoothPriceDurationMs,
|
|
273
|
+
pineScript: partial?.pineScript !== void 0 ? partial.pineScript : d.pineScript,
|
|
196
274
|
pineEnabled: partial?.pineEnabled ?? d.pineEnabled,
|
|
197
275
|
protobuf: partial?.protobuf ?? d.protobuf,
|
|
198
276
|
telemetry: partial?.telemetry ?? d.telemetry,
|
|
199
|
-
tickStream: partial?.tickStream ?? d.tickStream
|
|
277
|
+
tickStream: partial?.tickStream ?? d.tickStream,
|
|
278
|
+
pineWorker: partial?.pineWorker ?? d.pineWorker
|
|
200
279
|
};
|
|
201
280
|
}
|
|
202
281
|
function mergeChartFeatures(current, patch) {
|
|
@@ -209,10 +288,12 @@ function mergeChartFeatures(current, patch) {
|
|
|
209
288
|
indicatorPersist: patch.indicatorPersist ?? current.indicatorPersist,
|
|
210
289
|
smoothPriceUpdate: patch.smoothPriceUpdate ?? current.smoothPriceUpdate,
|
|
211
290
|
smoothPriceDurationMs: patch.smoothPriceDurationMs ?? current.smoothPriceDurationMs,
|
|
291
|
+
pineScript: patch.pineScript !== void 0 ? patch.pineScript : current.pineScript,
|
|
212
292
|
pineEnabled: patch.pineEnabled ?? current.pineEnabled,
|
|
213
293
|
protobuf: patch.protobuf ?? current.protobuf,
|
|
214
294
|
telemetry: patch.telemetry ?? current.telemetry,
|
|
215
|
-
tickStream: patch.tickStream ?? current.tickStream
|
|
295
|
+
tickStream: patch.tickStream ?? current.tickStream,
|
|
296
|
+
pineWorker: patch.pineWorker ?? current.pineWorker
|
|
216
297
|
});
|
|
217
298
|
}
|
|
218
299
|
var PENDING_SYMBOL = "";
|
|
@@ -284,6 +365,7 @@ var ChartController = class {
|
|
|
284
365
|
this.offCrosshair = this.orchestrator.subscribeCrosshair((payload) => {
|
|
285
366
|
this.emit("crosshairChange", payload);
|
|
286
367
|
});
|
|
368
|
+
this.bindPageResumeCatchUp();
|
|
287
369
|
if (this.hasActiveSymbol()) {
|
|
288
370
|
void this.bootstrap(this.loadGeneration);
|
|
289
371
|
} else {
|
|
@@ -306,6 +388,11 @@ var ChartController = class {
|
|
|
306
388
|
drawingManager = null;
|
|
307
389
|
offCrosshair = null;
|
|
308
390
|
features;
|
|
391
|
+
pineIr = null;
|
|
392
|
+
tickAggregator = null;
|
|
393
|
+
catchUpInFlight = false;
|
|
394
|
+
lastCatchUpAt = 0;
|
|
395
|
+
offPageResume = null;
|
|
309
396
|
getFeatures() {
|
|
310
397
|
return { ...this.features };
|
|
311
398
|
}
|
|
@@ -329,6 +416,58 @@ var ChartController = class {
|
|
|
329
416
|
);
|
|
330
417
|
this.drawingManager?.setPersistence(this.features.drawings.persist);
|
|
331
418
|
this.applyDrawingLayer();
|
|
419
|
+
this.recompilePine();
|
|
420
|
+
}
|
|
421
|
+
recompilePine() {
|
|
422
|
+
if (!this.features.pineEnabled || !this.features.pineScript?.trim()) {
|
|
423
|
+
this.pineIr = null;
|
|
424
|
+
this.orchestrator.setPinePlots(null);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const compiled = compilePineLite(this.features.pineScript);
|
|
428
|
+
if (!compiled.ok || !compiled.ir) {
|
|
429
|
+
this.pineIr = null;
|
|
430
|
+
this.orchestrator.setPinePlots(null);
|
|
431
|
+
this.emit("error", { kind: "pine", errors: compiled.errors });
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
this.pineIr = compiled.ir;
|
|
435
|
+
if (this.hasActiveSymbol()) {
|
|
436
|
+
const bars = this.virtualWindow.getBarsForRender();
|
|
437
|
+
if (bars.length > 0) this.applyPinePlots(bars);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
applyPinePlots(bars) {
|
|
441
|
+
if (!this.features.pineEnabled || !this.pineIr) {
|
|
442
|
+
this.orchestrator.setPinePlots(null);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const ir = this.pineIr;
|
|
446
|
+
const useWorker = this.features.pineWorker;
|
|
447
|
+
void runPineLiteAsync(ir, bars, { useWorker }).then((result) => {
|
|
448
|
+
if (this.destroyed || this.pineIr !== ir) return;
|
|
449
|
+
this.orchestrator.setPinePlots(
|
|
450
|
+
result.plots.map((p) => ({
|
|
451
|
+
title: p.title,
|
|
452
|
+
values: p.values,
|
|
453
|
+
color: void 0
|
|
454
|
+
}))
|
|
455
|
+
);
|
|
456
|
+
}).catch((err) => this.emit("error", err));
|
|
457
|
+
}
|
|
458
|
+
trackTelemetry(event, data) {
|
|
459
|
+
if (!this.features.telemetry) return;
|
|
460
|
+
this.emit("telemetry", { event, ...data });
|
|
461
|
+
}
|
|
462
|
+
setLocale(locale) {
|
|
463
|
+
setI18nLocale(locale);
|
|
464
|
+
this.trackTelemetry("locale", { locale });
|
|
465
|
+
return this;
|
|
466
|
+
}
|
|
467
|
+
subscribeBars(handler) {
|
|
468
|
+
const wrapper = (payload) => handler(payload);
|
|
469
|
+
this.on("barUpdate", wrapper);
|
|
470
|
+
return () => this.off("barUpdate", wrapper);
|
|
332
471
|
}
|
|
333
472
|
/** Integrator push: update last candle close (and H/L) without WS. */
|
|
334
473
|
updateLastPrice(price, timeMs = Date.now()) {
|
|
@@ -376,6 +515,7 @@ var ChartController = class {
|
|
|
376
515
|
this.refreshRender(loadGen);
|
|
377
516
|
}
|
|
378
517
|
this.emit("barUpdate", bar);
|
|
518
|
+
this.trackTelemetry("barUpdate", { t: bar.t, partial });
|
|
379
519
|
}
|
|
380
520
|
applyDrawingLayer() {
|
|
381
521
|
if (!this.drawingManager) return;
|
|
@@ -494,6 +634,58 @@ var ChartController = class {
|
|
|
494
634
|
this.orchestrator.scrollToRealtime();
|
|
495
635
|
return this;
|
|
496
636
|
}
|
|
637
|
+
getVisibleRange() {
|
|
638
|
+
return this.orchestrator.getVisibleRange();
|
|
639
|
+
}
|
|
640
|
+
getBarSpace() {
|
|
641
|
+
return this.orchestrator.getBarSpace();
|
|
642
|
+
}
|
|
643
|
+
setBarSpace(px) {
|
|
644
|
+
this.orchestrator.setBarSpace(px);
|
|
645
|
+
return this;
|
|
646
|
+
}
|
|
647
|
+
setVisibleRange(range) {
|
|
648
|
+
this.orchestrator.setVisibleRange(range);
|
|
649
|
+
const { fromMs, toMs } = range;
|
|
650
|
+
if (toMs > fromMs) {
|
|
651
|
+
this.virtualWindow.setVisibleRange({ fromMs, toMs });
|
|
652
|
+
this.visibleRangeInitialized = true;
|
|
653
|
+
}
|
|
654
|
+
return this;
|
|
655
|
+
}
|
|
656
|
+
scrollToTimestamp(tsMs, animationMs) {
|
|
657
|
+
this.orchestrator.scrollToTimestamp(tsMs, animationMs);
|
|
658
|
+
return this;
|
|
659
|
+
}
|
|
660
|
+
async reloadHistory() {
|
|
661
|
+
if (!this.hasActiveSymbol()) return this;
|
|
662
|
+
const savedRange = this.getVisibleRange();
|
|
663
|
+
const savedBarSpace = this.getBarSpace();
|
|
664
|
+
const loadGen = this.loadGeneration;
|
|
665
|
+
const symbol = this.store.symbol;
|
|
666
|
+
const interval = this.store.interval;
|
|
667
|
+
try {
|
|
668
|
+
const history = await fetchChartHistory(this.options.dataProvider, {
|
|
669
|
+
mode: "loadMore",
|
|
670
|
+
symbol,
|
|
671
|
+
interval,
|
|
672
|
+
endTime: Date.now(),
|
|
673
|
+
limit: 500
|
|
674
|
+
});
|
|
675
|
+
if (!this.isLoadGenerationCurrent(loadGen)) return this;
|
|
676
|
+
if (this.store.symbol !== symbol || this.store.interval !== interval) return this;
|
|
677
|
+
if (history.bars.length === 0) return this;
|
|
678
|
+
await this.store.mergeBars(history.bars.map((bar) => ({ bar, source: "rest" })));
|
|
679
|
+
if (!this.isLoadGenerationCurrent(loadGen)) return this;
|
|
680
|
+
this.orchestrator.preserveViewportOnNextSetBars();
|
|
681
|
+
this.refreshRender(loadGen);
|
|
682
|
+
if (savedBarSpace > 0) this.setBarSpace(savedBarSpace);
|
|
683
|
+
if (savedRange) this.setVisibleRange(savedRange);
|
|
684
|
+
} catch (err) {
|
|
685
|
+
this.emit("error", err);
|
|
686
|
+
}
|
|
687
|
+
return this;
|
|
688
|
+
}
|
|
497
689
|
setLogScale(enabled) {
|
|
498
690
|
this.orchestrator.setLogScale(enabled);
|
|
499
691
|
return this;
|
|
@@ -523,12 +715,15 @@ var ChartController = class {
|
|
|
523
715
|
destroy() {
|
|
524
716
|
if (this.destroyed) return;
|
|
525
717
|
this.destroyed = true;
|
|
718
|
+
this.offPageResume?.();
|
|
719
|
+
this.offPageResume = null;
|
|
526
720
|
this.offCrosshair?.();
|
|
527
721
|
this.offCrosshair = null;
|
|
528
722
|
this.resizeObserver.disconnect();
|
|
529
723
|
this.drawingManager?.destroy();
|
|
530
724
|
void this.teardownSubscription();
|
|
531
725
|
this.orchestrator.destroy();
|
|
726
|
+
terminatePineWorker();
|
|
532
727
|
this.emit("destroyed", { chartId: this.options.chartId ?? "default" });
|
|
533
728
|
this.emit("connectionChange", "disconnected");
|
|
534
729
|
}
|
|
@@ -548,7 +743,13 @@ var ChartController = class {
|
|
|
548
743
|
const symbol = this.store.symbol;
|
|
549
744
|
const interval = this.store.interval;
|
|
550
745
|
const endTime = Date.now();
|
|
551
|
-
|
|
746
|
+
if (this.features.protobuf) {
|
|
747
|
+
this.emit("error", {
|
|
748
|
+
code: "PROTOBUF_UNAVAILABLE",
|
|
749
|
+
message: "Protobuf encoding requires protocol v1.1 (not in 1.0.0)"
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
const history = await fetchChartHistory(this.options.dataProvider, {
|
|
552
753
|
mode: "loadMore",
|
|
553
754
|
symbol,
|
|
554
755
|
interval,
|
|
@@ -566,16 +767,22 @@ var ChartController = class {
|
|
|
566
767
|
});
|
|
567
768
|
this.emit("intervalChange", interval);
|
|
568
769
|
const streamMode = this.features.tickStream ? "bar+tick" : this.features.streamMode;
|
|
770
|
+
const tickOnly = streamMode === "tick";
|
|
569
771
|
const params = {
|
|
570
772
|
symbol,
|
|
571
773
|
interval,
|
|
572
|
-
channels: this.features.tickStream ? ["bar", "tick"] : ["bar"],
|
|
774
|
+
channels: tickOnly ? ["tick"] : this.features.tickStream ? ["bar", "tick"] : ["bar"],
|
|
573
775
|
streamMode
|
|
574
776
|
};
|
|
777
|
+
this.tickAggregator = tickOnly ? new TickAggregator(interval, (bar, partial) => {
|
|
778
|
+
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
779
|
+
if (this.store.symbol !== symbol || this.store.interval !== interval) return;
|
|
780
|
+
void this.applyRealtimeBar(bar, partial, loadGen);
|
|
781
|
+
}) : null;
|
|
575
782
|
await this.options.dataProvider.connect?.();
|
|
576
783
|
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
577
784
|
const sub = await this.options.dataProvider.subscribe(params, {
|
|
578
|
-
onBar: (bar, meta) => {
|
|
785
|
+
onBar: tickOnly ? void 0 : (bar, meta) => {
|
|
579
786
|
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
580
787
|
if (this.store.symbol !== symbol || this.store.interval !== interval) return;
|
|
581
788
|
void this.applyRealtimeBar(bar, meta.partial, loadGen);
|
|
@@ -583,10 +790,19 @@ var ChartController = class {
|
|
|
583
790
|
onTick: (tick) => {
|
|
584
791
|
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
585
792
|
if (this.store.symbol !== symbol || this.store.interval !== interval) return;
|
|
793
|
+
if (this.tickAggregator) {
|
|
794
|
+
this.tickAggregator.ingest(tick);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
586
797
|
const bar = this.buildBarFromPrice(tick.price, tick.t);
|
|
587
798
|
void this.applyRealtimeBar(bar, true, loadGen);
|
|
588
799
|
},
|
|
589
|
-
onConnectionChange: (state) =>
|
|
800
|
+
onConnectionChange: (state) => {
|
|
801
|
+
this.emit("connectionChange", state);
|
|
802
|
+
if (state === "connected" && this.subscriptionId != null) {
|
|
803
|
+
void this.catchUpMissedBars();
|
|
804
|
+
}
|
|
805
|
+
},
|
|
590
806
|
onError: (err) => this.emit("error", err)
|
|
591
807
|
});
|
|
592
808
|
if (!this.isLoadGenerationCurrent(loadGen)) {
|
|
@@ -596,11 +812,73 @@ var ChartController = class {
|
|
|
596
812
|
this.subscriptionId = sub.id;
|
|
597
813
|
}
|
|
598
814
|
async teardownSubscription() {
|
|
815
|
+
this.tickAggregator?.flush();
|
|
816
|
+
this.tickAggregator = null;
|
|
599
817
|
if (this.subscriptionId) {
|
|
600
818
|
await this.options.dataProvider.unsubscribe(this.subscriptionId);
|
|
601
819
|
this.subscriptionId = null;
|
|
602
820
|
}
|
|
603
821
|
}
|
|
822
|
+
bindPageResumeCatchUp() {
|
|
823
|
+
if (typeof document === "undefined") return;
|
|
824
|
+
const onResume = () => {
|
|
825
|
+
if (document.visibilityState !== "visible") return;
|
|
826
|
+
void this.catchUpMissedBars();
|
|
827
|
+
};
|
|
828
|
+
document.addEventListener("visibilitychange", onResume);
|
|
829
|
+
const cleanups = [
|
|
830
|
+
() => document.removeEventListener("visibilitychange", onResume)
|
|
831
|
+
];
|
|
832
|
+
if (typeof window !== "undefined") {
|
|
833
|
+
const onFocus = () => void this.catchUpMissedBars();
|
|
834
|
+
window.addEventListener("focus", onFocus);
|
|
835
|
+
cleanups.push(() => window.removeEventListener("focus", onFocus));
|
|
836
|
+
}
|
|
837
|
+
this.offPageResume = () => {
|
|
838
|
+
for (const fn of cleanups) fn();
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Backfill bars missed while the tab/window was backgrounded or WS delivery paused.
|
|
843
|
+
*/
|
|
844
|
+
async catchUpMissedBars() {
|
|
845
|
+
if (this.destroyed || !this.hasActiveSymbol()) return;
|
|
846
|
+
const now = Date.now();
|
|
847
|
+
if (now - this.lastCatchUpAt < 400) return;
|
|
848
|
+
if (this.catchUpInFlight) return;
|
|
849
|
+
const times = this.store.sortedTimes;
|
|
850
|
+
if (times.length === 0) return;
|
|
851
|
+
const lastT = times[times.length - 1];
|
|
852
|
+
const interval = this.store.interval;
|
|
853
|
+
const to = now + intervalMs2(interval);
|
|
854
|
+
if (to <= lastT) return;
|
|
855
|
+
this.catchUpInFlight = true;
|
|
856
|
+
this.lastCatchUpAt = now;
|
|
857
|
+
const loadGen = this.loadGeneration;
|
|
858
|
+
const symbol = this.store.symbol;
|
|
859
|
+
try {
|
|
860
|
+
const history = await fetchChartHistory(this.options.dataProvider, {
|
|
861
|
+
mode: "range",
|
|
862
|
+
symbol,
|
|
863
|
+
interval,
|
|
864
|
+
from: lastT,
|
|
865
|
+
to
|
|
866
|
+
});
|
|
867
|
+
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
868
|
+
if (this.store.symbol !== symbol || this.store.interval !== interval) return;
|
|
869
|
+
if (history.bars.length === 0) return;
|
|
870
|
+
await this.store.mergeBars(
|
|
871
|
+
history.bars.map((bar) => ({ bar, source: "rest" }))
|
|
872
|
+
);
|
|
873
|
+
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
874
|
+
this.orchestrator.preserveViewportOnNextSetBars();
|
|
875
|
+
this.refreshRender(loadGen);
|
|
876
|
+
} catch (err) {
|
|
877
|
+
this.emit("error", err);
|
|
878
|
+
} finally {
|
|
879
|
+
this.catchUpInFlight = false;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
604
882
|
async maybeLoadMore() {
|
|
605
883
|
if (this.destroyed || this.loadingMore) return;
|
|
606
884
|
const loadGen = this.loadGeneration;
|
|
@@ -610,7 +888,10 @@ var ChartController = class {
|
|
|
610
888
|
try {
|
|
611
889
|
for (const req of reqs) {
|
|
612
890
|
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
613
|
-
const history = await
|
|
891
|
+
const history = await fetchChartHistory(
|
|
892
|
+
this.options.dataProvider,
|
|
893
|
+
toHistoryQuery(req)
|
|
894
|
+
);
|
|
614
895
|
if (!this.isLoadGenerationCurrent(loadGen)) return;
|
|
615
896
|
if (history.bars.length === 0) continue;
|
|
616
897
|
await this.store.mergeBars(
|
|
@@ -639,7 +920,12 @@ var ChartController = class {
|
|
|
639
920
|
}
|
|
640
921
|
const bars = this.virtualWindow.getBarsForRender();
|
|
641
922
|
if (bars.length === 0) return;
|
|
642
|
-
this.
|
|
923
|
+
const gaps = this.features.gaps.whitespace ? computeGapStartTimes(
|
|
924
|
+
bars.map((b) => b.t),
|
|
925
|
+
this.store.interval
|
|
926
|
+
) : void 0;
|
|
927
|
+
this.orchestrator.setBars(bars, gaps);
|
|
928
|
+
this.applyPinePlots(bars);
|
|
643
929
|
this.drawingManager?.redraw();
|
|
644
930
|
this.emit("visibleRangeChange", {
|
|
645
931
|
from: bars[0].t,
|
|
@@ -671,6 +957,7 @@ function toHistoryQuery(req) {
|
|
|
671
957
|
|
|
672
958
|
// src/demo-presets.ts
|
|
673
959
|
import { DEFAULT_INDICATOR_CONFIG } from "@coderyo/indicators";
|
|
960
|
+
import { PINE_SAMPLE_SCRIPT } from "@coderyo/pine-lite";
|
|
674
961
|
function createDemoChartFeatures(opts) {
|
|
675
962
|
return {
|
|
676
963
|
fetchPolicy: "lazy-left-only",
|
|
@@ -681,7 +968,9 @@ function createDemoChartFeatures(opts) {
|
|
|
681
968
|
indicatorPersist: true,
|
|
682
969
|
smoothPriceUpdate: true,
|
|
683
970
|
smoothPriceDurationMs: 150,
|
|
684
|
-
tickStream: true
|
|
971
|
+
tickStream: true,
|
|
972
|
+
pineEnabled: true,
|
|
973
|
+
pineScript: PINE_SAMPLE_SCRIPT
|
|
685
974
|
};
|
|
686
975
|
}
|
|
687
976
|
function createDemoChartOptions(base) {
|
|
@@ -728,6 +1017,24 @@ function wrap(controller, beforeDestroy) {
|
|
|
728
1017
|
controller.scrollToRealtime();
|
|
729
1018
|
return wrap(controller, beforeDestroy);
|
|
730
1019
|
},
|
|
1020
|
+
getVisibleRange: () => controller.getVisibleRange(),
|
|
1021
|
+
getBarSpace: () => controller.getBarSpace(),
|
|
1022
|
+
setBarSpace: (px) => {
|
|
1023
|
+
controller.setBarSpace(px);
|
|
1024
|
+
return wrap(controller, beforeDestroy);
|
|
1025
|
+
},
|
|
1026
|
+
setVisibleRange: (range) => {
|
|
1027
|
+
controller.setVisibleRange(range);
|
|
1028
|
+
return wrap(controller, beforeDestroy);
|
|
1029
|
+
},
|
|
1030
|
+
scrollToTimestamp: (tsMs, animationMs) => {
|
|
1031
|
+
controller.scrollToTimestamp(tsMs, animationMs);
|
|
1032
|
+
return wrap(controller, beforeDestroy);
|
|
1033
|
+
},
|
|
1034
|
+
reloadHistory: async () => {
|
|
1035
|
+
await controller.reloadHistory();
|
|
1036
|
+
return wrap(controller, beforeDestroy);
|
|
1037
|
+
},
|
|
731
1038
|
resize: (s) => {
|
|
732
1039
|
controller.resize(s);
|
|
733
1040
|
return wrap(controller, beforeDestroy);
|
|
@@ -779,6 +1086,11 @@ function wrap(controller, beforeDestroy) {
|
|
|
779
1086
|
return wrap(controller, beforeDestroy);
|
|
780
1087
|
},
|
|
781
1088
|
hasActiveSymbol: () => controller.hasActiveSymbol(),
|
|
1089
|
+
setLocale: (locale) => {
|
|
1090
|
+
controller.setLocale(locale);
|
|
1091
|
+
return wrap(controller, beforeDestroy);
|
|
1092
|
+
},
|
|
1093
|
+
subscribeBars: (handler) => controller.subscribeBars(handler),
|
|
782
1094
|
destroy: () => {
|
|
783
1095
|
controller.destroy();
|
|
784
1096
|
beforeDestroy?.();
|
|
@@ -803,16 +1115,28 @@ function createChart(target, options) {
|
|
|
803
1115
|
}
|
|
804
1116
|
return chart;
|
|
805
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
// src/index.ts
|
|
1120
|
+
import {
|
|
1121
|
+
compilePineLite as compilePineLite2,
|
|
1122
|
+
runPineLite,
|
|
1123
|
+
PINE_SAMPLE_SCRIPT as PINE_SAMPLE_SCRIPT2,
|
|
1124
|
+
PINE_EDITOR_DEFAULT
|
|
1125
|
+
} from "@coderyo/pine-lite";
|
|
806
1126
|
export {
|
|
807
1127
|
ChartController,
|
|
808
1128
|
DEFAULT_CHART_FEATURES,
|
|
809
1129
|
PENDING_SYMBOL,
|
|
1130
|
+
PINE_EDITOR_DEFAULT,
|
|
1131
|
+
PINE_SAMPLE_SCRIPT2 as PINE_SAMPLE_SCRIPT,
|
|
810
1132
|
TRADVIEW_API_VERSION,
|
|
811
1133
|
TRADVIEW_VERSION,
|
|
1134
|
+
compilePineLite2 as compilePineLite,
|
|
812
1135
|
createChart,
|
|
813
1136
|
createDemoChartFeatures,
|
|
814
1137
|
createDemoChartOptions,
|
|
815
1138
|
resolveChartFeatures,
|
|
1139
|
+
runPineLite,
|
|
816
1140
|
wireChartBridge
|
|
817
1141
|
};
|
|
818
1142
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bridge-wire.ts","../src/version.ts","../src/chart-controller.ts","../src/chart-features.ts","../src/demo-presets.ts","../src/create-chart.ts"],"sourcesContent":["import type { BridgeAdapter } from '@coderyo/bridge';\nimport {\n BRIDGE_SCHEMA_VERSION,\n isBridgeInbound,\n type BridgeInboundType,\n type BridgeOutboundType,\n} from '@coderyo/bridge';\nimport type { Interval } from '@coderyo/data';\nimport type { CrosshairPayload } from '@coderyo/renderer-lite';\nimport type { ChartController, ChartEvent } from './chart-controller.js';\nimport type { IChart } from './create-chart.js';\nimport { TRADVIEW_VERSION } from './version.js';\n\nexport const TRADVIEW_API_VERSION = 1 as const;\n\nconst CHART_EVENT_TO_BRIDGE: Partial<Record<ChartEvent, BridgeOutboundType>> = {\n connectionChange: 'chart.connectionChange',\n visibleRangeChange: 'chart.visibleRange',\n error: 'chart.error',\n symbolChange: 'chart.symbol',\n intervalChange: 'chart.interval',\n crosshairChange: 'chart.crosshair',\n destroyed: 'chart.destroyed',\n};\n\nexport interface WireChartBridgeOptions {\n controller: ChartController;\n chart: IChart;\n bridge: BridgeAdapter;\n chartId?: string;\n /** Allowlist of outbound bridge events; default all mapped events. */\n outboundEvents?: BridgeOutboundType[];\n crosshairThrottleMs?: number;\n}\n\nexport function wireChartBridge(opts: WireChartBridgeOptions): () => void {\n const chartId = opts.chartId ?? `chart-${Date.now()}`;\n const { bridge, chart, controller } = opts;\n const allow = opts.outboundEvents ? new Set(opts.outboundEvents) : null;\n\n const shouldPost = (type: BridgeOutboundType): boolean =>\n allow === null || allow.has(type);\n\n const post = (type: BridgeOutboundType, payload: Record<string, unknown>) => {\n if (!shouldPost(type)) return;\n bridge.post({ type, payload });\n };\n\n post('chart.ready', {\n chartId,\n bridgeSchemaVersion: BRIDGE_SCHEMA_VERSION,\n apiVersion: TRADVIEW_API_VERSION,\n version: TRADVIEW_VERSION,\n });\n\n const postResize = () => {\n const el = controller.getContainer();\n const r = el.getBoundingClientRect();\n post('chart.resize', {\n chartId,\n width: Math.round(r.width),\n height: Math.round(r.height),\n });\n };\n if (shouldPost('chart.resize')) postResize();\n\n let crosshairTimer: ReturnType<typeof setTimeout> | null = null;\n let crosshairPending: CrosshairPayload | null = null;\n const throttleMs = opts.crosshairThrottleMs ?? 0;\n\n const flushCrosshair = () => {\n crosshairTimer = null;\n const p = crosshairPending;\n crosshairPending = null;\n if (!p) return;\n post('chart.crosshair', {\n chartId,\n time: p.time,\n price: p.price,\n ohlcv: p.ohlcv,\n symbol: controller.getSymbol(),\n interval: controller.getInterval(),\n });\n };\n\n const handlers = new Map<ChartEvent, (p?: unknown) => void>();\n\n handlers.set('connectionChange', (state) => {\n post('chart.connectionChange', { chartId, state });\n });\n handlers.set('visibleRangeChange', (range) => {\n const r = range as { from?: number; to?: number };\n post('chart.visibleRange', { chartId, from: r.from, to: r.to });\n });\n handlers.set('error', (err) => {\n const e = err as { code?: string; message?: string };\n post('chart.error', {\n chartId,\n code: e?.code ?? 'UNKNOWN',\n message: e?.message ?? String(err),\n });\n });\n handlers.set('symbolChange', (symbol) => {\n post('chart.symbol', { chartId, symbol: String(symbol ?? '') });\n });\n handlers.set('intervalChange', (interval) => {\n post('chart.interval', { chartId, interval: String(interval ?? '') });\n });\n handlers.set('crosshairChange', (payload) => {\n const p = payload as CrosshairPayload | null;\n if (!p) return;\n if (throttleMs <= 0) {\n post('chart.crosshair', {\n chartId,\n time: p.time,\n price: p.price,\n ohlcv: p.ohlcv,\n symbol: controller.getSymbol(),\n interval: controller.getInterval(),\n });\n return;\n }\n crosshairPending = p;\n if (!crosshairTimer) {\n crosshairTimer = setTimeout(flushCrosshair, throttleMs);\n }\n });\n handlers.set('destroyed', () => {\n post('chart.destroyed', { chartId });\n });\n\n for (const [ev, fn] of handlers) {\n const bridgeType = CHART_EVENT_TO_BRIDGE[ev];\n if (!bridgeType || shouldPost(bridgeType)) {\n chart.on(ev, fn);\n }\n }\n\n const offHost = bridge.onMessage((msg) => {\n if (!isBridgeInbound(msg)) return;\n const p = msg.payload ?? {};\n switch (msg.type as BridgeInboundType) {\n case 'host.setSymbol':\n if (typeof p.symbol === 'string') chart.setSymbol(p.symbol);\n break;\n case 'host.setInterval':\n if (typeof p.interval === 'string') chart.setInterval(p.interval as Interval);\n break;\n case 'host.setTheme':\n if (p.theme === 'dark' || p.theme === 'light') chart.setTheme(p.theme);\n break;\n case 'host.setShowGrid':\n if (typeof p.showGrid === 'boolean') chart.setShowGrid(p.showGrid);\n break;\n case 'host.fitContent':\n chart.fitContent();\n break;\n case 'host.scrollToRealtime':\n chart.scrollToRealtime();\n break;\n case 'host.resize':\n chart.resize({\n width: typeof p.width === 'number' ? p.width : undefined,\n height: typeof p.height === 'number' ? p.height : undefined,\n });\n postResize();\n break;\n case 'host.destroy':\n chart.destroy();\n break;\n default:\n break;\n }\n });\n\n return () => {\n if (crosshairTimer) clearTimeout(crosshairTimer);\n offHost();\n for (const [ev, fn] of handlers) chart.off(ev, fn);\n };\n}","/** Synced by scripts/sync-versions.mjs from repo VERSION file */\nexport const TRADVIEW_VERSION = '1.0.0-rc.3' as const;\n","import type { DrawingRecord, DrawingStyleMeta } from '@coderyo/drawings';\nimport type { IndicatorConfig } from '@coderyo/indicators';\n\nimport type {\n Bar,\n DataProvider,\n HistoryQuery,\n Interval,\n RealtimeStreamMode,\n SubscribeParams,\n SymbolResolver,\n} from '@coderyo/data';\nimport { floorBarOpenTime } from '@coderyo/data';\nimport type { HistoryRequest } from '@coderyo/virtual-window';\nimport { parseInterval } from '@coderyo/data';\nimport { BarStore } from '@coderyo/series';\nimport { VirtualWindow, type FetchPolicy } from '@coderyo/virtual-window';\nimport { DrawingManager } from '@coderyo/drawings';\nimport { PaneOrchestrator } from '@coderyo/renderer-lite';\nimport {\n mergeChartFeatures,\n PENDING_SYMBOL,\n resolveChartFeatures,\n type ChartFeatures,\n type ResolvedChartFeatures,\n} from './chart-features.js';\n\nexport interface ChartOptions {\n width?: number;\n height?: number;\n theme?: 'dark' | 'light';\n interval?: Interval;\n /** Omit for empty chart until setSymbol(). */\n symbol?: string;\n chartId?: string;\n /** Host element below main chart for MACD/RSI/KDJ panes (from ui-shell layout). */\n indicatorHost?: HTMLElement;\n dataProvider: DataProvider;\n /** Integrator feature flags (minimal defaults). */\n features?: ChartFeatures;\n /** @deprecated Use features.fetchPolicy */\n fetchPolicy?: FetchPolicy;\n scaleMode?: 'linear' | 'log';\n /** Grid lines on chart panes (default false). */\n showGrid?: boolean;\n symbolResolver?: SymbolResolver;\n drawingDefaults?: { returnToCursorAfterDraw?: boolean };\n /** @deprecated Use features.indicators */\n indicatorConfig?: IndicatorConfig;\n}\n\nexport type ChartEvent =\n | 'connectionChange'\n | 'barUpdate'\n | 'error'\n | 'visibleRangeChange'\n | 'symbolChange'\n | 'intervalChange'\n | 'crosshairChange'\n | 'destroyed'\n | 'drawingSelectionChange'\n | 'drawingContextMenu'\n | 'requestCursorTool'\n | 'featuresChange';\n\ntype EventHandler = (payload?: unknown) => void;\n\nexport class ChartController {\n private readonly store: BarStore;\n private readonly virtualWindow: VirtualWindow;\n private readonly orchestrator: PaneOrchestrator;\n private readonly handlers = new Map<ChartEvent, Set<EventHandler>>();\n private subscriptionId: string | null = null;\n private destroyed = false;\n private readonly resizeObserver: ResizeObserver;\n private loadingMore = false;\n private visibleRangeInitialized = false;\n /** Bumped on symbol/interval change to drop stale bootstrap / loadMore / WS merges. */\n private loadGeneration = 0;\n private drawingManager: DrawingManager | null = null;\n private offCrosshair: (() => void) | null = null;\n private features: ResolvedChartFeatures;\n\n constructor(\n private readonly container: HTMLElement,\n private readonly options: ChartOptions,\n ) {\n this.features = resolveChartFeatures({\n ...options.features,\n fetchPolicy: options.features?.fetchPolicy ?? options.fetchPolicy,\n indicators:\n options.features?.indicators !== undefined\n ? options.features.indicators\n : options.indicatorConfig !== undefined\n ? options.indicatorConfig\n : undefined,\n });\n\n const symbol = options.symbol?.trim() || PENDING_SYMBOL;\n const interval = parseInterval(options.interval ?? '1h');\n const fetchPolicy = this.features.gaps.fillVisibleHoles\n ? 'fill-visible-holes'\n : this.features.fetchPolicy;\n\n this.store = new BarStore(symbol || PENDING_SYMBOL, interval);\n this.virtualWindow = new VirtualWindow(this.store, { fetchPolicy });\n this.orchestrator = new PaneOrchestrator({\n container,\n indicatorRoot: options.indicatorHost,\n theme: options.theme ?? 'dark',\n scaleMode: options.scaleMode ?? 'linear',\n showGrid: options.showGrid ?? false,\n indicatorConfig: this.features.indicators,\n smoothPriceUpdate: this.features.smoothPriceUpdate,\n smoothPriceDurationMs: this.features.smoothPriceDurationMs,\n });\n\n if (options.width) container.style.width = `${options.width}px`;\n if (options.height) container.style.height = `${options.height}px`;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.destroyed) this.resize();\n });\n this.resizeObserver.observe(container);\n\n this.orchestrator.bus.subscribeTransform(() => {\n const bus = this.orchestrator.bus;\n if (bus.visibleToMs > bus.visibleFromMs) {\n this.virtualWindow.setVisibleRange({\n fromMs: bus.visibleFromMs,\n toMs: bus.visibleToMs,\n });\n this.visibleRangeInitialized = true;\n }\n void this.maybeLoadMore();\n this.drawingManager?.redraw();\n });\n\n const overlay = this.orchestrator.getOverlayCanvas();\n if (overlay) {\n this.orchestrator.setOverlayPointerEvents('none');\n this.drawingManager = new DrawingManager({\n canvas: overlay,\n interactionHost: overlay.parentElement ?? undefined,\n chartId: options.chartId ?? 'default',\n symbol,\n interval,\n priceToY: (p) => this.orchestrator.priceToY(p),\n timeToX: (t) => this.orchestrator.timeToX(t),\n xToTime: (x) => this.orchestrator.xToTime(x),\n yToPrice: (y) => this.orchestrator.yToPrice(y),\n returnToCursorAfterDraw: options.drawingDefaults?.returnToCursorAfterDraw ?? false,\n onRequestCursorTool: () => this.emit('requestCursorTool'),\n onSelectionChange: (id, record) =>\n this.emit('drawingSelectionChange', { id, record }),\n onContextMenu: (payload) => this.emit('drawingContextMenu', payload),\n });\n this.drawingManager.setPersistence(this.features.drawings.persist);\n this.applyDrawingLayer();\n }\n\n this.offCrosshair = this.orchestrator.subscribeCrosshair((payload) => {\n this.emit('crosshairChange', payload);\n });\n\n if (this.hasActiveSymbol()) {\n void this.bootstrap(this.loadGeneration);\n } else {\n this.emit('connectionChange', 'disconnected');\n }\n }\n\n getFeatures(): ResolvedChartFeatures {\n return { ...this.features };\n }\n\n setFeatures(patch: ChartFeatures): this {\n this.features = mergeChartFeatures(this.features, patch);\n this.applyFeatures();\n this.emit('featuresChange', this.getFeatures());\n return this;\n }\n\n hasActiveSymbol(): boolean {\n const s = this.store.symbol;\n return s.length > 0 && s !== PENDING_SYMBOL;\n }\n\n private applyFeatures(): void {\n const fetchPolicy = this.features.gaps.fillVisibleHoles\n ? 'fill-visible-holes'\n : this.features.fetchPolicy;\n this.virtualWindow.setFetchPolicy(fetchPolicy);\n\n this.orchestrator.setIndicatorConfig(this.features.indicators);\n this.orchestrator.setSmoothPriceUpdate(\n this.features.smoothPriceUpdate,\n this.features.smoothPriceDurationMs,\n );\n this.drawingManager?.setPersistence(this.features.drawings.persist);\n this.applyDrawingLayer();\n }\n\n /** Integrator push: update last candle close (and H/L) without WS. */\n updateLastPrice(price: number, timeMs = Date.now()): this {\n if (!this.hasActiveSymbol() || this.destroyed) return this;\n const bar = this.buildBarFromPrice(price, timeMs);\n void this.applyRealtimeBar(bar, true);\n return this;\n }\n\n private buildBarFromPrice(price: number, timeMs: number): Bar {\n const interval = this.store.interval;\n const open = floorBarOpenTime(timeMs, interval);\n const times = this.store.sortedTimes;\n const lastT = times.length > 0 ? times[times.length - 1]! : undefined;\n const existing = lastT !== undefined ? this.store.getBar(lastT) : undefined;\n\n if (existing && existing.t === open) {\n return {\n ...existing,\n c: price,\n h: Math.max(existing.h, price),\n l: Math.min(existing.l, price),\n };\n }\n\n const prevClose = existing?.c ?? price;\n return {\n t: open,\n o: prevClose,\n h: Math.max(prevClose, price),\n l: Math.min(prevClose, price),\n c: price,\n v: existing?.v ?? 0,\n };\n }\n\n private async applyRealtimeBar(\n bar: Bar,\n partial: boolean,\n loadGen = this.loadGeneration,\n ): Promise<void> {\n await this.store.mergeRealtime({ bar, partial });\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const bars = this.virtualWindow.getBarsForRender();\n const last = bars[bars.length - 1];\n if (last && this.features.smoothPriceUpdate) {\n this.orchestrator.updateLastBar(last, {\n smooth: true,\n durationMs: this.features.smoothPriceDurationMs,\n });\n this.drawingManager?.redraw();\n } else {\n this.refreshRender(loadGen);\n }\n this.emit('barUpdate', bar);\n }\n\n private applyDrawingLayer(): void {\n if (!this.drawingManager) return;\n this.drawingManager.setLayerVisible(this.features.drawings.layer);\n this.syncOverlayPointerEvents();\n }\n\n private syncOverlayPointerEvents(): void {\n if (!this.drawingManager) return;\n const layer = this.features.drawings.layer;\n if (!layer) {\n this.orchestrator.setOverlayPointerEvents('none');\n return;\n }\n const tool = this.drawingManager.getTool();\n this.orchestrator.setOverlayPointerEvents(tool === 'cursor' ? 'none' : 'auto');\n }\n\n getContainer(): HTMLElement {\n return this.container;\n }\n\n getSymbol(): string {\n return this.store.symbol;\n }\n\n getInterval(): Interval {\n return this.store.interval;\n }\n\n async searchSymbols(query: string): Promise<import('@coderyo/data').SymbolSearchHit[]> {\n const resolver = this.options.symbolResolver;\n if (resolver?.search) return resolver.search(query);\n if (this.options.dataProvider.searchSymbols) {\n return this.options.dataProvider.searchSymbols(query);\n }\n return [];\n }\n\n async resolveSymbol(symbol: string): Promise<import('@coderyo/data').SymbolInfo | null> {\n if (this.options.symbolResolver) {\n return this.options.symbolResolver.resolve(symbol);\n }\n return { symbol };\n }\n\n on(event: ChartEvent, handler: EventHandler): this {\n if (!this.handlers.has(event)) this.handlers.set(event, new Set());\n this.handlers.get(event)!.add(handler);\n return this;\n }\n\n off(event: ChartEvent, handler: EventHandler): this {\n this.handlers.get(event)?.delete(handler);\n return this;\n }\n\n resize(size?: { width?: number; height?: number }): this {\n if (size?.width) this.container.style.width = `${size.width}px`;\n if (size?.height) this.container.style.height = `${size.height}px`;\n this.orchestrator.resize();\n return this;\n }\n\n setDrawingTool(tool: import('@coderyo/drawings').DrawingTool): this {\n this.drawingManager?.setTool(tool);\n this.syncOverlayPointerEvents();\n return this;\n }\n\n deleteSelectedDrawing(): boolean {\n return this.drawingManager?.deleteSelected() ?? false;\n }\n\n copySelectedDrawing(): DrawingRecord | null {\n return this.drawingManager?.copySelected() ?? null;\n }\n\n toggleLockSelectedDrawing(): boolean {\n return this.drawingManager?.toggleLockSelected() ?? false;\n }\n\n updateSelectedDrawingStyle(patch: DrawingStyleMeta): void {\n this.drawingManager?.updateSelectedStyle(patch);\n }\n\n deselectDrawing(): void {\n this.drawingManager?.deselect();\n }\n\n setIndicatorConfig(config: IndicatorConfig | null): void {\n this.features = mergeChartFeatures(this.features, { indicators: config });\n this.orchestrator.setIndicatorConfig(config);\n this.emit('featuresChange', this.getFeatures());\n }\n\n setReturnToCursorAfterDraw(v: boolean): void {\n this.drawingManager?.setReturnToCursorAfterDraw(v);\n }\n\n async setSymbol(symbol: string): Promise<void> {\n const trimmed = symbol.trim();\n if (!trimmed) return;\n const gen = this.beginDataContextChange();\n await this.teardownSubscription();\n await this.store.setSymbolInterval(trimmed, this.store.interval);\n this.drawingManager?.setContext(symbol, this.store.interval);\n const info = await this.resolveSymbol(symbol);\n await this.bootstrap(gen);\n this.emit('symbolChange', info ?? { symbol });\n }\n\n async setInterval(interval: Interval): Promise<void> {\n const gen = this.beginDataContextChange();\n await this.teardownSubscription();\n await this.store.setSymbolInterval(this.store.symbol, interval);\n this.drawingManager?.setContext(this.store.symbol, interval);\n if (this.hasActiveSymbol()) {\n await this.bootstrap(gen);\n }\n }\n\n setTheme(theme: 'dark' | 'light'): this {\n this.orchestrator.setTheme(theme);\n return this;\n }\n\n setShowGrid(show: boolean): this {\n this.orchestrator.setShowGrid(show);\n return this;\n }\n\n fitContent(): this {\n this.orchestrator.fitContent();\n return this;\n }\n\n scrollToRealtime(): this {\n this.orchestrator.scrollToRealtime();\n return this;\n }\n\n setLogScale(enabled: boolean): this {\n this.orchestrator.setLogScale(enabled);\n return this;\n }\n\n setFullscreen(_enabled: boolean): this {\n if (_enabled && this.container.requestFullscreen) {\n void this.container.requestFullscreen();\n } else if (document.fullscreenElement) {\n void document.exitFullscreen();\n }\n return this;\n }\n\n async exportImage(opts?: { pixelRatio?: number }): Promise<Blob> {\n const canvas = this.container.querySelector('canvas');\n if (!canvas) throw new Error('No canvas to export');\n const scale = opts?.pixelRatio ?? 2;\n const exportCanvas = document.createElement('canvas');\n exportCanvas.width = canvas.width * scale;\n exportCanvas.height = canvas.height * scale;\n const ctx = exportCanvas.getContext('2d')!;\n ctx.scale(scale, scale);\n ctx.drawImage(canvas, 0, 0);\n return new Promise((resolve, reject) => {\n exportCanvas.toBlob((b) => (b ? resolve(b) : reject(new Error('export failed'))), 'image/png');\n });\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.offCrosshair?.();\n this.offCrosshair = null;\n this.resizeObserver.disconnect();\n this.drawingManager?.destroy();\n void this.teardownSubscription();\n this.orchestrator.destroy();\n this.emit('destroyed', { chartId: this.options.chartId ?? 'default' });\n this.emit('connectionChange', 'disconnected');\n }\n\n private beginDataContextChange(): number {\n this.loadGeneration += 1;\n this.visibleRangeInitialized = false;\n this.virtualWindow.setVisibleRange({ fromMs: 0, toMs: 0 });\n this.orchestrator.resetViewState();\n this.orchestrator.clearBars();\n return this.loadGeneration;\n }\n\n private isLoadGenerationCurrent(gen: number): boolean {\n return !this.destroyed && gen === this.loadGeneration;\n }\n\n private async bootstrap(loadGen: number): Promise<void> {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const symbol = this.store.symbol;\n const interval = this.store.interval;\n const endTime = Date.now();\n const history = await this.options.dataProvider.getHistory({\n mode: 'loadMore',\n symbol,\n interval,\n endTime,\n limit: 500,\n });\n\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n\n await this.store.mergeBars(history.bars.map((bar) => ({ bar })));\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.refreshRender(loadGen);\n void this.resolveSymbol(symbol).then((info) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.emit('symbolChange', info ?? { symbol });\n });\n this.emit('intervalChange', interval);\n\n const streamMode: RealtimeStreamMode = this.features.tickStream\n ? 'bar+tick'\n : this.features.streamMode;\n\n const params: SubscribeParams = {\n symbol,\n interval,\n channels: this.features.tickStream ? ['bar', 'tick'] : ['bar'],\n streamMode,\n };\n\n await this.options.dataProvider.connect?.();\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const sub = await this.options.dataProvider.subscribe(params, {\n onBar: (bar, meta) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n void this.applyRealtimeBar(bar, meta.partial, loadGen);\n },\n onTick: (tick) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n const bar = this.buildBarFromPrice(tick.price, tick.t);\n void this.applyRealtimeBar(bar, true, loadGen);\n },\n onConnectionChange: (state) => this.emit('connectionChange', state),\n onError: (err) => this.emit('error', err),\n });\n if (!this.isLoadGenerationCurrent(loadGen)) {\n await this.options.dataProvider.unsubscribe(sub.id);\n return;\n }\n this.subscriptionId = sub.id;\n }\n\n private async teardownSubscription(): Promise<void> {\n if (this.subscriptionId) {\n await this.options.dataProvider.unsubscribe(this.subscriptionId);\n this.subscriptionId = null;\n }\n }\n\n private async maybeLoadMore(): Promise<void> {\n if (this.destroyed || this.loadingMore) return;\n const loadGen = this.loadGeneration;\n const reqs = this.virtualWindow.planFetches();\n if (reqs.length === 0) return;\n\n this.loadingMore = true;\n try {\n for (const req of reqs) {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n const history = await this.options.dataProvider.getHistory(toHistoryQuery(req));\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (history.bars.length === 0) continue;\n await this.store.mergeBars(\n history.bars.map((bar) => ({ bar, source: 'rest' as const })),\n req.mode === 'loadMore',\n );\n }\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.refreshRender(loadGen);\n } catch (err) {\n this.emit('error', err);\n } finally {\n this.loadingMore = false;\n }\n }\n\n private refreshRender(loadGen = this.loadGeneration): void {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const times = this.store.sortedTimes;\n if (times.length === 0) return;\n\n // Only seed visible range once; resetting to full series each tick triggers spurious loadMore.\n if (!this.visibleRangeInitialized) {\n this.virtualWindow.setVisibleRange({\n fromMs: times[0]!,\n toMs: times[times.length - 1]!,\n });\n this.visibleRangeInitialized = true;\n }\n\n const bars = this.virtualWindow.getBarsForRender();\n if (bars.length === 0) return;\n\n this.orchestrator.setBars(bars);\n this.drawingManager?.redraw();\n this.emit('visibleRangeChange', {\n from: bars[0]!.t,\n to: bars[bars.length - 1]!.t,\n });\n }\n\n private emit(event: ChartEvent, payload?: unknown): void {\n for (const h of this.handlers.get(event) ?? []) h(payload);\n }\n}\n\nfunction toHistoryQuery(req: HistoryRequest): HistoryQuery {\n if (req.mode === 'loadMore') {\n return {\n mode: 'loadMore',\n symbol: req.symbol,\n interval: req.interval,\n endTime: req.endTime ?? Date.now(),\n limit: req.limit,\n };\n }\n return {\n mode: 'range',\n symbol: req.symbol,\n interval: req.interval,\n from: req.fromMs ?? 0,\n to: req.toMs ?? Date.now(),\n };\n}","import type { RealtimeStreamMode } from '@coderyo/data';\nimport type { IndicatorConfig } from '@coderyo/indicators';\nimport type { FetchPolicy } from '@coderyo/virtual-window';\n\nexport interface ChartGapsFeatures {\n whitespace?: boolean;\n fillVisibleHoles?: boolean;\n}\n\nexport interface ChartDrawingsFeatures {\n /** Show interactive drawing overlay (default false). API remains available when false. */\n layer?: boolean;\n /** Persist drawings to localStorage (default true when layer/API used). */\n persist?: boolean;\n}\n\nexport interface ChartFeatures {\n fetchPolicy?: FetchPolicy;\n streamMode?: RealtimeStreamMode;\n gaps?: ChartGapsFeatures;\n drawings?: ChartDrawingsFeatures;\n /** Pass config to enable MA + indicator panes; omit/null = no indicators. */\n indicators?: IndicatorConfig | null;\n /** Save indicator params to storage (default false). */\n indicatorPersist?: boolean;\n /** Ease last candle OHLC + price line to new values (~150ms). */\n smoothPriceUpdate?: boolean;\n smoothPriceDurationMs?: number;\n /** Post-1.0 hooks — default false, no-op until implemented. */\n pineEnabled?: boolean;\n protobuf?: boolean;\n telemetry?: boolean;\n tickStream?: boolean;\n}\n\nexport interface ResolvedChartFeatures {\n fetchPolicy: FetchPolicy;\n streamMode: RealtimeStreamMode;\n gaps: Required<ChartGapsFeatures>;\n drawings: Required<ChartDrawingsFeatures>;\n indicators: IndicatorConfig | null;\n indicatorPersist: boolean;\n smoothPriceUpdate: boolean;\n smoothPriceDurationMs: number;\n pineEnabled: boolean;\n protobuf: boolean;\n telemetry: boolean;\n tickStream: boolean;\n}\n\nexport const DEFAULT_CHART_FEATURES: ResolvedChartFeatures = {\n fetchPolicy: 'lazy-left-only',\n streamMode: 'bar',\n gaps: { whitespace: false, fillVisibleHoles: false },\n drawings: { layer: false, persist: true },\n indicators: null,\n indicatorPersist: false,\n smoothPriceUpdate: false,\n smoothPriceDurationMs: 150,\n pineEnabled: false,\n protobuf: false,\n telemetry: false,\n tickStream: false,\n};\n\nexport function resolveChartFeatures(partial?: ChartFeatures): ResolvedChartFeatures {\n const d = DEFAULT_CHART_FEATURES;\n return {\n fetchPolicy: partial?.fetchPolicy ?? d.fetchPolicy,\n streamMode: partial?.streamMode ?? d.streamMode,\n gaps: {\n whitespace: partial?.gaps?.whitespace ?? d.gaps.whitespace,\n fillVisibleHoles: partial?.gaps?.fillVisibleHoles ?? d.gaps.fillVisibleHoles,\n },\n drawings: {\n layer: partial?.drawings?.layer ?? d.drawings.layer,\n persist: partial?.drawings?.persist ?? d.drawings.persist,\n },\n indicators: partial?.indicators !== undefined ? partial.indicators : d.indicators,\n indicatorPersist: partial?.indicatorPersist ?? d.indicatorPersist,\n smoothPriceUpdate: partial?.smoothPriceUpdate ?? d.smoothPriceUpdate,\n smoothPriceDurationMs: partial?.smoothPriceDurationMs ?? d.smoothPriceDurationMs,\n pineEnabled: partial?.pineEnabled ?? d.pineEnabled,\n protobuf: partial?.protobuf ?? d.protobuf,\n telemetry: partial?.telemetry ?? d.telemetry,\n tickStream: partial?.tickStream ?? d.tickStream,\n };\n}\n\nexport function mergeChartFeatures(\n current: ResolvedChartFeatures,\n patch: ChartFeatures,\n): ResolvedChartFeatures {\n return resolveChartFeatures({\n fetchPolicy: patch.fetchPolicy ?? current.fetchPolicy,\n streamMode: patch.streamMode ?? current.streamMode,\n gaps: { ...current.gaps, ...patch.gaps },\n drawings: { ...current.drawings, ...patch.drawings },\n indicators: patch.indicators !== undefined ? patch.indicators : current.indicators,\n indicatorPersist: patch.indicatorPersist ?? current.indicatorPersist,\n smoothPriceUpdate: patch.smoothPriceUpdate ?? current.smoothPriceUpdate,\n smoothPriceDurationMs: patch.smoothPriceDurationMs ?? current.smoothPriceDurationMs,\n pineEnabled: patch.pineEnabled ?? current.pineEnabled,\n protobuf: patch.protobuf ?? current.protobuf,\n telemetry: patch.telemetry ?? current.telemetry,\n tickStream: patch.tickStream ?? current.tickStream,\n });\n}\n\n/** Empty chart until integrator calls setSymbol. */\nexport const PENDING_SYMBOL = '';","import type { IndicatorConfig } from '@coderyo/indicators';\nimport { DEFAULT_INDICATOR_CONFIG } from '@coderyo/indicators';\nimport type { Interval } from '@coderyo/data';\nimport type { ChartFeatures } from './chart-features.js';\nimport type { ChartOptions } from './chart-controller.js';\n\n/** Playground / docs: opt-in full TV-like chart features. */\nexport function createDemoChartFeatures(opts: {\n indicatorConfig?: IndicatorConfig;\n returnToCursorAfterDraw?: boolean;\n}): ChartFeatures {\n return {\n fetchPolicy: 'lazy-left-only',\n streamMode: 'bar+tick',\n gaps: { whitespace: false, fillVisibleHoles: false },\n drawings: { layer: true, persist: true },\n indicators: opts.indicatorConfig ?? DEFAULT_INDICATOR_CONFIG,\n indicatorPersist: true,\n smoothPriceUpdate: true,\n smoothPriceDurationMs: 150,\n tickStream: true,\n };\n}\n\nexport function createDemoChartOptions(\n base: Pick<ChartOptions, 'dataProvider' | 'indicatorHost' | 'symbolResolver' | 'chartId'> & {\n symbol: string;\n interval: Interval;\n theme?: 'dark' | 'light';\n showGrid?: boolean;\n indicatorConfig?: IndicatorConfig;\n returnToCursorAfterDraw?: boolean;\n },\n): ChartOptions {\n const indicatorConfig = base.indicatorConfig ?? DEFAULT_INDICATOR_CONFIG;\n return {\n ...base,\n features: createDemoChartFeatures({\n indicatorConfig,\n returnToCursorAfterDraw: base.returnToCursorAfterDraw,\n }),\n indicatorConfig,\n drawingDefaults: { returnToCursorAfterDraw: base.returnToCursorAfterDraw ?? false },\n };\n}","import type { BridgeAdapter } from '@coderyo/bridge';\nimport type { BridgeOutboundType } from '@coderyo/bridge';\nimport type { DrawingRecord, DrawingStyleMeta } from '@coderyo/drawings';\nimport type { IndicatorConfig } from '@coderyo/indicators';\nimport type { DataProvider } from '@coderyo/data';\nimport { wireChartBridge, TRADVIEW_API_VERSION } from './bridge-wire.js';\nimport { ChartController, type ChartOptions } from './chart-controller.js';\nimport type { ChartFeatures, ResolvedChartFeatures } from './chart-features.js';\nimport { TRADVIEW_VERSION } from './version.js';\n\nexport { TRADVIEW_API_VERSION, TRADVIEW_VERSION };\nexport type { ChartFeatures, ResolvedChartFeatures } from './chart-features.js';\nexport { resolveChartFeatures, DEFAULT_CHART_FEATURES, PENDING_SYMBOL } from './chart-features.js';\nexport { createDemoChartFeatures, createDemoChartOptions } from './demo-presets.js';\n\nexport interface CreateChartOptions extends Omit<ChartOptions, 'dataProvider'> {\n dataProvider: DataProvider;\n bridge?: BridgeAdapter;\n chartId?: string;\n /** If set, only these bridge outbound events are posted. */\n bridgeOutboundEvents?: BridgeOutboundType[];\n bridgeCrosshairThrottleMs?: number;\n}\n\nexport interface IChart {\n setSymbol(symbol: string): IChart;\n setInterval(interval: import('@coderyo/data').Interval): IChart;\n setTheme(theme: 'dark' | 'light'): IChart;\n setShowGrid(show: boolean): IChart;\n setLogScale(enabled: boolean): IChart;\n fitContent(): IChart;\n scrollToRealtime(): IChart;\n resize(size?: { width?: number; height?: number }): IChart;\n setFullscreen(enabled: boolean): IChart;\n exportImage(opts?: { pixelRatio?: number }): Promise<Blob>;\n on(event: import('./chart-controller.js').ChartEvent, handler: (p?: unknown) => void): IChart;\n off(event: import('./chart-controller.js').ChartEvent, handler: (p?: unknown) => void): IChart;\n searchSymbols(query: string): Promise<import('@coderyo/data').SymbolSearchHit[]>;\n setDrawingTool(tool: import('@coderyo/drawings').DrawingTool): IChart;\n deleteSelectedDrawing(): boolean;\n copySelectedDrawing(): DrawingRecord | null;\n toggleLockSelectedDrawing(): boolean;\n updateSelectedDrawingStyle(patch: DrawingStyleMeta): void;\n deselectDrawing(): void;\n setIndicatorConfig(config: IndicatorConfig | null): void;\n setReturnToCursorAfterDraw(v: boolean): void;\n setFeatures(patch: ChartFeatures): IChart;\n getFeatures(): ResolvedChartFeatures;\n /** Integrator push: smooth-update last candle toward `price` (no WS required). */\n updateLastPrice(price: number, timeMs?: number): IChart;\n hasActiveSymbol(): boolean;\n destroy(): void;\n}\n\nfunction wrap(controller: ChartController, beforeDestroy?: () => void): IChart {\n return {\n setSymbol: (s) => {\n void controller.setSymbol(s);\n return wrap(controller, beforeDestroy);\n },\n setInterval: (i) => {\n void controller.setInterval(i);\n return wrap(controller, beforeDestroy);\n },\n setTheme: (t) => {\n controller.setTheme(t);\n return wrap(controller, beforeDestroy);\n },\n setShowGrid: (show) => {\n controller.setShowGrid(show);\n return wrap(controller, beforeDestroy);\n },\n setLogScale: (enabled) => {\n controller.setLogScale(enabled);\n return wrap(controller, beforeDestroy);\n },\n fitContent: () => {\n controller.fitContent();\n return wrap(controller, beforeDestroy);\n },\n scrollToRealtime: () => {\n controller.scrollToRealtime();\n return wrap(controller, beforeDestroy);\n },\n resize: (s) => {\n controller.resize(s);\n return wrap(controller, beforeDestroy);\n },\n setFullscreen: (e) => {\n controller.setFullscreen(e);\n return wrap(controller, beforeDestroy);\n },\n exportImage: (o) => controller.exportImage(o),\n on: (e, h) => {\n controller.on(e, h);\n return wrap(controller, beforeDestroy);\n },\n off: (e, h) => {\n controller.off(e, h);\n return wrap(controller, beforeDestroy);\n },\n searchSymbols: (q) => controller.searchSymbols(q),\n setDrawingTool: (tool) => {\n controller.setDrawingTool(tool);\n return wrap(controller, beforeDestroy);\n },\n deleteSelectedDrawing: () => controller.deleteSelectedDrawing(),\n copySelectedDrawing: () => controller.copySelectedDrawing(),\n toggleLockSelectedDrawing: () => controller.toggleLockSelectedDrawing(),\n updateSelectedDrawingStyle: (p) => {\n controller.updateSelectedDrawingStyle(p);\n return wrap(controller, beforeDestroy);\n },\n deselectDrawing: () => {\n controller.deselectDrawing();\n return wrap(controller, beforeDestroy);\n },\n setIndicatorConfig: (c) => {\n controller.setIndicatorConfig(c);\n return wrap(controller, beforeDestroy);\n },\n setReturnToCursorAfterDraw: (v) => {\n controller.setReturnToCursorAfterDraw(v);\n return wrap(controller, beforeDestroy);\n },\n setFeatures: (patch) => {\n controller.setFeatures(patch);\n return wrap(controller, beforeDestroy);\n },\n getFeatures: () => controller.getFeatures(),\n updateLastPrice: (price, timeMs) => {\n controller.updateLastPrice(price, timeMs);\n return wrap(controller, beforeDestroy);\n },\n hasActiveSymbol: () => controller.hasActiveSymbol(),\n destroy: () => {\n controller.destroy();\n beforeDestroy?.();\n },\n };\n}\n\nexport function createChart(\n target: HTMLElement | string,\n options: CreateChartOptions,\n): IChart {\n const el =\n typeof target === 'string'\n ? (document.querySelector(target) as HTMLElement | null)\n : target;\n if (!el) throw new Error('Chart container not found');\n const controller = new ChartController(el, options);\n let bridgeTeardown: (() => void) | undefined;\n const chart = wrap(controller, () => bridgeTeardown?.());\n if (options.bridge) {\n bridgeTeardown = wireChartBridge({\n controller,\n chart,\n bridge: options.bridge,\n chartId: options.chartId,\n outboundEvents: options.bridgeOutboundEvents,\n crosshairThrottleMs: options.bridgeCrosshairThrottleMs,\n });\n }\n return chart;\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/bridge-wire.ts","../src/version.ts","../src/chart-controller.ts","../src/fetch-chart-history.ts","../src/chart-features.ts","../src/demo-presets.ts","../src/create-chart.ts","../src/index.ts"],"sourcesContent":["import type { BridgeAdapter } from '@coderyo/bridge';\nimport {\n BRIDGE_SCHEMA_VERSION,\n isBridgeInbound,\n type BridgeInboundType,\n type BridgeOutboundType,\n} from '@coderyo/bridge';\nimport type { Interval } from '@coderyo/data';\nimport type { CrosshairPayload } from '@coderyo/renderer-lite';\nimport type { ChartController, ChartEvent } from './chart-controller.js';\nimport type { IChart } from './create-chart.js';\nimport { TRADVIEW_VERSION } from './version.js';\n\nexport const TRADVIEW_API_VERSION = 1 as const;\n\nconst CHART_EVENT_TO_BRIDGE: Partial<Record<ChartEvent, BridgeOutboundType>> = {\n connectionChange: 'chart.connectionChange',\n visibleRangeChange: 'chart.visibleRange',\n error: 'chart.error',\n symbolChange: 'chart.symbol',\n intervalChange: 'chart.interval',\n crosshairChange: 'chart.crosshair',\n destroyed: 'chart.destroyed',\n barUpdate: 'chart.barUpdate',\n};\n\nexport interface WireChartBridgeOptions {\n controller: ChartController;\n chart: IChart;\n bridge: BridgeAdapter;\n chartId?: string;\n /** Allowlist of outbound bridge events; default all mapped events. */\n outboundEvents?: BridgeOutboundType[];\n crosshairThrottleMs?: number;\n}\n\nexport function wireChartBridge(opts: WireChartBridgeOptions): () => void {\n const chartId = opts.chartId ?? `chart-${Date.now()}`;\n const { bridge, chart, controller } = opts;\n const allow = opts.outboundEvents ? new Set(opts.outboundEvents) : null;\n\n const shouldPost = (type: BridgeOutboundType): boolean =>\n allow === null || allow.has(type);\n\n const post = (type: BridgeOutboundType, payload: Record<string, unknown>) => {\n if (!shouldPost(type)) return;\n bridge.post({ type, payload });\n };\n\n post('chart.ready', {\n chartId,\n bridgeSchemaVersion: BRIDGE_SCHEMA_VERSION,\n apiVersion: TRADVIEW_API_VERSION,\n version: TRADVIEW_VERSION,\n });\n\n const postResize = () => {\n const el = controller.getContainer();\n const r = el.getBoundingClientRect();\n post('chart.resize', {\n chartId,\n width: Math.round(r.width),\n height: Math.round(r.height),\n });\n };\n if (shouldPost('chart.resize')) postResize();\n\n let crosshairTimer: ReturnType<typeof setTimeout> | null = null;\n let crosshairPending: CrosshairPayload | null = null;\n const throttleMs = opts.crosshairThrottleMs ?? 0;\n\n const flushCrosshair = () => {\n crosshairTimer = null;\n const p = crosshairPending;\n crosshairPending = null;\n if (!p) return;\n post('chart.crosshair', {\n chartId,\n time: p.time,\n price: p.price,\n ohlcv: p.ohlcv,\n symbol: controller.getSymbol(),\n interval: controller.getInterval(),\n });\n };\n\n const handlers = new Map<ChartEvent, (p?: unknown) => void>();\n\n handlers.set('connectionChange', (state) => {\n post('chart.connectionChange', { chartId, state });\n });\n handlers.set('visibleRangeChange', (range) => {\n const r = range as { from?: number; to?: number };\n post('chart.visibleRange', { chartId, from: r.from, to: r.to });\n });\n handlers.set('error', (err) => {\n const e = err as { code?: string; message?: string };\n post('chart.error', {\n chartId,\n code: e?.code ?? 'UNKNOWN',\n message: e?.message ?? String(err),\n });\n });\n handlers.set('symbolChange', (symbol) => {\n post('chart.symbol', { chartId, symbol: String(symbol ?? '') });\n });\n handlers.set('intervalChange', (interval) => {\n post('chart.interval', { chartId, interval: String(interval ?? '') });\n });\n handlers.set('crosshairChange', (payload) => {\n const p = payload as CrosshairPayload | null;\n if (!p) return;\n if (throttleMs <= 0) {\n post('chart.crosshair', {\n chartId,\n time: p.time,\n price: p.price,\n ohlcv: p.ohlcv,\n symbol: controller.getSymbol(),\n interval: controller.getInterval(),\n });\n return;\n }\n crosshairPending = p;\n if (!crosshairTimer) {\n crosshairTimer = setTimeout(flushCrosshair, throttleMs);\n }\n });\n handlers.set('destroyed', () => {\n post('chart.destroyed', { chartId });\n });\n handlers.set('barUpdate', (bar) => {\n const b = bar as { t?: number; c?: number };\n post('chart.barUpdate', { chartId, t: b?.t, c: b?.c });\n });\n\n for (const [ev, fn] of handlers) {\n const bridgeType = CHART_EVENT_TO_BRIDGE[ev];\n if (!bridgeType || shouldPost(bridgeType)) {\n chart.on(ev, fn);\n }\n }\n\n const offHost = bridge.onMessage((msg) => {\n if (!isBridgeInbound(msg)) return;\n const p = msg.payload ?? {};\n switch (msg.type as BridgeInboundType) {\n case 'host.setSymbol':\n if (typeof p.symbol === 'string') chart.setSymbol(p.symbol);\n break;\n case 'host.setInterval':\n if (typeof p.interval === 'string') chart.setInterval(p.interval as Interval);\n break;\n case 'host.setTheme':\n if (p.theme === 'dark' || p.theme === 'light') chart.setTheme(p.theme);\n break;\n case 'host.setShowGrid':\n if (typeof p.showGrid === 'boolean') chart.setShowGrid(p.showGrid);\n break;\n case 'host.fitContent':\n chart.fitContent();\n break;\n case 'host.scrollToRealtime':\n chart.scrollToRealtime();\n break;\n case 'host.resize':\n chart.resize({\n width: typeof p.width === 'number' ? p.width : undefined,\n height: typeof p.height === 'number' ? p.height : undefined,\n });\n postResize();\n break;\n case 'host.setLogScale':\n if (typeof p.enabled === 'boolean') chart.setLogScale(p.enabled);\n break;\n case 'host.setBarSpace':\n if (typeof p.px === 'number') chart.setBarSpace(p.px);\n break;\n case 'host.setVisibleRange':\n if (typeof p.fromMs === 'number' && typeof p.toMs === 'number') {\n chart.setVisibleRange({ fromMs: p.fromMs, toMs: p.toMs });\n }\n break;\n case 'host.scrollToTimestamp':\n if (typeof p.tsMs === 'number') {\n chart.scrollToTimestamp(\n p.tsMs,\n typeof p.animationMs === 'number' ? p.animationMs : undefined,\n );\n }\n break;\n case 'host.reloadHistory':\n void chart.reloadHistory();\n break;\n case 'host.setLocale':\n if (typeof p.locale === 'string') chart.setLocale(p.locale);\n break;\n case 'host.setFeatures':\n if (p.features && typeof p.features === 'object') {\n chart.setFeatures(p.features as import('./chart-features.js').ChartFeatures);\n }\n break;\n case 'host.destroy':\n chart.destroy();\n break;\n default:\n break;\n }\n });\n\n return () => {\n if (crosshairTimer) clearTimeout(crosshairTimer);\n offHost();\n for (const [ev, fn] of handlers) chart.off(ev, fn);\n };\n}","/** Synced by scripts/sync-versions.mjs from repo VERSION file */\nexport const TRADVIEW_VERSION = '1.0.1' as const;\n","import type { DrawingRecord, DrawingStyleMeta } from '@coderyo/drawings';\nimport type { IndicatorConfig } from '@coderyo/indicators';\n\nimport type {\n Bar,\n DataProvider,\n HistoryQuery,\n Interval,\n RealtimeStreamMode,\n SubscribeParams,\n SymbolResolver,\n} from '@coderyo/data';\nimport { floorBarOpenTime, intervalMs } from '@coderyo/data';\nimport type { HistoryRequest } from '@coderyo/virtual-window';\nimport { parseInterval } from '@coderyo/data';\nimport { BarStore, computeGapStartTimes, TickAggregator } from '@coderyo/series';\nimport { setLocale as setI18nLocale } from '@coderyo/i18n';\nimport { fetchChartHistory } from './fetch-chart-history.js';\nimport { VirtualWindow, type FetchPolicy } from '@coderyo/virtual-window';\nimport { DrawingManager } from '@coderyo/drawings';\nimport {\n compilePineLite,\n runPineLiteAsync,\n terminatePineWorker,\n type PineIrProgram,\n} from '@coderyo/pine-lite';\nimport { PaneOrchestrator, type ChartVisibleRange } from '@coderyo/renderer-lite';\n\nexport type { ChartVisibleRange };\nimport {\n mergeChartFeatures,\n PENDING_SYMBOL,\n resolveChartFeatures,\n type ChartFeatures,\n type ResolvedChartFeatures,\n} from './chart-features.js';\n\nexport interface ChartOptions {\n width?: number;\n height?: number;\n theme?: 'dark' | 'light';\n interval?: Interval;\n /** Omit for empty chart until setSymbol(). */\n symbol?: string;\n chartId?: string;\n /** Host element below main chart for MACD/RSI/KDJ panes (from ui-shell layout). */\n indicatorHost?: HTMLElement;\n dataProvider: DataProvider;\n /** Integrator feature flags (minimal defaults). */\n features?: ChartFeatures;\n /** @deprecated Use features.fetchPolicy */\n fetchPolicy?: FetchPolicy;\n scaleMode?: 'linear' | 'log';\n /** Grid lines on chart panes (default false). */\n showGrid?: boolean;\n symbolResolver?: SymbolResolver;\n drawingDefaults?: { returnToCursorAfterDraw?: boolean };\n /** @deprecated Use features.indicators */\n indicatorConfig?: IndicatorConfig;\n}\n\nexport type ChartEvent =\n | 'connectionChange'\n | 'barUpdate'\n | 'error'\n | 'visibleRangeChange'\n | 'symbolChange'\n | 'intervalChange'\n | 'crosshairChange'\n | 'destroyed'\n | 'drawingSelectionChange'\n | 'drawingContextMenu'\n | 'requestCursorTool'\n | 'featuresChange'\n | 'telemetry';\n\ntype EventHandler = (payload?: unknown) => void;\n\nexport class ChartController {\n private readonly store: BarStore;\n private readonly virtualWindow: VirtualWindow;\n private readonly orchestrator: PaneOrchestrator;\n private readonly handlers = new Map<ChartEvent, Set<EventHandler>>();\n private subscriptionId: string | null = null;\n private destroyed = false;\n private readonly resizeObserver: ResizeObserver;\n private loadingMore = false;\n private visibleRangeInitialized = false;\n /** Bumped on symbol/interval change to drop stale bootstrap / loadMore / WS merges. */\n private loadGeneration = 0;\n private drawingManager: DrawingManager | null = null;\n private offCrosshair: (() => void) | null = null;\n private features: ResolvedChartFeatures;\n private pineIr: PineIrProgram | null = null;\n private tickAggregator: TickAggregator | null = null;\n private catchUpInFlight = false;\n private lastCatchUpAt = 0;\n private offPageResume: (() => void) | null = null;\n\n constructor(\n private readonly container: HTMLElement,\n private readonly options: ChartOptions,\n ) {\n this.features = resolveChartFeatures({\n ...options.features,\n fetchPolicy: options.features?.fetchPolicy ?? options.fetchPolicy,\n indicators:\n options.features?.indicators !== undefined\n ? options.features.indicators\n : options.indicatorConfig !== undefined\n ? options.indicatorConfig\n : undefined,\n });\n\n const symbol = options.symbol?.trim() || PENDING_SYMBOL;\n const interval = parseInterval(options.interval ?? '1h');\n const fetchPolicy = this.features.gaps.fillVisibleHoles\n ? 'fill-visible-holes'\n : this.features.fetchPolicy;\n\n this.store = new BarStore(symbol || PENDING_SYMBOL, interval);\n this.virtualWindow = new VirtualWindow(this.store, { fetchPolicy });\n this.orchestrator = new PaneOrchestrator({\n container,\n indicatorRoot: options.indicatorHost,\n theme: options.theme ?? 'dark',\n scaleMode: options.scaleMode ?? 'linear',\n showGrid: options.showGrid ?? false,\n indicatorConfig: this.features.indicators,\n smoothPriceUpdate: this.features.smoothPriceUpdate,\n smoothPriceDurationMs: this.features.smoothPriceDurationMs,\n });\n\n if (options.width) container.style.width = `${options.width}px`;\n if (options.height) container.style.height = `${options.height}px`;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.destroyed) this.resize();\n });\n this.resizeObserver.observe(container);\n\n this.orchestrator.bus.subscribeTransform(() => {\n const bus = this.orchestrator.bus;\n if (bus.visibleToMs > bus.visibleFromMs) {\n this.virtualWindow.setVisibleRange({\n fromMs: bus.visibleFromMs,\n toMs: bus.visibleToMs,\n });\n this.visibleRangeInitialized = true;\n }\n void this.maybeLoadMore();\n this.drawingManager?.redraw();\n });\n\n const overlay = this.orchestrator.getOverlayCanvas();\n if (overlay) {\n this.orchestrator.setOverlayPointerEvents('none');\n this.drawingManager = new DrawingManager({\n canvas: overlay,\n interactionHost: overlay.parentElement ?? undefined,\n chartId: options.chartId ?? 'default',\n symbol,\n interval,\n priceToY: (p) => this.orchestrator.priceToY(p),\n timeToX: (t) => this.orchestrator.timeToX(t),\n xToTime: (x) => this.orchestrator.xToTime(x),\n yToPrice: (y) => this.orchestrator.yToPrice(y),\n returnToCursorAfterDraw: options.drawingDefaults?.returnToCursorAfterDraw ?? false,\n onRequestCursorTool: () => this.emit('requestCursorTool'),\n onSelectionChange: (id, record) =>\n this.emit('drawingSelectionChange', { id, record }),\n onContextMenu: (payload) => this.emit('drawingContextMenu', payload),\n });\n this.drawingManager.setPersistence(this.features.drawings.persist);\n this.applyDrawingLayer();\n }\n\n this.offCrosshair = this.orchestrator.subscribeCrosshair((payload) => {\n this.emit('crosshairChange', payload);\n });\n\n this.bindPageResumeCatchUp();\n\n if (this.hasActiveSymbol()) {\n void this.bootstrap(this.loadGeneration);\n } else {\n this.emit('connectionChange', 'disconnected');\n }\n }\n\n getFeatures(): ResolvedChartFeatures {\n return { ...this.features };\n }\n\n setFeatures(patch: ChartFeatures): this {\n this.features = mergeChartFeatures(this.features, patch);\n this.applyFeatures();\n this.emit('featuresChange', this.getFeatures());\n return this;\n }\n\n hasActiveSymbol(): boolean {\n const s = this.store.symbol;\n return s.length > 0 && s !== PENDING_SYMBOL;\n }\n\n private applyFeatures(): void {\n const fetchPolicy = this.features.gaps.fillVisibleHoles\n ? 'fill-visible-holes'\n : this.features.fetchPolicy;\n this.virtualWindow.setFetchPolicy(fetchPolicy);\n\n this.orchestrator.setIndicatorConfig(this.features.indicators);\n this.orchestrator.setSmoothPriceUpdate(\n this.features.smoothPriceUpdate,\n this.features.smoothPriceDurationMs,\n );\n this.drawingManager?.setPersistence(this.features.drawings.persist);\n this.applyDrawingLayer();\n this.recompilePine();\n }\n\n private recompilePine(): void {\n if (!this.features.pineEnabled || !this.features.pineScript?.trim()) {\n this.pineIr = null;\n this.orchestrator.setPinePlots(null);\n return;\n }\n const compiled = compilePineLite(this.features.pineScript);\n if (!compiled.ok || !compiled.ir) {\n this.pineIr = null;\n this.orchestrator.setPinePlots(null);\n this.emit('error', { kind: 'pine', errors: compiled.errors });\n return;\n }\n this.pineIr = compiled.ir;\n if (this.hasActiveSymbol()) {\n const bars = this.virtualWindow.getBarsForRender();\n if (bars.length > 0) this.applyPinePlots(bars);\n }\n }\n\n private applyPinePlots(bars: Bar[]): void {\n if (!this.features.pineEnabled || !this.pineIr) {\n this.orchestrator.setPinePlots(null);\n return;\n }\n const ir = this.pineIr;\n const useWorker = this.features.pineWorker;\n void runPineLiteAsync(ir, bars, { useWorker })\n .then((result) => {\n if (this.destroyed || this.pineIr !== ir) return;\n this.orchestrator.setPinePlots(\n result.plots.map((p) => ({\n title: p.title,\n values: p.values,\n color: undefined,\n })),\n );\n })\n .catch((err) => this.emit('error', err));\n }\n\n private trackTelemetry(event: string, data?: Record<string, unknown>): void {\n if (!this.features.telemetry) return;\n this.emit('telemetry', { event, ...data });\n }\n\n setLocale(locale: string): this {\n setI18nLocale(locale);\n this.trackTelemetry('locale', { locale });\n return this;\n }\n\n subscribeBars(handler: (bar: Bar) => void): () => void {\n const wrapper = (payload?: unknown) => handler(payload as Bar);\n this.on('barUpdate', wrapper);\n return () => this.off('barUpdate', wrapper);\n }\n\n /** Integrator push: update last candle close (and H/L) without WS. */\n updateLastPrice(price: number, timeMs = Date.now()): this {\n if (!this.hasActiveSymbol() || this.destroyed) return this;\n const bar = this.buildBarFromPrice(price, timeMs);\n void this.applyRealtimeBar(bar, true);\n return this;\n }\n\n private buildBarFromPrice(price: number, timeMs: number): Bar {\n const interval = this.store.interval;\n const open = floorBarOpenTime(timeMs, interval);\n const times = this.store.sortedTimes;\n const lastT = times.length > 0 ? times[times.length - 1]! : undefined;\n const existing = lastT !== undefined ? this.store.getBar(lastT) : undefined;\n\n if (existing && existing.t === open) {\n return {\n ...existing,\n c: price,\n h: Math.max(existing.h, price),\n l: Math.min(existing.l, price),\n };\n }\n\n const prevClose = existing?.c ?? price;\n return {\n t: open,\n o: prevClose,\n h: Math.max(prevClose, price),\n l: Math.min(prevClose, price),\n c: price,\n v: existing?.v ?? 0,\n };\n }\n\n private async applyRealtimeBar(\n bar: Bar,\n partial: boolean,\n loadGen = this.loadGeneration,\n ): Promise<void> {\n await this.store.mergeRealtime({ bar, partial });\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const bars = this.virtualWindow.getBarsForRender();\n const last = bars[bars.length - 1];\n if (last && this.features.smoothPriceUpdate) {\n this.orchestrator.updateLastBar(last, {\n smooth: true,\n durationMs: this.features.smoothPriceDurationMs,\n });\n this.drawingManager?.redraw();\n } else {\n this.refreshRender(loadGen);\n }\n this.emit('barUpdate', bar);\n this.trackTelemetry('barUpdate', { t: bar.t, partial });\n }\n\n private applyDrawingLayer(): void {\n if (!this.drawingManager) return;\n this.drawingManager.setLayerVisible(this.features.drawings.layer);\n this.syncOverlayPointerEvents();\n }\n\n private syncOverlayPointerEvents(): void {\n if (!this.drawingManager) return;\n const layer = this.features.drawings.layer;\n if (!layer) {\n this.orchestrator.setOverlayPointerEvents('none');\n return;\n }\n const tool = this.drawingManager.getTool();\n this.orchestrator.setOverlayPointerEvents(tool === 'cursor' ? 'none' : 'auto');\n }\n\n getContainer(): HTMLElement {\n return this.container;\n }\n\n getSymbol(): string {\n return this.store.symbol;\n }\n\n getInterval(): Interval {\n return this.store.interval;\n }\n\n async searchSymbols(query: string): Promise<import('@coderyo/data').SymbolSearchHit[]> {\n const resolver = this.options.symbolResolver;\n if (resolver?.search) return resolver.search(query);\n if (this.options.dataProvider.searchSymbols) {\n return this.options.dataProvider.searchSymbols(query);\n }\n return [];\n }\n\n async resolveSymbol(symbol: string): Promise<import('@coderyo/data').SymbolInfo | null> {\n if (this.options.symbolResolver) {\n return this.options.symbolResolver.resolve(symbol);\n }\n return { symbol };\n }\n\n on(event: ChartEvent, handler: EventHandler): this {\n if (!this.handlers.has(event)) this.handlers.set(event, new Set());\n this.handlers.get(event)!.add(handler);\n return this;\n }\n\n off(event: ChartEvent, handler: EventHandler): this {\n this.handlers.get(event)?.delete(handler);\n return this;\n }\n\n resize(size?: { width?: number; height?: number }): this {\n if (size?.width) this.container.style.width = `${size.width}px`;\n if (size?.height) this.container.style.height = `${size.height}px`;\n this.orchestrator.resize();\n return this;\n }\n\n setDrawingTool(tool: import('@coderyo/drawings').DrawingTool): this {\n this.drawingManager?.setTool(tool);\n this.syncOverlayPointerEvents();\n return this;\n }\n\n deleteSelectedDrawing(): boolean {\n return this.drawingManager?.deleteSelected() ?? false;\n }\n\n copySelectedDrawing(): DrawingRecord | null {\n return this.drawingManager?.copySelected() ?? null;\n }\n\n toggleLockSelectedDrawing(): boolean {\n return this.drawingManager?.toggleLockSelected() ?? false;\n }\n\n updateSelectedDrawingStyle(patch: DrawingStyleMeta): void {\n this.drawingManager?.updateSelectedStyle(patch);\n }\n\n deselectDrawing(): void {\n this.drawingManager?.deselect();\n }\n\n setIndicatorConfig(config: IndicatorConfig | null): void {\n this.features = mergeChartFeatures(this.features, { indicators: config });\n this.orchestrator.setIndicatorConfig(config);\n this.emit('featuresChange', this.getFeatures());\n }\n\n setReturnToCursorAfterDraw(v: boolean): void {\n this.drawingManager?.setReturnToCursorAfterDraw(v);\n }\n\n async setSymbol(symbol: string): Promise<void> {\n const trimmed = symbol.trim();\n if (!trimmed) return;\n const gen = this.beginDataContextChange();\n await this.teardownSubscription();\n await this.store.setSymbolInterval(trimmed, this.store.interval);\n this.drawingManager?.setContext(symbol, this.store.interval);\n const info = await this.resolveSymbol(symbol);\n await this.bootstrap(gen);\n this.emit('symbolChange', info ?? { symbol });\n }\n\n async setInterval(interval: Interval): Promise<void> {\n const gen = this.beginDataContextChange();\n await this.teardownSubscription();\n await this.store.setSymbolInterval(this.store.symbol, interval);\n this.drawingManager?.setContext(this.store.symbol, interval);\n if (this.hasActiveSymbol()) {\n await this.bootstrap(gen);\n }\n }\n\n setTheme(theme: 'dark' | 'light'): this {\n this.orchestrator.setTheme(theme);\n return this;\n }\n\n setShowGrid(show: boolean): this {\n this.orchestrator.setShowGrid(show);\n return this;\n }\n\n fitContent(): this {\n this.orchestrator.fitContent();\n return this;\n }\n\n scrollToRealtime(): this {\n this.orchestrator.scrollToRealtime();\n return this;\n }\n\n getVisibleRange(): ChartVisibleRange | null {\n return this.orchestrator.getVisibleRange();\n }\n\n getBarSpace(): number {\n return this.orchestrator.getBarSpace();\n }\n\n setBarSpace(px: number): this {\n this.orchestrator.setBarSpace(px);\n return this;\n }\n\n setVisibleRange(range: ChartVisibleRange): this {\n this.orchestrator.setVisibleRange(range);\n const { fromMs, toMs } = range;\n if (toMs > fromMs) {\n this.virtualWindow.setVisibleRange({ fromMs, toMs });\n this.visibleRangeInitialized = true;\n }\n return this;\n }\n\n scrollToTimestamp(tsMs: number, animationMs?: number): this {\n this.orchestrator.scrollToTimestamp(tsMs, animationMs);\n return this;\n }\n\n async reloadHistory(): Promise<this> {\n if (!this.hasActiveSymbol()) return this;\n const savedRange = this.getVisibleRange();\n const savedBarSpace = this.getBarSpace();\n const loadGen = this.loadGeneration;\n const symbol = this.store.symbol;\n const interval = this.store.interval;\n\n try {\n const history = await fetchChartHistory(this.options.dataProvider, {\n mode: 'loadMore',\n symbol,\n interval,\n endTime: Date.now(),\n limit: 500,\n });\n if (!this.isLoadGenerationCurrent(loadGen)) return this;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return this;\n if (history.bars.length === 0) return this;\n\n await this.store.mergeBars(history.bars.map((bar) => ({ bar, source: 'rest' as const })));\n if (!this.isLoadGenerationCurrent(loadGen)) return this;\n\n this.orchestrator.preserveViewportOnNextSetBars();\n this.refreshRender(loadGen);\n if (savedBarSpace > 0) this.setBarSpace(savedBarSpace);\n if (savedRange) this.setVisibleRange(savedRange);\n } catch (err) {\n this.emit('error', err);\n }\n return this;\n }\n\n setLogScale(enabled: boolean): this {\n this.orchestrator.setLogScale(enabled);\n return this;\n }\n\n setFullscreen(_enabled: boolean): this {\n if (_enabled && this.container.requestFullscreen) {\n void this.container.requestFullscreen();\n } else if (document.fullscreenElement) {\n void document.exitFullscreen();\n }\n return this;\n }\n\n async exportImage(opts?: { pixelRatio?: number }): Promise<Blob> {\n const canvas = this.container.querySelector('canvas');\n if (!canvas) throw new Error('No canvas to export');\n const scale = opts?.pixelRatio ?? 2;\n const exportCanvas = document.createElement('canvas');\n exportCanvas.width = canvas.width * scale;\n exportCanvas.height = canvas.height * scale;\n const ctx = exportCanvas.getContext('2d')!;\n ctx.scale(scale, scale);\n ctx.drawImage(canvas, 0, 0);\n return new Promise((resolve, reject) => {\n exportCanvas.toBlob((b) => (b ? resolve(b) : reject(new Error('export failed'))), 'image/png');\n });\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.offPageResume?.();\n this.offPageResume = null;\n this.offCrosshair?.();\n this.offCrosshair = null;\n this.resizeObserver.disconnect();\n this.drawingManager?.destroy();\n void this.teardownSubscription();\n this.orchestrator.destroy();\n terminatePineWorker();\n this.emit('destroyed', { chartId: this.options.chartId ?? 'default' });\n this.emit('connectionChange', 'disconnected');\n }\n\n private beginDataContextChange(): number {\n this.loadGeneration += 1;\n this.visibleRangeInitialized = false;\n this.virtualWindow.setVisibleRange({ fromMs: 0, toMs: 0 });\n this.orchestrator.resetViewState();\n this.orchestrator.clearBars();\n return this.loadGeneration;\n }\n\n private isLoadGenerationCurrent(gen: number): boolean {\n return !this.destroyed && gen === this.loadGeneration;\n }\n\n private async bootstrap(loadGen: number): Promise<void> {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const symbol = this.store.symbol;\n const interval = this.store.interval;\n const endTime = Date.now();\n if (this.features.protobuf) {\n this.emit('error', {\n code: 'PROTOBUF_UNAVAILABLE',\n message: 'Protobuf encoding requires protocol v1.1 (not in 1.0.0)',\n });\n }\n\n const history = await fetchChartHistory(this.options.dataProvider, {\n mode: 'loadMore',\n symbol,\n interval,\n endTime,\n limit: 500,\n });\n\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n\n await this.store.mergeBars(history.bars.map((bar) => ({ bar })));\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.refreshRender(loadGen);\n void this.resolveSymbol(symbol).then((info) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.emit('symbolChange', info ?? { symbol });\n });\n this.emit('intervalChange', interval);\n\n const streamMode: RealtimeStreamMode = this.features.tickStream\n ? 'bar+tick'\n : this.features.streamMode;\n const tickOnly = streamMode === 'tick';\n\n const params: SubscribeParams = {\n symbol,\n interval,\n channels: tickOnly ? ['tick'] : this.features.tickStream ? ['bar', 'tick'] : ['bar'],\n streamMode,\n };\n\n this.tickAggregator = tickOnly\n ? new TickAggregator(interval, (bar, partial) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n void this.applyRealtimeBar(bar, partial, loadGen);\n })\n : null;\n\n await this.options.dataProvider.connect?.();\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const sub = await this.options.dataProvider.subscribe(params, {\n onBar: tickOnly\n ? undefined\n : (bar, meta) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n void this.applyRealtimeBar(bar, meta.partial, loadGen);\n },\n onTick: (tick) => {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n if (this.tickAggregator) {\n this.tickAggregator.ingest(tick);\n return;\n }\n const bar = this.buildBarFromPrice(tick.price, tick.t);\n void this.applyRealtimeBar(bar, true, loadGen);\n },\n onConnectionChange: (state) => {\n this.emit('connectionChange', state);\n // Only backfill on reconnect; initial connect loads history in bootstrap.\n if (state === 'connected' && this.subscriptionId != null) {\n void this.catchUpMissedBars();\n }\n },\n onError: (err) => this.emit('error', err),\n });\n if (!this.isLoadGenerationCurrent(loadGen)) {\n await this.options.dataProvider.unsubscribe(sub.id);\n return;\n }\n this.subscriptionId = sub.id;\n }\n\n private async teardownSubscription(): Promise<void> {\n this.tickAggregator?.flush();\n this.tickAggregator = null;\n if (this.subscriptionId) {\n await this.options.dataProvider.unsubscribe(this.subscriptionId);\n this.subscriptionId = null;\n }\n }\n\n private bindPageResumeCatchUp(): void {\n if (typeof document === 'undefined') return;\n\n const onResume = () => {\n if (document.visibilityState !== 'visible') return;\n void this.catchUpMissedBars();\n };\n\n document.addEventListener('visibilitychange', onResume);\n const cleanups: Array<() => void> = [\n () => document.removeEventListener('visibilitychange', onResume),\n ];\n\n if (typeof window !== 'undefined') {\n const onFocus = () => void this.catchUpMissedBars();\n window.addEventListener('focus', onFocus);\n cleanups.push(() => window.removeEventListener('focus', onFocus));\n }\n\n this.offPageResume = () => {\n for (const fn of cleanups) fn();\n };\n }\n\n /**\n * Backfill bars missed while the tab/window was backgrounded or WS delivery paused.\n */\n private async catchUpMissedBars(): Promise<void> {\n if (this.destroyed || !this.hasActiveSymbol()) return;\n\n const now = Date.now();\n if (now - this.lastCatchUpAt < 400) return;\n if (this.catchUpInFlight) return;\n\n const times = this.store.sortedTimes;\n if (times.length === 0) return;\n\n const lastT = times[times.length - 1]!;\n const interval = this.store.interval;\n const to = now + intervalMs(interval);\n if (to <= lastT) return;\n\n this.catchUpInFlight = true;\n this.lastCatchUpAt = now;\n const loadGen = this.loadGeneration;\n const symbol = this.store.symbol;\n\n try {\n const history = await fetchChartHistory(this.options.dataProvider, {\n mode: 'range',\n symbol,\n interval,\n from: lastT,\n to,\n });\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (this.store.symbol !== symbol || this.store.interval !== interval) return;\n if (history.bars.length === 0) return;\n\n await this.store.mergeBars(\n history.bars.map((bar) => ({ bar, source: 'rest' as const })),\n );\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n this.orchestrator.preserveViewportOnNextSetBars();\n this.refreshRender(loadGen);\n } catch (err) {\n this.emit('error', err);\n } finally {\n this.catchUpInFlight = false;\n }\n }\n\n private async maybeLoadMore(): Promise<void> {\n if (this.destroyed || this.loadingMore) return;\n const loadGen = this.loadGeneration;\n const reqs = this.virtualWindow.planFetches();\n if (reqs.length === 0) return;\n\n this.loadingMore = true;\n try {\n for (const req of reqs) {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n const history = await fetchChartHistory(\n this.options.dataProvider,\n toHistoryQuery(req),\n );\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n if (history.bars.length === 0) continue;\n await this.store.mergeBars(\n history.bars.map((bar) => ({ bar, source: 'rest' as const })),\n req.mode === 'loadMore',\n );\n }\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n this.refreshRender(loadGen);\n } catch (err) {\n this.emit('error', err);\n } finally {\n this.loadingMore = false;\n }\n }\n\n private refreshRender(loadGen = this.loadGeneration): void {\n if (!this.isLoadGenerationCurrent(loadGen)) return;\n\n const times = this.store.sortedTimes;\n if (times.length === 0) return;\n\n // Only seed visible range once; resetting to full series each tick triggers spurious loadMore.\n if (!this.visibleRangeInitialized) {\n this.virtualWindow.setVisibleRange({\n fromMs: times[0]!,\n toMs: times[times.length - 1]!,\n });\n this.visibleRangeInitialized = true;\n }\n\n const bars = this.virtualWindow.getBarsForRender();\n if (bars.length === 0) return;\n\n const gaps = this.features.gaps.whitespace\n ? computeGapStartTimes(\n bars.map((b) => b.t),\n this.store.interval,\n )\n : undefined;\n this.orchestrator.setBars(bars, gaps);\n this.applyPinePlots(bars);\n this.drawingManager?.redraw();\n this.emit('visibleRangeChange', {\n from: bars[0]!.t,\n to: bars[bars.length - 1]!.t,\n });\n }\n\n private emit(event: ChartEvent, payload?: unknown): void {\n for (const h of this.handlers.get(event) ?? []) h(payload);\n }\n}\n\nfunction toHistoryQuery(req: HistoryRequest): HistoryQuery {\n if (req.mode === 'loadMore') {\n return {\n mode: 'loadMore',\n symbol: req.symbol,\n interval: req.interval,\n endTime: req.endTime ?? Date.now(),\n limit: req.limit,\n };\n }\n return {\n mode: 'range',\n symbol: req.symbol,\n interval: req.interval,\n from: req.fromMs ?? 0,\n to: req.toMs ?? Date.now(),\n };\n}","import type { Bar, DataProvider, HistoryQuery } from '@coderyo/data';\nimport { intervalMs } from '@coderyo/data';\n\n/** REST with optional WS `requestWsHistory` fallback when capabilities allow. */\nexport async function fetchChartHistory(\n provider: DataProvider,\n query: HistoryQuery,\n): Promise<{ bars: Bar[]; nextCursor?: string; hasMore?: boolean }> {\n const caps = await provider.getCapabilities?.();\n if (caps?.wsHistory && provider.requestWsHistory) {\n try {\n if (query.mode === 'range') {\n const bars = await provider.requestWsHistory({\n symbol: query.symbol,\n interval: query.interval,\n from: query.from,\n to: query.to,\n });\n return { bars, hasMore: false };\n }\n if (query.mode === 'loadMore') {\n const ms = intervalMs(query.interval);\n const from = query.endTime - ms * query.limit;\n const bars = await provider.requestWsHistory({\n symbol: query.symbol,\n interval: query.interval,\n from,\n to: query.endTime,\n });\n return { bars, hasMore: false };\n }\n } catch {\n /* fall through to REST */\n }\n }\n return provider.getHistory(query);\n}","import type { RealtimeStreamMode } from '@coderyo/data';\nimport type { IndicatorConfig } from '@coderyo/indicators';\nimport type { FetchPolicy } from '@coderyo/virtual-window';\n\nexport interface ChartGapsFeatures {\n whitespace?: boolean;\n fillVisibleHoles?: boolean;\n}\n\nexport interface ChartDrawingsFeatures {\n /** Show interactive drawing overlay (default false). API remains available when false. */\n layer?: boolean;\n /** Persist drawings to localStorage (default true when layer/API used). */\n persist?: boolean;\n}\n\nexport interface ChartFeatures {\n fetchPolicy?: FetchPolicy;\n streamMode?: RealtimeStreamMode;\n gaps?: ChartGapsFeatures;\n drawings?: ChartDrawingsFeatures;\n /** Pass config to enable MA + indicator panes; omit/null = no indicators. */\n indicators?: IndicatorConfig | null;\n /** Save indicator params to storage (default false). */\n indicatorPersist?: boolean;\n /** Ease last candle OHLC + price line to new values (~150ms). */\n smoothPriceUpdate?: boolean;\n smoothPriceDurationMs?: number;\n /** Pine-lite script source (requires pineEnabled). */\n pineScript?: string | null;\n /** Post-1.0 hooks — default false. */\n pineEnabled?: boolean;\n protobuf?: boolean;\n telemetry?: boolean;\n tickStream?: boolean;\n /** Run Pine-lite VM in a Web Worker when available (default true). */\n pineWorker?: boolean;\n}\n\nexport interface ResolvedChartFeatures {\n fetchPolicy: FetchPolicy;\n streamMode: RealtimeStreamMode;\n gaps: Required<ChartGapsFeatures>;\n drawings: Required<ChartDrawingsFeatures>;\n indicators: IndicatorConfig | null;\n indicatorPersist: boolean;\n smoothPriceUpdate: boolean;\n smoothPriceDurationMs: number;\n pineScript: string | null;\n pineEnabled: boolean;\n protobuf: boolean;\n telemetry: boolean;\n tickStream: boolean;\n pineWorker: boolean;\n}\n\nexport const DEFAULT_CHART_FEATURES: ResolvedChartFeatures = {\n fetchPolicy: 'lazy-left-only',\n streamMode: 'bar',\n gaps: { whitespace: false, fillVisibleHoles: false },\n drawings: { layer: false, persist: true },\n indicators: null,\n indicatorPersist: false,\n smoothPriceUpdate: false,\n smoothPriceDurationMs: 150,\n pineScript: null,\n pineEnabled: false,\n protobuf: false,\n telemetry: false,\n tickStream: false,\n pineWorker: true,\n};\n\nexport function resolveChartFeatures(partial?: ChartFeatures): ResolvedChartFeatures {\n const d = DEFAULT_CHART_FEATURES;\n return {\n fetchPolicy: partial?.fetchPolicy ?? d.fetchPolicy,\n streamMode: partial?.streamMode ?? d.streamMode,\n gaps: {\n whitespace: partial?.gaps?.whitespace ?? d.gaps.whitespace,\n fillVisibleHoles: partial?.gaps?.fillVisibleHoles ?? d.gaps.fillVisibleHoles,\n },\n drawings: {\n layer: partial?.drawings?.layer ?? d.drawings.layer,\n persist: partial?.drawings?.persist ?? d.drawings.persist,\n },\n indicators: partial?.indicators !== undefined ? partial.indicators : d.indicators,\n indicatorPersist: partial?.indicatorPersist ?? d.indicatorPersist,\n smoothPriceUpdate: partial?.smoothPriceUpdate ?? d.smoothPriceUpdate,\n smoothPriceDurationMs: partial?.smoothPriceDurationMs ?? d.smoothPriceDurationMs,\n pineScript: partial?.pineScript !== undefined ? partial.pineScript : d.pineScript,\n pineEnabled: partial?.pineEnabled ?? d.pineEnabled,\n protobuf: partial?.protobuf ?? d.protobuf,\n telemetry: partial?.telemetry ?? d.telemetry,\n tickStream: partial?.tickStream ?? d.tickStream,\n pineWorker: partial?.pineWorker ?? d.pineWorker,\n };\n}\n\nexport function mergeChartFeatures(\n current: ResolvedChartFeatures,\n patch: ChartFeatures,\n): ResolvedChartFeatures {\n return resolveChartFeatures({\n fetchPolicy: patch.fetchPolicy ?? current.fetchPolicy,\n streamMode: patch.streamMode ?? current.streamMode,\n gaps: { ...current.gaps, ...patch.gaps },\n drawings: { ...current.drawings, ...patch.drawings },\n indicators: patch.indicators !== undefined ? patch.indicators : current.indicators,\n indicatorPersist: patch.indicatorPersist ?? current.indicatorPersist,\n smoothPriceUpdate: patch.smoothPriceUpdate ?? current.smoothPriceUpdate,\n smoothPriceDurationMs: patch.smoothPriceDurationMs ?? current.smoothPriceDurationMs,\n pineScript: patch.pineScript !== undefined ? patch.pineScript : current.pineScript,\n pineEnabled: patch.pineEnabled ?? current.pineEnabled,\n protobuf: patch.protobuf ?? current.protobuf,\n telemetry: patch.telemetry ?? current.telemetry,\n tickStream: patch.tickStream ?? current.tickStream,\n pineWorker: patch.pineWorker ?? current.pineWorker,\n });\n}\n\n/** Empty chart until integrator calls setSymbol. */\nexport const PENDING_SYMBOL = '';","import type { IndicatorConfig } from '@coderyo/indicators';\nimport { DEFAULT_INDICATOR_CONFIG } from '@coderyo/indicators';\nimport { PINE_SAMPLE_SCRIPT } from '@coderyo/pine-lite';\nimport type { Interval } from '@coderyo/data';\nimport type { ChartFeatures } from './chart-features.js';\nimport type { ChartOptions } from './chart-controller.js';\n\n/** Playground / docs: opt-in full TV-like chart features. */\nexport function createDemoChartFeatures(opts: {\n indicatorConfig?: IndicatorConfig;\n returnToCursorAfterDraw?: boolean;\n}): ChartFeatures {\n return {\n fetchPolicy: 'lazy-left-only',\n streamMode: 'bar+tick',\n gaps: { whitespace: false, fillVisibleHoles: false },\n drawings: { layer: true, persist: true },\n indicators: opts.indicatorConfig ?? DEFAULT_INDICATOR_CONFIG,\n indicatorPersist: true,\n smoothPriceUpdate: true,\n smoothPriceDurationMs: 150,\n tickStream: true,\n pineEnabled: true,\n pineScript: PINE_SAMPLE_SCRIPT,\n };\n}\n\nexport function createDemoChartOptions(\n base: Pick<ChartOptions, 'dataProvider' | 'indicatorHost' | 'symbolResolver' | 'chartId'> & {\n symbol: string;\n interval: Interval;\n theme?: 'dark' | 'light';\n showGrid?: boolean;\n indicatorConfig?: IndicatorConfig;\n returnToCursorAfterDraw?: boolean;\n },\n): ChartOptions {\n const indicatorConfig = base.indicatorConfig ?? DEFAULT_INDICATOR_CONFIG;\n return {\n ...base,\n features: createDemoChartFeatures({\n indicatorConfig,\n returnToCursorAfterDraw: base.returnToCursorAfterDraw,\n }),\n indicatorConfig,\n drawingDefaults: { returnToCursorAfterDraw: base.returnToCursorAfterDraw ?? false },\n };\n}","import type { BridgeAdapter } from '@coderyo/bridge';\nimport type { BridgeOutboundType } from '@coderyo/bridge';\nimport type { DrawingRecord, DrawingStyleMeta } from '@coderyo/drawings';\nimport type { IndicatorConfig } from '@coderyo/indicators';\nimport type { DataProvider } from '@coderyo/data';\nimport { wireChartBridge, TRADVIEW_API_VERSION } from './bridge-wire.js';\nimport { ChartController, type ChartOptions } from './chart-controller.js';\nimport type { ChartFeatures, ResolvedChartFeatures } from './chart-features.js';\nimport { TRADVIEW_VERSION } from './version.js';\nimport type { ChartVisibleRange } from '@coderyo/renderer-lite';\n\nexport { TRADVIEW_API_VERSION, TRADVIEW_VERSION };\nexport type { ChartVisibleRange };\nexport type { ChartFeatures, ResolvedChartFeatures } from './chart-features.js';\nexport { resolveChartFeatures, DEFAULT_CHART_FEATURES, PENDING_SYMBOL } from './chart-features.js';\nexport { createDemoChartFeatures, createDemoChartOptions } from './demo-presets.js';\n\nexport interface CreateChartOptions extends Omit<ChartOptions, 'dataProvider'> {\n dataProvider: DataProvider;\n bridge?: BridgeAdapter;\n chartId?: string;\n /** If set, only these bridge outbound events are posted. */\n bridgeOutboundEvents?: BridgeOutboundType[];\n bridgeCrosshairThrottleMs?: number;\n}\n\nexport interface IChart {\n setSymbol(symbol: string): IChart;\n setInterval(interval: import('@coderyo/data').Interval): IChart;\n setTheme(theme: 'dark' | 'light'): IChart;\n setShowGrid(show: boolean): IChart;\n setLogScale(enabled: boolean): IChart;\n fitContent(): IChart;\n scrollToRealtime(): IChart;\n /** Visible time range in ms (`fromMs` / `toMs`), or `null` if unknown. */\n getVisibleRange(): ChartVisibleRange | null;\n /** Bar spacing in px (zoom). Alias for LWC `barSpacing`. */\n getBarSpace(): number;\n setBarSpace(px: number): IChart;\n /** Restore viewport time range after re-bootstrap. */\n setVisibleRange(range: ChartVisibleRange): IChart;\n /** Scroll so `tsMs` aligns to the right edge of the viewport. */\n scrollToTimestamp(tsMs: number, animationMs?: number): IChart;\n /** Re-fetch recent history without clearing scroll/zoom. */\n reloadHistory(): Promise<IChart>;\n resize(size?: { width?: number; height?: number }): IChart;\n setFullscreen(enabled: boolean): IChart;\n exportImage(opts?: { pixelRatio?: number }): Promise<Blob>;\n on(event: import('./chart-controller.js').ChartEvent, handler: (p?: unknown) => void): IChart;\n off(event: import('./chart-controller.js').ChartEvent, handler: (p?: unknown) => void): IChart;\n searchSymbols(query: string): Promise<import('@coderyo/data').SymbolSearchHit[]>;\n setDrawingTool(tool: import('@coderyo/drawings').DrawingTool): IChart;\n deleteSelectedDrawing(): boolean;\n copySelectedDrawing(): DrawingRecord | null;\n toggleLockSelectedDrawing(): boolean;\n updateSelectedDrawingStyle(patch: DrawingStyleMeta): void;\n deselectDrawing(): void;\n setIndicatorConfig(config: IndicatorConfig | null): void;\n setReturnToCursorAfterDraw(v: boolean): void;\n setFeatures(patch: ChartFeatures): IChart;\n getFeatures(): ResolvedChartFeatures;\n /** Integrator push: smooth-update last candle toward `price` (no WS required). */\n updateLastPrice(price: number, timeMs?: number): IChart;\n hasActiveSymbol(): boolean;\n setLocale(locale: string): IChart;\n /** Subscribe to realtime bar updates; returns unsubscribe. */\n subscribeBars(handler: (bar: import('@coderyo/data').Bar) => void): () => void;\n destroy(): void;\n}\n\nfunction wrap(controller: ChartController, beforeDestroy?: () => void): IChart {\n return {\n setSymbol: (s) => {\n void controller.setSymbol(s);\n return wrap(controller, beforeDestroy);\n },\n setInterval: (i) => {\n void controller.setInterval(i);\n return wrap(controller, beforeDestroy);\n },\n setTheme: (t) => {\n controller.setTheme(t);\n return wrap(controller, beforeDestroy);\n },\n setShowGrid: (show) => {\n controller.setShowGrid(show);\n return wrap(controller, beforeDestroy);\n },\n setLogScale: (enabled) => {\n controller.setLogScale(enabled);\n return wrap(controller, beforeDestroy);\n },\n fitContent: () => {\n controller.fitContent();\n return wrap(controller, beforeDestroy);\n },\n scrollToRealtime: () => {\n controller.scrollToRealtime();\n return wrap(controller, beforeDestroy);\n },\n getVisibleRange: () => controller.getVisibleRange(),\n getBarSpace: () => controller.getBarSpace(),\n setBarSpace: (px) => {\n controller.setBarSpace(px);\n return wrap(controller, beforeDestroy);\n },\n setVisibleRange: (range) => {\n controller.setVisibleRange(range);\n return wrap(controller, beforeDestroy);\n },\n scrollToTimestamp: (tsMs, animationMs) => {\n controller.scrollToTimestamp(tsMs, animationMs);\n return wrap(controller, beforeDestroy);\n },\n reloadHistory: async () => {\n await controller.reloadHistory();\n return wrap(controller, beforeDestroy);\n },\n resize: (s) => {\n controller.resize(s);\n return wrap(controller, beforeDestroy);\n },\n setFullscreen: (e) => {\n controller.setFullscreen(e);\n return wrap(controller, beforeDestroy);\n },\n exportImage: (o) => controller.exportImage(o),\n on: (e, h) => {\n controller.on(e, h);\n return wrap(controller, beforeDestroy);\n },\n off: (e, h) => {\n controller.off(e, h);\n return wrap(controller, beforeDestroy);\n },\n searchSymbols: (q) => controller.searchSymbols(q),\n setDrawingTool: (tool) => {\n controller.setDrawingTool(tool);\n return wrap(controller, beforeDestroy);\n },\n deleteSelectedDrawing: () => controller.deleteSelectedDrawing(),\n copySelectedDrawing: () => controller.copySelectedDrawing(),\n toggleLockSelectedDrawing: () => controller.toggleLockSelectedDrawing(),\n updateSelectedDrawingStyle: (p) => {\n controller.updateSelectedDrawingStyle(p);\n return wrap(controller, beforeDestroy);\n },\n deselectDrawing: () => {\n controller.deselectDrawing();\n return wrap(controller, beforeDestroy);\n },\n setIndicatorConfig: (c) => {\n controller.setIndicatorConfig(c);\n return wrap(controller, beforeDestroy);\n },\n setReturnToCursorAfterDraw: (v) => {\n controller.setReturnToCursorAfterDraw(v);\n return wrap(controller, beforeDestroy);\n },\n setFeatures: (patch) => {\n controller.setFeatures(patch);\n return wrap(controller, beforeDestroy);\n },\n getFeatures: () => controller.getFeatures(),\n updateLastPrice: (price, timeMs) => {\n controller.updateLastPrice(price, timeMs);\n return wrap(controller, beforeDestroy);\n },\n hasActiveSymbol: () => controller.hasActiveSymbol(),\n setLocale: (locale) => {\n controller.setLocale(locale);\n return wrap(controller, beforeDestroy);\n },\n subscribeBars: (handler) => controller.subscribeBars(handler),\n destroy: () => {\n controller.destroy();\n beforeDestroy?.();\n },\n };\n}\n\nexport function createChart(\n target: HTMLElement | string,\n options: CreateChartOptions,\n): IChart {\n const el =\n typeof target === 'string'\n ? (document.querySelector(target) as HTMLElement | null)\n : target;\n if (!el) throw new Error('Chart container not found');\n const controller = new ChartController(el, options);\n let bridgeTeardown: (() => void) | undefined;\n const chart = wrap(controller, () => bridgeTeardown?.());\n if (options.bridge) {\n bridgeTeardown = wireChartBridge({\n controller,\n chart,\n bridge: options.bridge,\n chartId: options.chartId,\n outboundEvents: options.bridgeOutboundEvents,\n crosshairThrottleMs: options.bridgeCrosshairThrottleMs,\n });\n }\n return chart;\n}","export {\n createChart,\n type IChart,\n type CreateChartOptions,\n TRADVIEW_API_VERSION,\n TRADVIEW_VERSION,\n type ChartFeatures,\n type ResolvedChartFeatures,\n resolveChartFeatures,\n DEFAULT_CHART_FEATURES,\n PENDING_SYMBOL,\n createDemoChartFeatures,\n createDemoChartOptions,\n} from './create-chart.js';\nexport {\n ChartController,\n type ChartOptions,\n type ChartEvent,\n type ChartVisibleRange,\n} from './chart-controller.js';\nexport { wireChartBridge, type WireChartBridgeOptions } from './bridge-wire.js';\nexport {\n compilePineLite,\n runPineLite,\n PINE_SAMPLE_SCRIPT,\n PINE_EDITOR_DEFAULT,\n type PineCompileResult,\n type PineIrProgram,\n type PinePlotSeries,\n} from '@coderyo/pine-lite';"],"mappings":"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","names":["intervalMs","intervalMs","compilePineLite","PINE_SAMPLE_SCRIPT"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderyo/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -10,20 +10,22 @@
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@coderyo/data": "1.0.
|
|
14
|
-
"@coderyo/
|
|
15
|
-
"@coderyo/
|
|
16
|
-
"@coderyo/
|
|
17
|
-
"@coderyo/
|
|
18
|
-
"@coderyo/renderer-lite": "1.0.
|
|
19
|
-
"@coderyo/
|
|
13
|
+
"@coderyo/data": "1.0.1",
|
|
14
|
+
"@coderyo/bridge": "1.0.1",
|
|
15
|
+
"@coderyo/series": "1.0.1",
|
|
16
|
+
"@coderyo/virtual-window": "1.0.1",
|
|
17
|
+
"@coderyo/indicators": "1.0.1",
|
|
18
|
+
"@coderyo/renderer-lite": "1.0.1",
|
|
19
|
+
"@coderyo/pine-lite": "1.0.1",
|
|
20
|
+
"@coderyo/i18n": "1.0.1",
|
|
21
|
+
"@coderyo/drawings": "1.0.1"
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
22
24
|
"tsup": "^8.5.0",
|
|
23
25
|
"typescript": "^5.8.3",
|
|
24
26
|
"vitest": "^3.2.4",
|
|
25
|
-
"@coderyo/
|
|
26
|
-
"@coderyo/
|
|
27
|
+
"@coderyo/tsconfig": "0.0.0",
|
|
28
|
+
"@coderyo/eslint-config": "0.0.0"
|
|
27
29
|
},
|
|
28
30
|
"files": [
|
|
29
31
|
"dist"
|