@tradecanvas/chart 0.1.0

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.
@@ -0,0 +1,238 @@
1
+ import { ChartOptions, ChartType, OHLCBar, DataSeries, Theme, ThemeName, ChartEventType, ChartEvent, TauriBridgeOptions, IndicatorPlugin, IndicatorDescriptor, IndicatorOutput, DrawingToolType, DrawingState, DrawingStyle, DrawingPlugin, PanelPosition, TradingOrder, TradingPosition, DepthData, TradingConfig, MarketConfig, Locale, StreamConfig, ConnectionState, ConnectionInfo, TimeFrame, FeaturesConfig } from '@tradecanvas/commons';
2
+ export declare class Chart {
3
+ static version: string;
4
+ private engine;
5
+ private viewport;
6
+ private dataManager;
7
+ private themeManager;
8
+ private layoutManager;
9
+ private pluginManager;
10
+ private indicatorEngine;
11
+ private drawingManager;
12
+ private drawingRenderer;
13
+ private tradingManager;
14
+ private tradingRenderer;
15
+ private eventBus;
16
+ private streamManager;
17
+ private autoScrollOnNewBar;
18
+ private displayDataCache;
19
+ private resolvedLayoutCache;
20
+ private panelInfoCache;
21
+ private renderScheduled;
22
+ private containerSizeCache;
23
+ private containerSizeCacheTime;
24
+ private chartLegend;
25
+ private watermark;
26
+ private barCountdown;
27
+ private sessionBreaks;
28
+ private compareRenderer;
29
+ private countdownInterval;
30
+ private volumeRenderer;
31
+ private alertManager;
32
+ private replayManager;
33
+ private undoRedoManager;
34
+ private autoSaveTimer;
35
+ private autoSaveDelay;
36
+ private autoSaveKey;
37
+ private animator;
38
+ private crosshairTooltip;
39
+ private interactionManager;
40
+ private crosshairHandler;
41
+ private chartRenderer;
42
+ private gridRenderer;
43
+ private priceAxis;
44
+ private timeAxis;
45
+ private options;
46
+ private features;
47
+ private marketConfig;
48
+ private container;
49
+ private currentPriceLine;
50
+ constructor(container: HTMLElement, options: ChartOptions);
51
+ setData(data: DataSeries): void;
52
+ appendBar(bar: OHLCBar): void;
53
+ updateLastBar(bar: OHLCBar): void;
54
+ /** Merge a price tick into the current last bar (convenience for live feeds) */
55
+ updateLastBarFromTick(tick: {
56
+ price: number;
57
+ volume?: number;
58
+ time: number;
59
+ }): void;
60
+ setChartType(type: ChartType): void;
61
+ addIndicator(id: string, params?: Record<string, number | string | boolean>, position?: PanelPosition): string | null;
62
+ updateIndicator(instanceId: string, params: Record<string, number | string | boolean>): void;
63
+ removeIndicator(instanceId: string): void;
64
+ getIndicatorOutput(instanceId: string): IndicatorOutput | null;
65
+ registerIndicator(plugin: IndicatorPlugin): void;
66
+ static indicators(): IndicatorDescriptor[];
67
+ setPanelPosition(instanceId: string, position: PanelPosition): void;
68
+ setPanelSize(instanceId: string, size: number): void;
69
+ setDrawingTool(type: DrawingToolType | null): void;
70
+ getDrawingTool(): DrawingToolType | null;
71
+ setDrawingStyle(style: Partial<DrawingStyle>): void;
72
+ getDrawings(): DrawingState[];
73
+ setDrawings(drawings: DrawingState[]): void;
74
+ removeDrawing(id: string): void;
75
+ clearDrawings(): void;
76
+ registerDrawingTool(plugin: DrawingPlugin): void;
77
+ undo(): boolean;
78
+ redo(): boolean;
79
+ getUndoRedoState(): {
80
+ canUndo: boolean;
81
+ canRedo: boolean;
82
+ };
83
+ setDrawingMagnet(enabled: boolean): void;
84
+ getDrawingMagnet(): boolean;
85
+ lockAllDrawings(): void;
86
+ unlockAllDrawings(): void;
87
+ hideAllDrawings(): void;
88
+ showAllDrawings(): void;
89
+ duplicateDrawing(id?: string): string | null;
90
+ exportVisibleData(format?: 'csv' | 'json', filename?: string): void;
91
+ exportAllData(format?: 'csv' | 'json', filename?: string): void;
92
+ setAutoSave(key: string, delayMs?: number): void;
93
+ disableAutoSave(): void;
94
+ private scheduleAutoSave;
95
+ getAvailableIndicators(): IndicatorDescriptor[];
96
+ getIndicatorInputs(id: string): {
97
+ id: string;
98
+ params: Record<string, unknown>;
99
+ } | null;
100
+ /** Get all active indicator instances with their current params */
101
+ getActiveIndicators(): {
102
+ instanceId: string;
103
+ id: string;
104
+ params: Record<string, unknown>;
105
+ descriptor: IndicatorDescriptor;
106
+ }[];
107
+ /** Get current config for a specific indicator instance */
108
+ getIndicatorConfig(instanceId: string): {
109
+ id: string;
110
+ params: Record<string, unknown>;
111
+ } | null;
112
+ /** Update indicator colors/line widths at runtime */
113
+ updateIndicatorStyle(instanceId: string, style: {
114
+ colors?: string[];
115
+ lineWidths?: number[];
116
+ opacity?: number;
117
+ }): void;
118
+ setOrders(orders: TradingOrder[]): void;
119
+ setPositions(positions: TradingPosition[]): void;
120
+ setDepthData(depth: DepthData | null): void;
121
+ setCurrentPrice(price: number): void;
122
+ setTradingConfig(config: Partial<TradingConfig>): void;
123
+ /**
124
+ * Connect to a real-time data source.
125
+ * Loads history, starts streaming, manages reconnection automatically.
126
+ *
127
+ * @example
128
+ * import { BinanceAdapter } from '@tradecanvas/core';
129
+ * chart.connect({
130
+ * adapter: new BinanceAdapter(),
131
+ * symbol: 'BTCUSDT',
132
+ * timeframe: '1m',
133
+ * });
134
+ */
135
+ connect(config: StreamConfig): Promise<void>;
136
+ /**
137
+ * Switch symbol or timeframe on an active stream without full reconnect.
138
+ */
139
+ switchStream(symbol: string, timeframe: TimeFrame): Promise<void>;
140
+ /**
141
+ * Disconnect the real-time stream.
142
+ */
143
+ disconnectStream(): void;
144
+ setBarCountdownVisible(visible: boolean): void;
145
+ setSessionBreaksVisible(visible: boolean): void;
146
+ addCompareSymbol(id: string, label: string, data: DataSeries, color: string): void;
147
+ removeCompareSymbol(id: string): void;
148
+ updateCompareData(id: string, data: DataSeries): void;
149
+ setCompareMode(mode: 'percent' | 'absolute'): void;
150
+ clearCompareSymbols(): void;
151
+ setLogScale(enabled: boolean): void;
152
+ isLogScale(): boolean;
153
+ setSessionBreaksConfig(config: {
154
+ color?: string;
155
+ lineStyle?: 'solid' | 'dashed' | 'dotted';
156
+ lineWidth?: number;
157
+ }): void;
158
+ getConnectionState(): ConnectionState;
159
+ getConnectionInfo(): ConnectionInfo;
160
+ setAutoScroll(enabled: boolean): void;
161
+ scrollTo(timestamp: number): void;
162
+ scrollToEnd(): void;
163
+ setVisibleRange(fromTimestamp: number, toTimestamp: number): void;
164
+ zoomIn(): void;
165
+ zoomOut(): void;
166
+ fitContent(): void;
167
+ on(type: ChartEventType, handler: (event: ChartEvent) => void): void;
168
+ off(type: ChartEventType, handler: (event: ChartEvent) => void): void;
169
+ enableTauriBridge(options?: Partial<TauriBridgeOptions>): void;
170
+ disableTauriBridge(): void;
171
+ setTheme(themeOrName: ThemeName | Theme): void;
172
+ getTheme(): Theme;
173
+ setWatermark(text: string, opts?: {
174
+ color?: string;
175
+ fontSize?: number;
176
+ }): void;
177
+ setAutoScale(enabled: boolean): void;
178
+ isAutoScale(): boolean;
179
+ setCrosshairMode(mode: 'normal' | 'magnet' | 'hidden'): void;
180
+ getCrosshairMode(): string;
181
+ setGridVisible(visible: boolean): void;
182
+ isGridVisible(): boolean;
183
+ setVolumeVisible(visible: boolean): void;
184
+ setTooltipVisible(visible: boolean): void;
185
+ setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void;
186
+ setSymbolName(symbol: string): void;
187
+ screenshot(filename?: string): void;
188
+ screenshotDataURL(): string | null;
189
+ screenshotBlob(): Promise<Blob | null>;
190
+ addAlert(price: number, condition?: import('@tradecanvas/core').AlertCondition, message?: string): string | null;
191
+ removeAlert(id: string): void;
192
+ getAlerts(): import('@tradecanvas/core').PriceAlert[];
193
+ clearAlerts(): void;
194
+ saveAlerts(key: string): void;
195
+ loadAlerts(key: string): void;
196
+ replay(config?: Partial<import('@tradecanvas/core').ReplayConfig>): void;
197
+ replayPause(): void;
198
+ replayResume(): void;
199
+ replayStop(): void;
200
+ replaySeek(index: number): void;
201
+ setReplaySpeed(speed: number): void;
202
+ getReplayState(): 'playing' | 'paused' | 'stopped';
203
+ getReplayProgress(): {
204
+ current: number;
205
+ total: number;
206
+ percent: number;
207
+ };
208
+ saveState(key?: string): string | null;
209
+ loadState(json: string): void;
210
+ loadStateFromStorage(key: string): boolean;
211
+ downloadState(filename?: string): void;
212
+ loadStateFromFile(): Promise<void>;
213
+ setLocale(locale: Locale): void;
214
+ setMarket(config: MarketConfig): void;
215
+ getMarket(): MarketConfig | null;
216
+ setPriceLimits(referencePrice: number): void;
217
+ /** Get the resolved feature configuration */
218
+ getFeatures(): Readonly<Required<FeaturesConfig>>;
219
+ /** Update feature flags at runtime. Only provided keys are changed. */
220
+ setFeatures(patch: Partial<FeaturesConfig>): void;
221
+ resize(): void;
222
+ destroy(): void;
223
+ private createChartRenderer;
224
+ /** Cached display data. Invalidated when raw data or chart type changes. */
225
+ private getDisplayData;
226
+ /** Lightweight render for streaming updates. No layout resolve, no indicator recalc. */
227
+ private scheduleRender;
228
+ /** Full update: resolve layout, update viewport, sync context, request render. */
229
+ private updateViewportAndRender;
230
+ private getResolvedLayout;
231
+ /** Cache container size for 500ms to avoid layout thrashing on rapid calls */
232
+ private cachedContainerSize;
233
+ private buildPanelRenderInfos;
234
+ private syncRenderContext;
235
+ private timeframeToMs;
236
+ private buildPriceLimits;
237
+ }
238
+ //# sourceMappingURL=Chart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../src/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,OAAO,EACP,UAAU,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,cAAc,EACf,MAAM,sBAAsB,CAAC;AA0D9B,qBAAa,KAAK;IAChB,MAAM,CAAC,OAAO,SAAW;IAEzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,mBAAmB,CAA8D;IACzF,OAAO,CAAC,cAAc,CAA8D;IACpF,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,gBAAgB,CAA+C;gBAE3D,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY;IAgRzD,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAc/B,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAS7B,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAcjC,gFAAgF;IAChF,qBAAqB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAanF,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAUnC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,MAAM,GAAG,IAAI;IAanI,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI;IAK5F,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOzC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAI9D,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAIhD,MAAM,CAAC,UAAU,IAAI,mBAAmB,EAAE;IAQ1C,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAKnE,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAOpD,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI;IAOlD,cAAc,IAAI,eAAe,GAAG,IAAI;IAIxC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAInD,WAAW,IAAI,YAAY,EAAE;IAI7B,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAI3C,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI/B,aAAa,IAAI,IAAI;IAIrB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAMhD,IAAI,IAAI,OAAO;IAKf,IAAI,IAAI,OAAO;IAKf,gBAAgB,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAM1D,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIxC,gBAAgB,IAAI,OAAO;IAM3B,eAAe,IAAI,IAAI;IAIvB,iBAAiB,IAAI,IAAI;IAIzB,eAAe,IAAI,IAAI;IAIvB,eAAe,IAAI,IAAI;IAMvB,gBAAgB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ5C,iBAAiB,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAgB1E,aAAa,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAatE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAO,GAAG,IAAI;IAK9C,eAAe,IAAI,IAAI;IASvB,OAAO,CAAC,gBAAgB;IAaxB,sBAAsB,IAAI,mBAAmB,EAAE;IAI/C,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI;IAOtF,mEAAmE;IACnE,mBAAmB,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,UAAU,EAAE,mBAAmB,CAAA;KAAE,EAAE;IAI7H,2DAA2D;IAC3D,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI;IAM9F,qDAAqD;IACrD,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOrH,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI;IAKvC,YAAY,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI;IAKhD,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAK3C,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQpC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAOtD;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDlD;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAOxB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAK9C,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAO/C,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlF,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKrC,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAKrD,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI;IAKlD,mBAAmB,IAAI,IAAI;IAO3B,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKnC,UAAU,IAAI,OAAO;IAIrB,sBAAsB,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKvH,kBAAkB,IAAI,eAAe;IAIrC,iBAAiB,IAAI,cAAc;IAInC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMrC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAYjC,WAAW,IAAI,IAAI;IAKnB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAuBjE,MAAM,IAAI,IAAI;IAMd,OAAO,IAAI,IAAI;IAMf,UAAU,IAAI,IAAI;IAQlB,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAIpE,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI;IAIrE,iBAAiB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAI9D,kBAAkB,IAAI,IAAI;IAM1B,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;IAQ9C,QAAQ,IAAI,KAAK;IAMjB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAO9E,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKpC,WAAW,IAAI,OAAO;IAMtB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAK5D,gBAAgB,IAAI,MAAM;IAM1B,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKtC,aAAa,IAAI,OAAO;IAMxB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOxC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMzC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,GAAG,IAAI;IAK1E,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOnC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAKnC,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAK5B,cAAc,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAO5C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,mBAAmB,EAAE,cAA2B,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO5H,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK7B,SAAS,IAAI,OAAO,mBAAmB,EAAE,UAAU,EAAE;IAIrD,WAAW,IAAI,IAAI;IAKnB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO7B,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,GAAG,IAAI;IAcxE,WAAW,IAAI,IAAI;IACnB,YAAY,IAAI,IAAI;IACpB,UAAU,IAAI,IAAI;IAClB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC/B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACnC,cAAc,IAAI,SAAS,GAAG,QAAQ,GAAG,SAAS;IAClD,iBAAiB,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAIxE,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAetC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAc7B,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQ1C,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAShC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO/B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IA8BrC,SAAS,IAAI,YAAY,GAAG,IAAI;IAIhC,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAc5C,6CAA6C;IAC7C,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAIjD,uEAAuE;IACvE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IA2BjD,MAAM,IAAI,IAAI;IAgBd,OAAO,IAAI,IAAI;IAiBf,OAAO,CAAC,mBAAmB;IAiB3B,4EAA4E;IAC5E,OAAO,CAAC,cAAc;IAuBtB,wFAAwF;IACxF,OAAO,CAAC,cAAc;IAYtB,kFAAkF;IAClF,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,iBAAiB;IAOzB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,qBAAqB;IAyD7B,OAAO,CAAC,iBAAiB;IAmCzB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,gBAAgB;CAazB"}
@@ -0,0 +1,16 @@
1
+ import { OHLCBar, DataSeries } from '@tradecanvas/commons';
2
+ export declare class DataManager {
3
+ private data;
4
+ getData(): DataSeries;
5
+ setData(data: DataSeries): void;
6
+ appendBar(bar: OHLCBar): void;
7
+ updateLastBar(bar: OHLCBar): void;
8
+ updateLastBarFromTick(tick: {
9
+ price: number;
10
+ volume?: number;
11
+ time: number;
12
+ }): void;
13
+ getLength(): number;
14
+ clear(): void;
15
+ }
16
+ //# sourceMappingURL=DataManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataManager.d.ts","sourceRoot":"","sources":["../src/DataManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4BhE,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAkB;IAE9B,OAAO,IAAI,UAAU;IAIrB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAO/B,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAK7B,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAUjC,qBAAqB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOnF,SAAS,IAAI,MAAM;IAInB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,19 @@
1
+ import { ViewportState, Rect } from '@tradecanvas/commons';
2
+ export interface PaneInfo {
3
+ instanceId: string;
4
+ height: number;
5
+ rect: Rect;
6
+ }
7
+ export declare class PaneManager {
8
+ private panels;
9
+ private containerWidth;
10
+ private containerHeight;
11
+ resize(width: number, height: number): void;
12
+ addPanel(instanceId: string, height?: number): void;
13
+ removePanel(instanceId: string): void;
14
+ getPanels(): PaneInfo[];
15
+ getMainChartRect(): Rect;
16
+ createPanelViewport(panel: PaneInfo, mainViewport: ViewportState): ViewportState;
17
+ private recalcLayout;
18
+ }
19
+ //# sourceMappingURL=PaneManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaneManager.d.ts","sourceRoot":"","sources":["../src/PaneManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGhE,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAE5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAM3C,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,SAAuB,GAAG,IAAI;IAKjE,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAKrC,SAAS,IAAI,QAAQ,EAAE;IAIvB,gBAAgB,IAAI,IAAI;IAUxB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,GAAG,aAAa;IAQhF,OAAO,CAAC,YAAY;CAarB"}
@@ -0,0 +1,8 @@
1
+ import { Theme, ThemeName } from '@tradecanvas/commons';
2
+ export declare class ThemeManager {
3
+ private theme;
4
+ constructor(themeOrName?: ThemeName | Theme);
5
+ getTheme(): Theme;
6
+ setTheme(themeOrName: ThemeName | Theme): void;
7
+ }
8
+ //# sourceMappingURL=ThemeManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeManager.d.ts","sourceRoot":"","sources":["../src/ThemeManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG7D,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAQ;gBAET,WAAW,CAAC,EAAE,SAAS,GAAG,KAAK;IAU3C,QAAQ,IAAI,KAAK;IAIjB,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;CAS/C"}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@tradecanvas/commons`),t=require(`@tradecanvas/core`);function n(e){if(!e||typeof e.time!=`number`)return!1;let{open:t,high:n,low:r,close:i}=e;return!(!isFinite(t)||!isFinite(n)||!isFinite(r)||!isFinite(i)||t<0||n<0||r<0||i<0||n<r||e.volume!==void 0&&(!isFinite(e.volume)||e.volume<0))}function r(e){return{...e,high:Math.max(e.open,e.high,e.low,e.close),low:Math.min(e.open,e.high,e.low,e.close),volume:e.volume===void 0?0:Math.max(0,e.volume)}}var i=class{data=[];getData(){return this.data}setData(e){this.data=e.filter(n).map(r)}appendBar(e){n(e)&&this.data.push(r(e))}updateLastBar(e){if(!n(e))return;let t=r(e);if(this.data.length===0){this.data.push(t);return}this.data[this.data.length-1]=t}updateLastBarFromTick(t){this.data.length!==0&&(!isFinite(t.price)||t.price<0||t.volume!==void 0&&(!isFinite(t.volume)||t.volume<0)||(this.data[this.data.length-1]=(0,e.mergeBar)(this.data[this.data.length-1],t)))}getLength(){return this.data.length}clear(){this.data=[]}},a=class{theme;constructor(t){!t||t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}getTheme(){return this.theme}setTheme(t){t===`dark`?this.theme={...e.DARK_THEME}:t===`light`?this.theme={...e.LIGHT_THEME}:this.theme={...t}}},o=200,s=80,c=class{panels=[];containerWidth=0;containerHeight=0;resize(e,t){this.containerWidth=e,this.containerHeight=t}addPanel(t,n=`bottom`,r){let i=n===`left`||n===`right`;this.panels.push({id:t,position:n,size:r??(i?o:e.DEFAULT_PANEL_HEIGHT),minSize:i?s:e.MIN_PANEL_HEIGHT,content:{type:`indicator`,indicatorInstanceId:t}})}removePanel(e){this.panels=this.panels.filter(t=>t.id!==e)}setPanelPosition(t,n){let r=this.panels.find(e=>e.id===t);if(r){let t=r.position===`left`||r.position===`right`,i=n===`left`||n===`right`;r.position=n,t!==i&&(r.size=i?o:e.DEFAULT_PANEL_HEIGHT,r.minSize=i?s:e.MIN_PANEL_HEIGHT)}}setPanelSize(e,t){let n=this.panels.find(t=>t.id===e);n&&(n.size=Math.max(n.minSize,t))}getPanels(){return this.panels}resolve(){let t=this.panels.filter(e=>e.position===`left`),n=this.panels.filter(e=>e.position===`right`),r=this.panels.filter(e=>e.position===`top`),i=this.panels.filter(e=>e.position===`bottom`),a=t.reduce((e,t)=>e+t.size,0),o=n.reduce((e,t)=>e+t.size,0),s=r.reduce((e,t)=>e+t.size,0),c=i.reduce((e,t)=>e+t.size,0),l={x:a,y:s,width:Math.max(0,this.containerWidth-a-o-e.PRICE_AXIS_WIDTH),height:Math.max(0,this.containerHeight-s-c-e.TIME_AXIS_HEIGHT)},u=[],d=[],f=0;for(let n of t)u.push({config:n,rect:{x:f,y:0,width:n.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:n.id,rect:{x:f+n.size-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=n.size;let p=0;for(let e of r)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p+e.size-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;p=l.y+l.height;for(let e of i)u.push({config:e,rect:{x:a,y:p,width:l.width,height:e.size}}),d.push({panelId:e.id,rect:{x:a,y:p-2,width:l.width,height:4},orientation:`horizontal`}),p+=e.size;f=a+l.width+e.PRICE_AXIS_WIDTH;for(let t of n)u.push({config:t,rect:{x:f,y:0,width:t.size,height:this.containerHeight-e.TIME_AXIS_HEIGHT}}),d.push({panelId:t.id,rect:{x:f-2,y:0,width:4,height:this.containerHeight},orientation:`vertical`}),f+=t.size;return{mainChartRect:l,panels:u,dividers:d}}getMainChartRect(){return this.resolve().mainChartRect}},l=class{constructor(e){this.indicatorEngine=e}registerIndicator(e){this.indicatorEngine.register(e)}},u=class{static version=`0.3.0`;engine;viewport;dataManager;themeManager;layoutManager;pluginManager;indicatorEngine;drawingManager;drawingRenderer;tradingManager;tradingRenderer;eventBus;streamManager=null;autoScrollOnNewBar=!0;displayDataCache=null;resolvedLayoutCache=null;panelInfoCache=null;renderScheduled=!1;containerSizeCache=null;containerSizeCacheTime=0;chartLegend;watermark;barCountdown;sessionBreaks;compareRenderer;countdownInterval=null;volumeRenderer;alertManager;replayManager;undoRedoManager;autoSaveTimer=null;autoSaveDelay=0;autoSaveKey=null;animator;crosshairTooltip;interactionManager;crosshairHandler;chartRenderer;gridRenderer;priceAxis;timeAxis;options;features;marketConfig=null;container;currentPriceLine;constructor(n,r){this.container=n,this.options=r;let o=r.features??{};this.features={drawings:o.drawings??!0,drawingTools:o.drawingTools??[],drawingMagnet:o.drawingMagnet??!0,drawingUndoRedo:o.drawingUndoRedo??!0,trading:o.trading??!0,tradingContextMenu:o.tradingContextMenu??!0,indicators:o.indicators??!0,indicatorIds:o.indicatorIds??[],panning:o.panning??!0,zooming:o.zooming??!0,crosshair:o.crosshair??!0,keyboard:o.keyboard??!0,priceAxis:o.priceAxis??!0,timeAxis:o.timeAxis??!0,grid:o.grid??r.grid?.visible??!0,legend:o.legend??!0,volume:o.volume??!0,watermark:o.watermark??!0,saveLoad:o.saveLoad??!0,screenshot:o.screenshot??!0,alerts:o.alerts??!0,replay:o.replay??!0,sessionBreaks:o.sessionBreaks??!0,barCountdown:o.barCountdown??!0,compareSymbols:o.compareSymbols??!0,dataExport:o.dataExport??!0,logScale:o.logScale??!0,timeframes:o.timeframes??[],defaultTimeframeFavorites:o.defaultTimeframeFavorites??[]},n.style.position=`relative`,n.style.overflow=`hidden`,n.tabIndex=0,n.style.outline=`none`,this.dataManager=new i,this.themeManager=new a(r.theme),this.layoutManager=new c,this.indicatorEngine=new t.IndicatorEngine,this.pluginManager=new l(this.indicatorEngine),this.eventBus=new t.EventBus,(0,t.registerBuiltInIndicators)(this.indicatorEngine),this.drawingManager=new t.DrawingManager,(0,t.registerBuiltInDrawingTools)(this.drawingManager),this.drawingRenderer=new t.DrawingRenderer(this.drawingManager),this.drawingManager.setRequestRender(()=>{this.syncRenderContext(),this.engine.requestRender(e.LayerType.Overlay),this.scheduleAutoSave()}),this.drawingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.undoRedoManager=new t.UndoRedoManager,this.drawingManager.setUndoRedoManager(this.undoRedoManager),this.drawingManager.setDataGetter(()=>this.dataManager.getData()),this.drawingManager.setDisplayDataGetter(()=>this.getDisplayData()),r.crosshair?.mode===`magnet`&&this.drawingManager.setMagnetMode(`magnet`),this.tradingManager=new t.TradingManager,this.tradingRenderer=new t.TradingRenderer(this.tradingManager),this.tradingManager.setContainer(n),this.tradingManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.tradingManager.setEventCallback((e,t)=>{this.eventBus.emit(e,t)}),this.engine=new t.RenderEngine(n);let s=this.engine.dprManager.getContainerSize();this.viewport=new t.Viewport(s.width,s.height,r.minBarSpacing??2,r.maxBarSpacing??30,r.rightMargin??5),this.layoutManager.resize(s.width,s.height),this.engine.onContainerResize=e=>{if(e.width<=0||e.height<=0)return;let t=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(t)},this.chartRenderer=this.createChartRenderer(r.chartType),this.gridRenderer=new t.GridRenderer,r.grid?.visible===!1&&this.gridRenderer.setVisible(!1),this.priceAxis=new t.PriceAxis,this.timeAxis=new t.TimeAxis,this.crosshairHandler=new t.CrosshairHandler,r.crosshair?.mode&&this.crosshairHandler.setMode(r.crosshair.mode),this.crosshairHandler.setCallback((e,t)=>{if(e!==null&&t){let n=this.dataManager.getData(),r=e<n.length?n[e]:void 0;this.chartLegend.setHoverBar(r??null),r&&this.crosshairTooltip.show(t,r,this.themeManager.getTheme(),this.cachedContainerSize()),this.eventBus.emit(`crosshairMove`,{point:t,bar:r,barIndex:e})}else this.crosshairTooltip.hide(),this.chartLegend.setHoverBar(null)}),this.chartLegend=new t.ChartLegend,this.chartLegend.setChartType(r.chartType),this.watermark=new t.Watermark,r.watermark&&this.watermark.setConfig(r.watermark),this.volumeRenderer=new t.VolumeRenderer,this.barCountdown=new t.BarCountdown,this.sessionBreaks=new t.SessionBreaks,this.compareRenderer=new t.CompareRenderer,r.sessionBreaks?this.sessionBreaks.setConfig({visible:r.sessionBreaks.visible??!0,color:r.sessionBreaks.color,lineStyle:r.sessionBreaks.lineStyle,lineWidth:r.sessionBreaks.lineWidth}):r.features?.sessionBreaks!==!1&&this.sessionBreaks.setVisible(!0),r.logScale&&this.viewport.setLogScale(!0),this.animator=new t.Animator,this.crosshairTooltip=new t.CrosshairTooltip,this.crosshairTooltip.create(n),new t.KeyboardHandler({scrollBars:e=>{let t=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(e*t),this.updateViewportAndRender()},zoom:e=>{let t=this.viewport.getState().chartRect.width;this.viewport.zoom(e,t/2),this.updateViewportAndRender()},goToStart:()=>{this.viewport.scrollBy(-1/0),this.updateViewportAndRender()},goToEnd:()=>{this.viewport.scrollToEnd(),this.updateViewportAndRender()},fitContent:()=>this.fitContent()}),this.currentPriceLine=new t.CurrentPriceLine,this.alertManager=new t.AlertManager,this.alertManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.alertManager.on(`triggered`,e=>{this.eventBus.emit(`dataUpdate`,{alert:`triggered`,alertId:e.id,price:e.price,message:e.message})}),this.replayManager=new t.ReplayManager,this.interactionManager=new t.InteractionManager(n),this.features.panning&&this.interactionManager.setPanHandler(new t.PanHandler(e=>{this.viewport.scrollBy(e),this.updateViewportAndRender()})),this.features.zooming&&this.interactionManager.setZoomHandler(new t.ZoomHandler((e,t)=>{this.viewport.zoom(e,t),this.updateViewportAndRender()})),this.features.crosshair&&this.interactionManager.setCrosshairHandler(this.crosshairHandler),this.features.drawings&&this.interactionManager.setDrawingManager(this.drawingManager,()=>this.viewport.getState()),this.features.trading&&this.interactionManager.setTradingManager(this.tradingManager,()=>this.viewport.getState()),this.interactionManager.setOverlayDirtyCallback(()=>{this.engine.requestRender(e.LayerType.Overlay),this.layoutManager.getPanels().length>0&&this.engine.requestRender(e.LayerType.UI)}),this.interactionManager.attach(),this.syncRenderContext(),this.engine.start()}setData(e){this.dataManager.setData(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.sessionBreaks.invalidateCache(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),e.length>0&&this.currentPriceLine.setPrice(e[e.length-1].close),this.updateViewportAndRender(!0),this.eventBus.emit(`dataUpdate`,{length:e.length})}appendBar(e){this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.displayDataCache=null,this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}updateLastBar(e){this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.scheduleRender()}updateLastBarFromTick(e){this.dataManager.updateLastBarFromTick(e),this.currentPriceLine.setPrice(e.price),this.options.chartType!==`candlestick`&&this.options.chartType!==`line`&&this.options.chartType!==`area`&&this.options.chartType!==`bar`&&this.options.chartType!==`hollowCandle`&&(this.displayDataCache=null),this.scheduleRender()}setChartType(e){this.options.chartType=e,this.chartRenderer=this.createChartRenderer(e),this.chartLegend.setChartType(e),this.displayDataCache=null,this.updateViewportAndRender(!0)}addIndicator(e,t={},n=`bottom`){if(!this.features.indicators||this.features.indicatorIds.length>0&&!this.features.indicatorIds.includes(e))return null;let r=this.indicatorEngine.addIndicator(e,t,this.dataManager.getData());return this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e)?.placement===`panel`&&this.layoutManager.addPanel(r,n),this.eventBus.emit(`indicatorAdd`,{instanceId:r,id:e}),this.engine.requestRender(),r}updateIndicator(e,t){this.indicatorEngine.updateIndicator(e,t,this.dataManager.getData()),this.engine.requestRender()}removeIndicator(e){this.indicatorEngine.removeIndicator(e),this.layoutManager.removePanel(e),this.eventBus.emit(`indicatorRemove`,{instanceId:e}),this.engine.requestRender()}getIndicatorOutput(e){return this.indicatorEngine.getOutput(e)}registerIndicator(e){this.pluginManager.registerIndicator(e)}static indicators(){let e=new t.IndicatorEngine;return(0,t.registerBuiltInIndicators)(e),e.getAvailableIndicators()}setPanelPosition(e,t){this.layoutManager.setPanelPosition(e,t),this.engine.requestRender()}setPanelSize(e,t){this.layoutManager.setPanelSize(e,t),this.engine.requestRender()}setDrawingTool(e){this.features.drawings&&(e&&this.features.drawingTools.length>0&&!this.features.drawingTools.includes(e)||this.drawingManager.setActiveTool(e))}getDrawingTool(){return this.drawingManager.getActiveTool()}setDrawingStyle(e){this.drawingManager.setStyle(e)}getDrawings(){return this.drawingManager.getDrawings()}setDrawings(e){this.drawingManager.setDrawings(e)}removeDrawing(e){this.drawingManager.removeDrawing(e)}clearDrawings(){this.drawingManager.clearDrawings()}registerDrawingTool(e){this.drawingManager.register(e)}undo(){return this.features.drawingUndoRedo?this.drawingManager.undo():!1}redo(){return this.features.drawingUndoRedo?this.drawingManager.redo():!1}getUndoRedoState(){return this.undoRedoManager.getState()}setDrawingMagnet(e){this.drawingManager.setMagnetMode(e?`magnet`:`none`)}getDrawingMagnet(){return this.drawingManager.getMagnetMode()===`magnet`}lockAllDrawings(){this.drawingManager.lockAllDrawings()}unlockAllDrawings(){this.drawingManager.unlockAllDrawings()}hideAllDrawings(){this.drawingManager.hideAllDrawings()}showAllDrawings(){this.drawingManager.showAllDrawings()}duplicateDrawing(e){let t=e??this.drawingManager.getSelectedDrawingId();return t?this.drawingManager.duplicateDrawing(t):null}exportVisibleData(e=`csv`,n){let r=this.viewport.getState(),i=this.dataManager.getData(),a=Math.max(0,r.visibleRange.from),o=Math.min(i.length-1,r.visibleRange.to),s=i.slice(a,o+1);if(e===`json`){let e=t.DataExporter.toJSON(s);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(s);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}exportAllData(e=`csv`,n){let r=this.dataManager.getData();if(e===`json`){let e=t.DataExporter.toJSON(r);t.DataExporter.download(e,n??`chart-data.json`,`application/json`)}else{let e=t.DataExporter.toCSV(r);t.DataExporter.download(e,n??`chart-data.csv`,`text/csv`)}}setAutoSave(e,t=5e3){this.autoSaveKey=e,this.autoSaveDelay=t}disableAutoSave(){this.autoSaveDelay=0,this.autoSaveKey=null,this.autoSaveTimer&&=(clearTimeout(this.autoSaveTimer),null)}scheduleAutoSave(){this.autoSaveDelay<=0||!this.autoSaveKey||(this.autoSaveTimer&&clearTimeout(this.autoSaveTimer),this.autoSaveTimer=setTimeout(()=>{this.autoSaveTimer=null,this.autoSaveKey&&this.saveState(this.autoSaveKey)},this.autoSaveDelay))}getAvailableIndicators(){return this.indicatorEngine.getAvailableIndicators()}getIndicatorInputs(e){let t=this.indicatorEngine.getAvailableIndicators().find(t=>t.id===e);return t?{id:t.id,params:t.defaultConfig}:null}getActiveIndicators(){return this.indicatorEngine.getActiveIndicators()}getIndicatorConfig(e){let t=this.indicatorEngine.getIndicatorConfig(e);return t?{id:t.id,params:{...t.params}}:null}updateIndicatorStyle(e,t){this.indicatorEngine.updateIndicatorStyle(e,t),this.engine.requestRender()}setOrders(e){this.features.trading&&this.tradingManager.setOrders(e)}setPositions(e){this.features.trading&&this.tradingManager.setPositions(e)}setDepthData(e){this.features.trading&&this.tradingManager.setDepthData(e)}setCurrentPrice(e){this.tradingManager.setCurrentPrice(e),this.currentPriceLine.setPrice(e),this.scheduleRender(),this.features.alerts&&this.alertManager.checkPrice(e)}setTradingConfig(e){this.features.trading&&this.tradingManager.setConfig(e)}async connect(n){this.disconnectStream(),this.streamManager=new t.StreamManager,this.streamManager.on(`snapshot`,e=>{this.setData(e)}),this.streamManager.on(`barClose`,e=>{this.dataManager.appendBar(e),this.crosshairHandler.setData(this.dataManager.getData()),this.autoScrollOnNewBar&&this.viewport.scrollToEnd(),this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.updateViewportAndRender()}),this.streamManager.on(`barUpdate`,e=>{this.dataManager.updateLastBar(e),this.currentPriceLine.setPrice(e.close),this.scheduleRender()}),this.streamManager.on(`priceChange`,({price:t})=>{this.tradingManager.setCurrentPrice(t),this.currentPriceLine.setPrice(t),this.engine.requestRender(e.LayerType.Overlay),this.engine.requestRender(e.LayerType.UI)}),this.streamManager.on(`connectionChange`,e=>{this.eventBus.emit(`dataUpdate`,{connection:e})}),this.streamManager.on(`error`,e=>{this.eventBus.emit(`dataUpdate`,{error:e.message})}),this.autoScrollOnNewBar=n.autoScroll!==!1,await this.streamManager.connect(n);let r=this.timeframeToMs(n.timeframe);this.barCountdown.setTimeframeMs(r),this.countdownInterval&&clearInterval(this.countdownInterval),this.countdownInterval=setInterval(()=>{this.barCountdown.isVisible()&&this.engine.requestRender(e.LayerType.UI)},1e3)}async switchStream(e,t){this.streamManager&&await this.streamManager.switchTo(e,t)}disconnectStream(){this.streamManager&&=(this.streamManager.dispose(),null)}setBarCountdownVisible(t){this.barCountdown.setVisible(t),this.engine.requestRender(e.LayerType.UI)}setSessionBreaksVisible(t){this.sessionBreaks.setVisible(t),this.engine.requestRender(e.LayerType.Background)}addCompareSymbol(t,n,r,i){this.compareRenderer.addSymbol({id:t,label:n,data:r,color:i,visible:!0}),this.engine.requestRender(e.LayerType.Main)}removeCompareSymbol(t){this.compareRenderer.removeSymbol(t),this.engine.requestRender(e.LayerType.Main)}updateCompareData(t,n){this.compareRenderer.setSymbolData(t,n),this.engine.requestRender(e.LayerType.Main)}setCompareMode(t){this.compareRenderer.setMode(t),this.engine.requestRender(e.LayerType.Main)}clearCompareSymbols(){this.compareRenderer.clear(),this.engine.requestRender(e.LayerType.Main)}setLogScale(e){this.viewport.setLogScale(e),this.updateViewportAndRender()}isLogScale(){return this.viewport.isLogScale()}setSessionBreaksConfig(t){this.sessionBreaks.setConfig(t),this.engine.requestRender(e.LayerType.Background)}getConnectionState(){return this.streamManager?.getConnectionState()??`disconnected`}getConnectionInfo(){return this.streamManager?.getConnectionInfo()??{state:`disconnected`}}setAutoScroll(e){this.autoScrollOnNewBar=e}scrollTo(e){let t=this.dataManager.getData();for(let n=0;n<t.length;n++)if(t[n].time>=e){let e=this.viewport.getState().barWidth+this.viewport.getState().barSpacing;this.viewport.scrollBy(n*e-this.viewport.getState().offset),this.updateViewportAndRender();return}}scrollToEnd(){this.viewport.scrollToEnd(),this.updateViewportAndRender()}setVisibleRange(e,t){let n=this.dataManager.getData(),r=0,i=n.length-1;for(let t=0;t<n.length;t++)if(n[t].time>=e){r=t;break}for(let e=n.length-1;e>=0;e--)if(n[e].time<=t){i=e;break}let a=i-r+1;if(a>0){let e=this.viewport.getState().chartRect.width,t=e/a,n=Math.max(2,t-this.viewport.getState().barSpacing);this.viewport.zoom((n-this.viewport.getState().barWidth)/this.viewport.getState().barWidth,e/2)}this.updateViewportAndRender()}zoomIn(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(.2,e/2),this.updateViewportAndRender()}zoomOut(){let e=this.viewport.getState().chartRect.width;this.viewport.zoom(-.2,e/2),this.updateViewportAndRender()}fitContent(){let e=this.dataManager.getData();e.length!==0&&this.setVisibleRange(e[0].time,e[e.length-1].time)}on(e,t){this.eventBus.on(e,t)}off(e,t){this.eventBus.off(e,t)}enableTauriBridge(e){this.eventBus.enableTauriBridge({enabled:!0,...e})}disableTauriBridge(){this.eventBus.disableTauriBridge()}setTheme(e){this.themeManager.setTheme(e),this.syncRenderContext(),this.container.style.backgroundColor=this.themeManager.getTheme().background,this.engine.requestRender(),this.eventBus.emit(`themeChange`,{theme:e})}getTheme(){return this.themeManager.getTheme()}setWatermark(t,n){this.watermark.setConfig({text:t,...n}),this.engine.requestRender(e.LayerType.Background)}setAutoScale(e){this.options.autoScale=e,this.updateViewportAndRender()}isAutoScale(){return this.options.autoScale!==!1}setCrosshairMode(t){this.crosshairHandler.setMode(t),this.engine.requestRender(e.LayerType.Overlay)}getCrosshairMode(){return this.crosshairHandler.getMode()}setGridVisible(t){this.gridRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Background)}isGridVisible(){return this.gridRenderer.isVisible()}setVolumeVisible(t){this.volumeRenderer.setVisible(t),this.engine.requestRender(e.LayerType.Main)}setTooltipVisible(e){e||this.crosshairTooltip.hide()}setLegend(t){this.chartLegend.setConfig(t),this.engine.requestRender(e.LayerType.UI)}setSymbolName(t){this.chartLegend.setSymbol(t),this.engine.requestRender(e.LayerType.UI)}screenshot(e){this.features.screenshot&&t.Screenshot.download(this.container,e,this.themeManager.getTheme().background)}screenshotDataURL(){return this.features.screenshot?t.Screenshot.toDataURL(this.container,this.themeManager.getTheme().background):null}async screenshotBlob(){return this.features.screenshot?t.Screenshot.toBlob(this.container,this.themeManager.getTheme().background):null}addAlert(e,t=`crossing`,n){if(!this.features.alerts)return null;let r=this.alertManager.addAlert(e,t,n);return this.scheduleAutoSave(),r}removeAlert(e){this.alertManager.removeAlert(e),this.scheduleAutoSave()}getAlerts(){return this.alertManager.getAlerts()}clearAlerts(){this.alertManager.clearAlerts(),this.scheduleAutoSave()}saveAlerts(e){this.alertManager.saveToStorage(e)}loadAlerts(t){this.alertManager.loadFromStorage(t),this.engine.requestRender(e.LayerType.Overlay)}replay(e){if(!this.features.replay)return;let t=this.dataManager.getData();this.replayManager.load(t),this.replayManager.on(`bar`,({bar:e,index:n})=>{let r=t.slice(0,n+1);this.dataManager.setData(r),this.crosshairHandler.setData(r),this.indicatorEngine.recalculateAll(r),this.updateViewportAndRender()}),this.replayManager.play(e)}replayPause(){this.replayManager.pause()}replayResume(){this.replayManager.resume()}replayStop(){this.replayManager.stop()}replaySeek(e){this.replayManager.seekTo(e)}setReplaySpeed(e){this.replayManager.setSpeed(e)}getReplayState(){return this.replayManager.getState()}getReplayProgress(){return this.replayManager.getProgress()}saveState(e){if(!this.features.saveLoad)return null;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType}),r=t.ChartStateManager.serialize(n);return e&&t.ChartStateManager.saveToStorage(e,n),r}loadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.deserialize(e);if(n.chartType&&this.setChartType(n.chartType),n.drawings&&this.setDrawings(n.drawings),n.theme&&this.setTheme(n.theme),n.alerts){this.clearAlerts();for(let e of n.alerts)this.addAlert(e.price,e.condition,e.message)}}loadStateFromStorage(e){if(!this.features.saveLoad)return!1;let n=t.ChartStateManager.loadFromStorage(e);return n?(this.loadState(t.ChartStateManager.serialize(n)),!0):!1}downloadState(e){if(!this.features.saveLoad)return;let n=t.ChartStateManager.capture({getDrawings:()=>this.getDrawings(),getTheme:()=>this.getTheme(),getAlerts:()=>this.getAlerts()},{chartType:this.options.chartType});t.ChartStateManager.downloadFile(n,e)}async loadStateFromFile(){if(!this.features.saveLoad)return;let e=await t.ChartStateManager.loadFromFile();this.loadState(t.ChartStateManager.serialize(e))}setLocale(t){(0,e.setLocale)(t),this.engine.requestRender()}setMarket(e){if(this.marketConfig=e,e.colorScheme){let t={...this.themeManager.getTheme(),candleUp:e.colorScheme.up,candleDown:e.colorScheme.down,candleUpWick:e.colorScheme.up,candleDownWick:e.colorScheme.down,volumeUp:e.colorScheme.up.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.up}4D`,volumeDown:e.colorScheme.down.replace(`)`,`, 0.3)`).replace(`rgb(`,`rgba(`)||`${e.colorScheme.down}4D`};this.themeManager.setTheme(t)}e.pricePrecision!==void 0&&(this.tradingManager.setConfig({pricePrecision:e.pricePrecision}),this.alertManager.setPricePrecision(e.pricePrecision),this.streamManager?.priceLine.setPricePrecision(e.pricePrecision),this.crosshairHandler.setPricePrecision(e.pricePrecision)),this.syncRenderContext(),this.engine.requestRender()}getMarket(){return this.marketConfig}setPriceLimits(t){this.marketConfig&&((0,e.computePriceLimits)(t,this.marketConfig)&&(this.marketConfig.priceLimits={...this.marketConfig.priceLimits,referencePrice:t}),this.engine.requestRender())}getFeatures(){return this.features}setFeatures(t){Object.assign(this.features,t),t.crosshair===!1&&this.crosshairTooltip.hide(),t.grid!==void 0&&this.engine.requestRender(e.LayerType.Background),t.volume!==void 0&&(this.volumeRenderer.setVisible(t.volume),this.engine.requestRender(e.LayerType.Main)),t.drawings===!1&&this.drawingManager.setActiveTool(null),t.trading===!1&&(this.tradingManager.setOrders([]),this.tradingManager.setPositions([])),this.engine.requestRender()}resize(){let e=this.engine.dprManager.readContainerSize();if(e.width<=0||e.height<=0)return;this.containerSizeCache=e,this.containerSizeCacheTime=Date.now();let t=this.engine.dprManager.getDpr();this.engine.layerManager.resize(e,t);let n=this.viewport.isAtEnd();this.viewport.resize(e.width,e.height),this.layoutManager.resize(e.width,e.height),this.updateViewportAndRender(n),this.eventBus.emit(`resize`,e)}destroy(){this.countdownInterval&&clearInterval(this.countdownInterval),this.disableAutoSave(),this.disconnectStream(),this.interactionManager.detach(),this.tradingManager.destroy(),this.animator.dispose(),this.crosshairTooltip.destroy(),this.replayManager.dispose(),this.undoRedoManager.clear(),this.engine.destroy(),this.eventBus.destroy(),this.container.innerHTML=``}createChartRenderer(e){switch(e){case`candlestick`:return new t.CandlestickRenderer;case`heikinAshi`:return new t.CandlestickRenderer;case`line`:return new t.LineRenderer;case`area`:return new t.AreaRenderer;case`bar`:return new t.BarRenderer;case`hollowCandle`:return new t.HollowCandleRenderer;case`baseline`:return new t.BaselineRenderer;case`renko`:return new t.RenkoRenderer;case`lineBreak`:return new t.CandlestickRenderer;case`kagi`:return new t.KagiRenderer;case`pointAndFigure`:return new t.PointAndFigureRenderer;default:return new t.CandlestickRenderer}}getDisplayData(){if(this.displayDataCache)return this.displayDataCache;let e=this.dataManager.getData();if(e.length===0)return e;let n;switch(this.options.chartType){case`heikinAshi`:n=(0,t.toHeikinAshi)(e);break;case`renko`:n=(0,t.toRenko)(e,{brickSize:0,useATR:!0,atrPeriod:14});break;case`lineBreak`:n=(0,t.toLineBreak)(e,3);break;case`kagi`:n=(0,t.toKagi)(e,4);break;case`pointAndFigure`:n=(0,t.toPointAndFigure)(e,e.reduce((e,t)=>e+t.close,0)/e.length*.01,3);break;default:n=e}return this.displayDataCache=n,n}scheduleRender(){this.renderScheduled||(this.renderScheduled=!0,requestAnimationFrame(()=>{this.renderScheduled=!1;let e=this.getDisplayData();this.viewport.updateData(e,this.options.autoScale!==!1),this.syncRenderContext(),this.engine.requestRender()}))}updateViewportAndRender(e=!1){this.resolvedLayoutCache=null,this.panelInfoCache=null;let t=this.getResolvedLayout();this.viewport.setChartRect(t.mainChartRect);let n=this.getDisplayData();this.viewport.updateData(n,this.options.autoScale!==!1),e&&this.viewport.scrollToEnd(),this.syncRenderContext(),this.engine.requestRender()}getResolvedLayout(){return this.resolvedLayoutCache||=this.layoutManager.resolve(),this.resolvedLayoutCache}cachedContainerSize(){let e=Date.now();return(!this.containerSizeCache||e-this.containerSizeCacheTime>500)&&(this.containerSizeCache=this.engine.dprManager.getContainerSize(),this.containerSizeCacheTime=e),this.containerSizeCache}buildPanelRenderInfos(){if(this.panelInfoCache)return this.panelInfoCache;let e=this.getResolvedLayout(),t=this.viewport.getState(),n=e.panels.map(e=>{let n=this.indicatorEngine.getOutput(e.config.id),r=0,i=100;if(n){let e=1/0,a=-1/0,{from:o,to:s}=t.visibleRange,c=0;for(let[,t]of n.values){if(c>=o&&c<=s)for(let n in t){let r=t[n];r!==void 0&&(r<e&&(e=r),r>a&&(a=r))}c++}if(e!==1/0){let t=a-e||1;r=e-t*.1,i=a+t*.1}}let a={x:e.rect.x,y:e.rect.y+20,width:e.rect.width,height:Math.max(0,e.rect.height-20)};return{instanceId:e.config.id,rect:e.rect,viewport:{...t,chartRect:a,priceRange:{min:r,max:i}}}});return this.panelInfoCache=n,n}syncRenderContext(){let e=this.getResolvedLayout(),t=this.features.indicators?this.buildPanelRenderInfos():[],n=e.panels.filter(e=>e.config.position===`bottom`).reduce((e,t)=>e+t.rect.height,0),r=e.mainChartRect.y+e.mainChartRect.height+n;this.engine.setRenderContext({chartRenderer:this.chartRenderer,gridRenderer:this.features.grid?this.gridRenderer:null,priceAxis:this.features.priceAxis?this.priceAxis:null,timeAxis:this.features.timeAxis?this.timeAxis:null,crosshairHandler:this.features.crosshair?this.crosshairHandler:null,indicatorEngine:this.features.indicators?this.indicatorEngine:null,drawingRenderer:this.features.drawings?this.drawingRenderer:null,tradingRenderer:this.features.trading?this.tradingRenderer:null,currentPriceLine:this.streamManager?.priceLine??this.currentPriceLine,chartLegend:this.features.legend?this.chartLegend:null,volumeRenderer:this.features.volume?this.volumeRenderer:null,watermark:this.features.watermark?this.watermark:null,barCountdown:this.barCountdown,sessionBreaks:this.sessionBreaks,compareRenderer:this.compareRenderer,panels:t,priceLimits:this.buildPriceLimits(),timeAxisY:r,viewport:this.viewport.getState(),theme:this.themeManager.getTheme(),data:this.getDisplayData()})}timeframeToMs(e){let t=e.match(/^(\d+)([smhdwMy])$/);if(!t)return 0;let n=parseInt(t[1],10);switch(t[2]){case`s`:return n*1e3;case`m`:return n*6e4;case`h`:return n*36e5;case`d`:return n*864e5;case`w`:return n*6048e5;case`M`:return n*2592e6;default:return 0}}buildPriceLimits(){if(!this.marketConfig?.priceLimits?.enabled||!this.marketConfig.priceLimits.referencePrice)return null;let t=(0,e.computePriceLimits)(this.marketConfig.priceLimits.referencePrice,this.marketConfig);return t?{...t,colors:this.marketConfig.colorScheme?{ceiling:this.marketConfig.colorScheme.ceiling,floor:this.marketConfig.colorScheme.floor,reference:this.marketConfig.colorScheme.reference}:void 0}:null}};Object.defineProperty(exports,`AlertManager`,{enumerable:!0,get:function(){return t.AlertManager}}),Object.defineProperty(exports,`Animator`,{enumerable:!0,get:function(){return t.Animator}}),Object.defineProperty(exports,`BarCountdown`,{enumerable:!0,get:function(){return t.BarCountdown}}),Object.defineProperty(exports,`BinanceAdapter`,{enumerable:!0,get:function(){return t.BinanceAdapter}}),exports.Chart=u,Object.defineProperty(exports,`ChartLegend`,{enumerable:!0,get:function(){return t.ChartLegend}}),Object.defineProperty(exports,`ChartStateManager`,{enumerable:!0,get:function(){return t.ChartStateManager}}),Object.defineProperty(exports,`CompareRenderer`,{enumerable:!0,get:function(){return t.CompareRenderer}}),Object.defineProperty(exports,`CrosshairTooltip`,{enumerable:!0,get:function(){return t.CrosshairTooltip}}),Object.defineProperty(exports,`CurrentPriceLine`,{enumerable:!0,get:function(){return t.CurrentPriceLine}}),Object.defineProperty(exports,`DARK_THEME`,{enumerable:!0,get:function(){return e.DARK_THEME}}),Object.defineProperty(exports,`DEFAULT_DRAWING_STYLE`,{enumerable:!0,get:function(){return e.DEFAULT_DRAWING_STYLE}}),Object.defineProperty(exports,`DEFAULT_LEGEND_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_LEGEND_CONFIG}}),Object.defineProperty(exports,`DEFAULT_RECONNECT`,{enumerable:!0,get:function(){return e.DEFAULT_RECONNECT}}),Object.defineProperty(exports,`DEFAULT_STREAM_CONFIG`,{enumerable:!0,get:function(){return e.DEFAULT_STREAM_CONFIG}}),Object.defineProperty(exports,`DEFAULT_TIMEFRAME_FAVORITES`,{enumerable:!0,get:function(){return e.DEFAULT_TIMEFRAME_FAVORITES}}),Object.defineProperty(exports,`DEFAULT_TRADING_CONFIG`,{enumerable:!0,get:function(){return e.DEFAULT_TRADING_CONFIG}}),Object.defineProperty(exports,`DataExporter`,{enumerable:!0,get:function(){return t.DataExporter}}),exports.DataManager=i,Object.defineProperty(exports,`DrawingBase`,{enumerable:!0,get:function(){return t.DrawingBase}}),Object.defineProperty(exports,`Easing`,{enumerable:!0,get:function(){return t.Easing}}),Object.defineProperty(exports,`IndicatorBase`,{enumerable:!0,get:function(){return t.IndicatorBase}}),Object.defineProperty(exports,`KeyboardHandler`,{enumerable:!0,get:function(){return t.KeyboardHandler}}),Object.defineProperty(exports,`LIGHT_THEME`,{enumerable:!0,get:function(){return e.LIGHT_THEME}}),exports.LayoutManager=c,Object.defineProperty(exports,`MARKET_CRYPTO`,{enumerable:!0,get:function(){return e.MARKET_CRYPTO}}),Object.defineProperty(exports,`MARKET_HNX`,{enumerable:!0,get:function(){return e.MARKET_HNX}}),Object.defineProperty(exports,`MARKET_HOSE`,{enumerable:!0,get:function(){return e.MARKET_HOSE}}),Object.defineProperty(exports,`MARKET_NYSE`,{enumerable:!0,get:function(){return e.MARKET_NYSE}}),Object.defineProperty(exports,`MARKET_UPCOM`,{enumerable:!0,get:function(){return e.MARKET_UPCOM}}),Object.defineProperty(exports,`MockAdapter`,{enumerable:!0,get:function(){return t.MockAdapter}}),exports.PluginManager=l,Object.defineProperty(exports,`ReplayManager`,{enumerable:!0,get:function(){return t.ReplayManager}}),Object.defineProperty(exports,`Screenshot`,{enumerable:!0,get:function(){return t.Screenshot}}),Object.defineProperty(exports,`SessionBreaks`,{enumerable:!0,get:function(){return t.SessionBreaks}}),Object.defineProperty(exports,`StreamManager`,{enumerable:!0,get:function(){return t.StreamManager}}),Object.defineProperty(exports,`TIMEFRAMES_CRYPTO`,{enumerable:!0,get:function(){return e.TIMEFRAMES_CRYPTO}}),Object.defineProperty(exports,`TIMEFRAMES_FOREX`,{enumerable:!0,get:function(){return e.TIMEFRAMES_FOREX}}),Object.defineProperty(exports,`TIMEFRAMES_STOCK`,{enumerable:!0,get:function(){return e.TIMEFRAMES_STOCK}}),exports.ThemeManager=a,Object.defineProperty(exports,`TickAggregator`,{enumerable:!0,get:function(){return t.TickAggregator}}),Object.defineProperty(exports,`UndoRedoManager`,{enumerable:!0,get:function(){return t.UndoRedoManager}}),Object.defineProperty(exports,`VN_COLORS`,{enumerable:!0,get:function(){return e.VN_COLORS}}),Object.defineProperty(exports,`VolumeRenderer`,{enumerable:!0,get:function(){return t.VolumeRenderer}}),Object.defineProperty(exports,`Watermark`,{enumerable:!0,get:function(){return t.Watermark}}),Object.defineProperty(exports,`computePriceLimits`,{enumerable:!0,get:function(){return e.computePriceLimits}}),Object.defineProperty(exports,`createVNTheme`,{enumerable:!0,get:function(){return e.createVNTheme}}),Object.defineProperty(exports,`formatNumber`,{enumerable:!0,get:function(){return e.formatNumber}}),Object.defineProperty(exports,`formatVND`,{enumerable:!0,get:function(){return e.formatVND}}),Object.defineProperty(exports,`formatVolumeLoc`,{enumerable:!0,get:function(){return e.formatVolumeLoc}}),Object.defineProperty(exports,`getCurrentSession`,{enumerable:!0,get:function(){return e.getCurrentSession}}),Object.defineProperty(exports,`getLocale`,{enumerable:!0,get:function(){return e.getLocale}}),Object.defineProperty(exports,`registerLocale`,{enumerable:!0,get:function(){return e.registerLocale}}),Object.defineProperty(exports,`setLocale`,{enumerable:!0,get:function(){return e.setLocale}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e.t}}),Object.defineProperty(exports,`toHeikinAshi`,{enumerable:!0,get:function(){return t.toHeikinAshi}}),Object.defineProperty(exports,`toKagi`,{enumerable:!0,get:function(){return t.toKagi}}),Object.defineProperty(exports,`toLineBreak`,{enumerable:!0,get:function(){return t.toLineBreak}}),Object.defineProperty(exports,`toPointAndFigure`,{enumerable:!0,get:function(){return t.toPointAndFigure}}),Object.defineProperty(exports,`toRenko`,{enumerable:!0,get:function(){return t.toRenko}});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/DataManager.ts","../src/ThemeManager.ts","../src/layout/LayoutManager.ts","../src/plugins/PluginManager.ts","../src/Chart.ts"],"sourcesContent":["import type { OHLCBar, DataSeries } from '@tradecanvas/commons';\nimport { mergeBar } from '@tradecanvas/commons';\n\n/** Validate a single OHLC bar. Returns true if bar is usable. */\nfunction isValidBar(bar: OHLCBar): boolean {\n if (!bar || typeof bar.time !== 'number') return false;\n const { open, high, low, close } = bar;\n // Reject NaN / Infinity\n if (!isFinite(open) || !isFinite(high) || !isFinite(low) || !isFinite(close)) return false;\n // Reject negative prices\n if (open < 0 || high < 0 || low < 0 || close < 0) return false;\n // High must be >= low\n if (high < low) return false;\n // Volume (optional) must be non-negative if present\n if (bar.volume !== undefined && (!isFinite(bar.volume) || bar.volume < 0)) return false;\n return true;\n}\n\n/** Sanitize a bar: clamp high/low to envelope OHLC values. */\nfunction sanitizeBar(bar: OHLCBar): OHLCBar {\n return {\n ...bar,\n high: Math.max(bar.open, bar.high, bar.low, bar.close),\n low: Math.min(bar.open, bar.high, bar.low, bar.close),\n volume: bar.volume !== undefined ? Math.max(0, bar.volume) : 0,\n };\n}\n\nexport class DataManager {\n private data: DataSeries = [];\n\n getData(): DataSeries {\n return this.data;\n }\n\n setData(data: DataSeries): void {\n // Filter out completely invalid bars, sanitize the rest\n this.data = data\n .filter(isValidBar)\n .map(sanitizeBar);\n }\n\n appendBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n this.data.push(sanitizeBar(bar));\n }\n\n updateLastBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n const sanitized = sanitizeBar(bar);\n if (this.data.length === 0) {\n this.data.push(sanitized);\n return;\n }\n this.data[this.data.length - 1] = sanitized;\n }\n\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\n if (this.data.length === 0) return;\n if (!isFinite(tick.price) || tick.price < 0) return;\n if (tick.volume !== undefined && (!isFinite(tick.volume) || tick.volume < 0)) return;\n this.data[this.data.length - 1] = mergeBar(this.data[this.data.length - 1], tick);\n }\n\n getLength(): number {\n return this.data.length;\n }\n\n clear(): void {\n this.data = [];\n }\n}\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\n\nexport class ThemeManager {\n private theme: Theme;\n\n constructor(themeOrName?: ThemeName | Theme) {\n if (!themeOrName || themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n\n getTheme(): Theme {\n return this.theme;\n }\n\n setTheme(themeOrName: ThemeName | Theme): void {\n if (themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n}\n","import type { PanelPosition, PanelConfig, ResolvedLayout, ResolvedPanel, DividerRect, Rect } from '@tradecanvas/commons';\nimport { DEFAULT_PANEL_HEIGHT, MIN_PANEL_HEIGHT, PRICE_AXIS_WIDTH, TIME_AXIS_HEIGHT } from '@tradecanvas/commons';\n\nconst DEFAULT_PANEL_WIDTH = 200;\nconst MIN_PANEL_WIDTH = 80;\n\nexport class LayoutManager {\n private panels: PanelConfig[] = [];\n private containerWidth = 0;\n private containerHeight = 0;\n\n resize(width: number, height: number): void {\n this.containerWidth = width;\n this.containerHeight = height;\n }\n\n addPanel(instanceId: string, position: PanelPosition = 'bottom', size?: number): void {\n const isVertical = position === 'left' || position === 'right';\n this.panels.push({\n id: instanceId,\n position,\n size: size ?? (isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT),\n minSize: isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT,\n content: { type: 'indicator', indicatorInstanceId: instanceId },\n });\n }\n\n removePanel(instanceId: string): void {\n this.panels = this.panels.filter((p) => p.id !== instanceId);\n }\n\n setPanelPosition(instanceId: string, position: PanelPosition): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n const wasVertical = panel.position === 'left' || panel.position === 'right';\n const isVertical = position === 'left' || position === 'right';\n panel.position = position;\n if (wasVertical !== isVertical) {\n panel.size = isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT;\n panel.minSize = isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT;\n }\n }\n }\n\n setPanelSize(instanceId: string, size: number): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n panel.size = Math.max(panel.minSize, size);\n }\n }\n\n getPanels(): PanelConfig[] {\n return this.panels;\n }\n\n resolve(): ResolvedLayout {\n const leftPanels = this.panels.filter((p) => p.position === 'left');\n const rightPanels = this.panels.filter((p) => p.position === 'right');\n const topPanels = this.panels.filter((p) => p.position === 'top');\n const bottomPanels = this.panels.filter((p) => p.position === 'bottom');\n\n const leftWidth = leftPanels.reduce((s, p) => s + p.size, 0);\n const rightWidth = rightPanels.reduce((s, p) => s + p.size, 0);\n const topHeight = topPanels.reduce((s, p) => s + p.size, 0);\n const bottomHeight = bottomPanels.reduce((s, p) => s + p.size, 0);\n\n const mainChartRect: Rect = {\n x: leftWidth,\n y: topHeight,\n width: Math.max(0, this.containerWidth - leftWidth - rightWidth - PRICE_AXIS_WIDTH),\n height: Math.max(0, this.containerHeight - topHeight - bottomHeight - TIME_AXIS_HEIGHT),\n };\n\n const resolvedPanels: ResolvedPanel[] = [];\n const dividers: DividerRect[] = [];\n\n // Left panels (stacked vertically)\n let x = 0;\n for (const panel of leftPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x + panel.size - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n // Top panels (stacked horizontally, full width minus left/right)\n let y = 0;\n for (const panel of topPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y + panel.size - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Bottom panels\n y = mainChartRect.y + mainChartRect.height;\n for (const panel of bottomPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Right panels\n x = leftWidth + mainChartRect.width + PRICE_AXIS_WIDTH;\n for (const panel of rightPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n return { mainChartRect, panels: resolvedPanels, dividers };\n }\n\n getMainChartRect(): Rect {\n return this.resolve().mainChartRect;\n }\n}\n","import type { IndicatorPlugin } from '@tradecanvas/commons';\nimport type { IndicatorEngine } from '@tradecanvas/core';\n\nexport class PluginManager {\n constructor(private indicatorEngine: IndicatorEngine) {}\n\n registerIndicator(plugin: IndicatorPlugin): void {\n this.indicatorEngine.register(plugin);\n }\n}\n","import type {\n ChartOptions,\n ChartType,\n OHLCBar,\n DataSeries,\n Theme,\n ThemeName,\n ChartEventType,\n ChartEvent,\n TauriBridgeOptions,\n IndicatorPlugin,\n IndicatorDescriptor,\n IndicatorOutput,\n DrawingToolType,\n DrawingState,\n DrawingStyle,\n DrawingPlugin,\n PanelPosition,\n TradingOrder,\n TradingPosition,\n DepthData,\n TradingConfig,\n MarketConfig,\n Locale,\n StreamConfig,\n ConnectionState,\n ConnectionInfo,\n TimeFrame,\n FeaturesConfig,\n} from '@tradecanvas/commons';\nimport { LayerType, setLocale as setGlobalLocale, computePriceLimits } from '@tradecanvas/commons';\nimport {\n RenderEngine,\n Viewport,\n CandlestickRenderer,\n LineRenderer,\n AreaRenderer,\n BarRenderer,\n GridRenderer,\n PriceAxis,\n TimeAxis,\n InteractionManager,\n PanHandler,\n ZoomHandler,\n CrosshairHandler,\n IndicatorEngine,\n registerBuiltInIndicators,\n EventBus,\n DrawingManager,\n DrawingRenderer,\n registerBuiltInDrawingTools,\n TradingManager,\n TradingRenderer,\n StreamManager,\n ChartLegend,\n Screenshot,\n Watermark,\n BarCountdown,\n VolumeRenderer,\n AlertManager,\n ReplayManager,\n ChartStateManager,\n UndoRedoManager,\n Animator,\n KeyboardHandler,\n CrosshairTooltip,\n HollowCandleRenderer,\n BaselineRenderer,\n RenkoRenderer,\n KagiRenderer,\n PointAndFigureRenderer,\n toHeikinAshi,\n toRenko,\n toLineBreak,\n toKagi,\n toPointAndFigure,\n DataExporter,\n SessionBreaks,\n CompareRenderer,\n CurrentPriceLine,\n} from '@tradecanvas/core';\nimport type { ChartRendererInterface } from '@tradecanvas/core';\nimport { DataManager } from './DataManager.js';\nimport { ThemeManager } from './ThemeManager.js';\nimport { LayoutManager } from './layout/LayoutManager.js';\nimport { PluginManager } from './plugins/PluginManager.js';\n\nexport class Chart {\n static version = '0.3.0';\n\n private engine: RenderEngine;\n private viewport: Viewport;\n private dataManager: DataManager;\n private themeManager: ThemeManager;\n private layoutManager: LayoutManager;\n private pluginManager: PluginManager;\n private indicatorEngine: IndicatorEngine;\n private drawingManager: DrawingManager;\n private drawingRenderer: DrawingRenderer;\n private tradingManager: TradingManager;\n private tradingRenderer: TradingRenderer;\n private eventBus: EventBus;\n private streamManager: StreamManager | null = null;\n private autoScrollOnNewBar = true;\n private displayDataCache: DataSeries | null = null;\n private resolvedLayoutCache: import('@tradecanvas/commons').ResolvedLayout | null = null;\n private panelInfoCache: import('@tradecanvas/core').PanelRenderInfo[] | null = null;\n private renderScheduled = false;\n private containerSizeCache: { width: number; height: number } | null = null;\n private containerSizeCacheTime = 0;\n private chartLegend: ChartLegend;\n private watermark: Watermark;\n private barCountdown: BarCountdown;\n private sessionBreaks: SessionBreaks;\n private compareRenderer: CompareRenderer;\n private countdownInterval: ReturnType<typeof setInterval> | null = null;\n private volumeRenderer: VolumeRenderer;\n private alertManager: AlertManager;\n private replayManager: ReplayManager;\n private undoRedoManager: UndoRedoManager;\n private autoSaveTimer: ReturnType<typeof setTimeout> | null = null;\n private autoSaveDelay = 0; // 0 = disabled\n private autoSaveKey: string | null = null;\n private animator: Animator;\n private crosshairTooltip: CrosshairTooltip;\n private interactionManager: InteractionManager;\n private crosshairHandler: CrosshairHandler;\n private chartRenderer: ChartRendererInterface;\n private gridRenderer: GridRenderer;\n private priceAxis: PriceAxis;\n private timeAxis: TimeAxis;\n private options: ChartOptions;\n private features: Required<FeaturesConfig>;\n private marketConfig: MarketConfig | null = null;\n private container: HTMLElement;\n private currentPriceLine: import('@tradecanvas/core').CurrentPriceLine;\n\n constructor(container: HTMLElement, options: ChartOptions) {\n this.container = container;\n this.options = options;\n\n // Resolve feature flags (all default to true)\n const f = options.features ?? {};\n this.features = {\n drawings: f.drawings ?? true,\n drawingTools: f.drawingTools ?? [],\n drawingMagnet: f.drawingMagnet ?? true,\n drawingUndoRedo: f.drawingUndoRedo ?? true,\n trading: f.trading ?? true,\n tradingContextMenu: f.tradingContextMenu ?? true,\n indicators: f.indicators ?? true,\n indicatorIds: f.indicatorIds ?? [],\n panning: f.panning ?? true,\n zooming: f.zooming ?? true,\n crosshair: f.crosshair ?? true,\n keyboard: f.keyboard ?? true,\n priceAxis: f.priceAxis ?? true,\n timeAxis: f.timeAxis ?? true,\n grid: f.grid ?? (options.grid?.visible ?? true),\n legend: f.legend ?? true,\n volume: f.volume ?? true,\n watermark: f.watermark ?? true,\n saveLoad: f.saveLoad ?? true,\n screenshot: f.screenshot ?? true,\n alerts: f.alerts ?? true,\n replay: f.replay ?? true,\n sessionBreaks: f.sessionBreaks ?? true,\n barCountdown: f.barCountdown ?? true,\n compareSymbols: f.compareSymbols ?? true,\n dataExport: f.dataExport ?? true,\n logScale: f.logScale ?? true,\n timeframes: f.timeframes ?? [],\n defaultTimeframeFavorites: f.defaultTimeframeFavorites ?? [],\n };\n\n container.style.position = 'relative';\n container.style.overflow = 'hidden';\n container.tabIndex = 0; // Allow keyboard events\n container.style.outline = 'none';\n\n // Initialize managers\n this.dataManager = new DataManager();\n this.themeManager = new ThemeManager(options.theme);\n this.layoutManager = new LayoutManager();\n this.indicatorEngine = new IndicatorEngine();\n this.pluginManager = new PluginManager(this.indicatorEngine);\n this.eventBus = new EventBus();\n\n registerBuiltInIndicators(this.indicatorEngine);\n\n // Drawing tools\n this.drawingManager = new DrawingManager();\n registerBuiltInDrawingTools(this.drawingManager);\n this.drawingRenderer = new DrawingRenderer(this.drawingManager);\n this.drawingManager.setRequestRender(() => {\n // Sync entire render context so drawings render with same viewport as candles\n this.syncRenderContext();\n this.engine.requestRender(LayerType.Overlay);\n this.scheduleAutoSave();\n });\n this.drawingManager.setEventCallback((event, data) => {\n this.eventBus.emit(event as ChartEventType, data);\n });\n // Undo/redo\n this.undoRedoManager = new UndoRedoManager();\n this.drawingManager.setUndoRedoManager(this.undoRedoManager);\n this.drawingManager.setDataGetter(() => this.dataManager.getData());\n this.drawingManager.setDisplayDataGetter(() => this.getDisplayData());\n // Magnet mode\n if (options.crosshair?.mode === 'magnet') {\n this.drawingManager.setMagnetMode('magnet');\n }\n\n // Trading\n this.tradingManager = new TradingManager();\n this.tradingRenderer = new TradingRenderer(this.tradingManager);\n this.tradingManager.setContainer(container);\n this.tradingManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\n this.tradingManager.setEventCallback((event, data) => {\n this.eventBus.emit(event as ChartEventType, data);\n });\n\n // Rendering\n this.engine = new RenderEngine(container);\n const size = this.engine.dprManager.getContainerSize();\n this.viewport = new Viewport(\n size.width,\n size.height,\n options.minBarSpacing ?? 2,\n options.maxBarSpacing ?? 30,\n options.rightMargin ?? 5,\n );\n this.layoutManager.resize(size.width, size.height);\n\n // Sync viewport + layout when the container resizes. Without this hook\n // the chart's viewport keeps its construction-time chartRect forever\n // (which is wrong if the container started at 0 or got resized since),\n // and `scrollToEnd` / clampOffset compute against stale dimensions —\n // chart sticks at the wrong offset and the user can't scroll to the\n // latest bar.\n this.engine.onContainerResize = (newSize) => {\n if (newSize.width <= 0 || newSize.height <= 0) return;\n const wasAtEnd = this.viewport.isAtEnd();\n this.viewport.resize(newSize.width, newSize.height);\n this.layoutManager.resize(newSize.width, newSize.height);\n // wasAtEnd carries the user's intent: if they were tracking the live\n // edge before the resize, keep them there afterwards. Otherwise leave\n // their scroll position alone.\n this.updateViewportAndRender(wasAtEnd);\n };\n\n // Chart renderer\n this.chartRenderer = this.createChartRenderer(options.chartType);\n this.gridRenderer = new GridRenderer();\n if (options.grid?.visible === false) this.gridRenderer.setVisible(false);\n this.priceAxis = new PriceAxis();\n this.timeAxis = new TimeAxis();\n\n // Crosshair\n this.crosshairHandler = new CrosshairHandler();\n if (options.crosshair?.mode) {\n this.crosshairHandler.setMode(options.crosshair.mode);\n }\n // Crosshair callback — fired via microtask AFTER render, only when bar changes.\n // No DOM writes, no layout reads, no extra render requests.\n this.crosshairHandler.setCallback((barIndex, point) => {\n if (barIndex !== null && point) {\n const data = this.dataManager.getData();\n const bar = barIndex < data.length ? data[barIndex] : undefined;\n\n // Update legend (canvas-rendered, will show on next UI paint)\n this.chartLegend.setHoverBar(bar ?? null);\n\n // Update tooltip (DOM, lightweight update only when bar changes)\n if (bar) {\n this.crosshairTooltip.show(point, bar, this.themeManager.getTheme(), this.cachedContainerSize());\n }\n\n // Emit for external consumers\n this.eventBus.emit('crosshairMove', { point, bar, barIndex });\n } else {\n this.crosshairTooltip.hide();\n this.chartLegend.setHoverBar(null);\n }\n });\n\n // Chart legend (OHLCV overlay)\n this.chartLegend = new ChartLegend();\n this.chartLegend.setChartType(options.chartType);\n\n // Watermark + Volume\n this.watermark = new Watermark();\n if (options.watermark) this.watermark.setConfig(options.watermark);\n this.volumeRenderer = new VolumeRenderer();\n\n // Bar countdown timer\n this.barCountdown = new BarCountdown();\n this.sessionBreaks = new SessionBreaks();\n this.compareRenderer = new CompareRenderer();\n\n // Apply session break config from options\n if (options.sessionBreaks) {\n this.sessionBreaks.setConfig({\n visible: options.sessionBreaks.visible ?? true,\n color: options.sessionBreaks.color,\n lineStyle: options.sessionBreaks.lineStyle,\n lineWidth: options.sessionBreaks.lineWidth,\n });\n } else if (options.features?.sessionBreaks !== false) {\n this.sessionBreaks.setVisible(true);\n }\n\n // Apply log scale from options\n if (options.logScale) {\n this.viewport.setLogScale(true);\n }\n\n // Animation\n this.animator = new Animator();\n\n // Crosshair tooltip (DOM)\n this.crosshairTooltip = new CrosshairTooltip();\n this.crosshairTooltip.create(container);\n\n // Keyboard navigation\n void new KeyboardHandler({\n scrollBars: (count) => {\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\n this.viewport.scrollBy(count * barUnit);\n this.updateViewportAndRender();\n },\n zoom: (delta) => {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(delta, chartWidth / 2);\n this.updateViewportAndRender();\n },\n goToStart: () => {\n this.viewport.scrollBy(-Infinity);\n this.updateViewportAndRender();\n },\n goToEnd: () => {\n this.viewport.scrollToEnd();\n this.updateViewportAndRender();\n },\n fitContent: () => this.fitContent(),\n });\n\n // Current price line (standalone, works without StreamManager)\n this.currentPriceLine = new CurrentPriceLine();\n\n // Alerts\n this.alertManager = new AlertManager();\n this.alertManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\n this.alertManager.on('triggered', (alert) => {\n this.eventBus.emit('dataUpdate', { alert: 'triggered', alertId: alert.id, price: alert.price, message: alert.message });\n });\n\n // Replay\n this.replayManager = new ReplayManager();\n\n // Interaction\n this.interactionManager = new InteractionManager(container);\n if (this.features.panning) {\n this.interactionManager.setPanHandler(\n new PanHandler((deltaX) => {\n this.viewport.scrollBy(deltaX);\n this.updateViewportAndRender();\n }),\n );\n }\n if (this.features.zooming) {\n this.interactionManager.setZoomHandler(\n new ZoomHandler((delta, centerX) => {\n this.viewport.zoom(delta, centerX);\n this.updateViewportAndRender();\n }),\n );\n }\n if (this.features.crosshair) {\n this.interactionManager.setCrosshairHandler(this.crosshairHandler);\n }\n if (this.features.drawings) {\n this.interactionManager.setDrawingManager(\n this.drawingManager,\n () => this.viewport.getState(),\n );\n }\n if (this.features.trading) {\n this.interactionManager.setTradingManager(\n this.tradingManager,\n () => this.viewport.getState(),\n );\n }\n this.interactionManager.setOverlayDirtyCallback(() => {\n this.engine.requestRender(LayerType.Overlay);\n // Also refresh UI layer for panel crosshair value labels\n if (this.layoutManager.getPanels().length > 0) {\n this.engine.requestRender(LayerType.UI);\n }\n });\n this.interactionManager.attach();\n\n // Set render context\n this.syncRenderContext();\n this.engine.start();\n }\n\n // --- Data ---\n\n setData(data: DataSeries): void {\n this.dataManager.setData(data);\n this.crosshairHandler.setData(this.dataManager.getData());\n this.displayDataCache = null;\n this.sessionBreaks.invalidateCache();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n // Auto-set current price line from last bar's close\n if (data.length > 0) {\n this.currentPriceLine.setPrice(data[data.length - 1].close);\n }\n this.updateViewportAndRender(true);\n this.eventBus.emit('dataUpdate', { length: data.length });\n }\n\n appendBar(bar: OHLCBar): void {\n this.dataManager.appendBar(bar);\n this.crosshairHandler.setData(this.dataManager.getData());\n this.displayDataCache = null;\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.updateViewportAndRender();\n }\n\n updateLastBar(bar: OHLCBar): void {\n this.dataManager.updateLastBar(bar);\n this.currentPriceLine.setPrice(bar.close);\n // For non-transform chart types, the displayDataCache still points to the\n // same raw array (mutated in place), so no need to invalidate.\n // Only invalidate for transform types that produce derived arrays.\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\n && this.options.chartType !== 'hollowCandle') {\n this.displayDataCache = null;\n }\n this.scheduleRender();\n }\n\n /** Merge a price tick into the current last bar (convenience for live feeds) */\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\n this.dataManager.updateLastBarFromTick(tick);\n this.currentPriceLine.setPrice(tick.price);\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\n && this.options.chartType !== 'hollowCandle') {\n this.displayDataCache = null;\n }\n this.scheduleRender();\n }\n\n // --- Chart type ---\n\n setChartType(type: ChartType): void {\n this.options.chartType = type;\n this.chartRenderer = this.createChartRenderer(type);\n this.chartLegend.setChartType(type);\n this.displayDataCache = null;\n this.updateViewportAndRender(true);\n }\n\n // --- Indicators ---\n\n addIndicator(id: string, params: Record<string, number | string | boolean> = {}, position: PanelPosition = 'bottom'): string | null {\n if (!this.features.indicators) return null;\n if (this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(id)) return null;\n const instanceId = this.indicatorEngine.addIndicator(id, params, this.dataManager.getData());\n const descriptor = this.indicatorEngine.getAvailableIndicators().find((d) => d.id === id);\n if (descriptor?.placement === 'panel') {\n this.layoutManager.addPanel(instanceId, position);\n }\n this.eventBus.emit('indicatorAdd', { instanceId, id });\n this.engine.requestRender();\n return instanceId;\n }\n\n updateIndicator(instanceId: string, params: Record<string, number | string | boolean>): void {\n this.indicatorEngine.updateIndicator(instanceId, params, this.dataManager.getData());\n this.engine.requestRender();\n }\n\n removeIndicator(instanceId: string): void {\n this.indicatorEngine.removeIndicator(instanceId);\n this.layoutManager.removePanel(instanceId);\n this.eventBus.emit('indicatorRemove', { instanceId });\n this.engine.requestRender();\n }\n\n getIndicatorOutput(instanceId: string): IndicatorOutput | null {\n return this.indicatorEngine.getOutput(instanceId);\n }\n\n registerIndicator(plugin: IndicatorPlugin): void {\n this.pluginManager.registerIndicator(plugin);\n }\n\n static indicators(): IndicatorDescriptor[] {\n const engine = new IndicatorEngine();\n registerBuiltInIndicators(engine);\n return engine.getAvailableIndicators();\n }\n\n // --- Panel layout ---\n\n setPanelPosition(instanceId: string, position: PanelPosition): void {\n this.layoutManager.setPanelPosition(instanceId, position);\n this.engine.requestRender();\n }\n\n setPanelSize(instanceId: string, size: number): void {\n this.layoutManager.setPanelSize(instanceId, size);\n this.engine.requestRender();\n }\n\n // --- Drawing tools ---\n\n setDrawingTool(type: DrawingToolType | null): void {\n if (!this.features.drawings) return;\n // If whitelist is set, check it\n if (type && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(type)) return;\n this.drawingManager.setActiveTool(type);\n }\n\n getDrawingTool(): DrawingToolType | null {\n return this.drawingManager.getActiveTool();\n }\n\n setDrawingStyle(style: Partial<DrawingStyle>): void {\n this.drawingManager.setStyle(style);\n }\n\n getDrawings(): DrawingState[] {\n return this.drawingManager.getDrawings();\n }\n\n setDrawings(drawings: DrawingState[]): void {\n this.drawingManager.setDrawings(drawings);\n }\n\n removeDrawing(id: string): void {\n this.drawingManager.removeDrawing(id);\n }\n\n clearDrawings(): void {\n this.drawingManager.clearDrawings();\n }\n\n registerDrawingTool(plugin: DrawingPlugin): void {\n this.drawingManager.register(plugin);\n }\n\n // --- Undo/Redo ---\n\n undo(): boolean {\n if (!this.features.drawingUndoRedo) return false;\n return this.drawingManager.undo();\n }\n\n redo(): boolean {\n if (!this.features.drawingUndoRedo) return false;\n return this.drawingManager.redo();\n }\n\n getUndoRedoState(): { canUndo: boolean; canRedo: boolean } {\n return this.undoRedoManager.getState();\n }\n\n // --- Drawing magnet ---\n\n setDrawingMagnet(enabled: boolean): void {\n this.drawingManager.setMagnetMode(enabled ? 'magnet' : 'none');\n }\n\n getDrawingMagnet(): boolean {\n return this.drawingManager.getMagnetMode() === 'magnet';\n }\n\n // --- Bulk drawing operations ---\n\n lockAllDrawings(): void {\n this.drawingManager.lockAllDrawings();\n }\n\n unlockAllDrawings(): void {\n this.drawingManager.unlockAllDrawings();\n }\n\n hideAllDrawings(): void {\n this.drawingManager.hideAllDrawings();\n }\n\n showAllDrawings(): void {\n this.drawingManager.showAllDrawings();\n }\n\n // --- Drawing duplication ---\n\n duplicateDrawing(id?: string): string | null {\n const targetId = id ?? this.drawingManager.getSelectedDrawingId();\n if (!targetId) return null;\n return this.drawingManager.duplicateDrawing(targetId);\n }\n\n // --- Data export ---\n\n exportVisibleData(format: 'csv' | 'json' = 'csv', filename?: string): void {\n const vp = this.viewport.getState();\n const data = this.dataManager.getData();\n const from = Math.max(0, vp.visibleRange.from);\n const to = Math.min(data.length - 1, vp.visibleRange.to);\n const slice = data.slice(from, to + 1);\n\n if (format === 'json') {\n const content = DataExporter.toJSON(slice);\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\n } else {\n const content = DataExporter.toCSV(slice);\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\n }\n }\n\n exportAllData(format: 'csv' | 'json' = 'csv', filename?: string): void {\n const data = this.dataManager.getData();\n if (format === 'json') {\n const content = DataExporter.toJSON(data);\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\n } else {\n const content = DataExporter.toCSV(data);\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\n }\n }\n\n // --- Auto-save ---\n\n setAutoSave(key: string, delayMs = 5000): void {\n this.autoSaveKey = key;\n this.autoSaveDelay = delayMs;\n }\n\n disableAutoSave(): void {\n this.autoSaveDelay = 0;\n this.autoSaveKey = null;\n if (this.autoSaveTimer) {\n clearTimeout(this.autoSaveTimer);\n this.autoSaveTimer = null;\n }\n }\n\n private scheduleAutoSave(): void {\n if (this.autoSaveDelay <= 0 || !this.autoSaveKey) return;\n if (this.autoSaveTimer) clearTimeout(this.autoSaveTimer);\n this.autoSaveTimer = setTimeout(() => {\n this.autoSaveTimer = null;\n if (this.autoSaveKey) {\n this.saveState(this.autoSaveKey);\n }\n }, this.autoSaveDelay);\n }\n\n // --- Indicator introspection ---\n\n getAvailableIndicators(): IndicatorDescriptor[] {\n return this.indicatorEngine.getAvailableIndicators();\n }\n\n getIndicatorInputs(id: string): { id: string; params: Record<string, unknown> } | null {\n const indicators = this.indicatorEngine.getAvailableIndicators();\n const desc = indicators.find(i => i.id === id);\n if (!desc) return null;\n return { id: desc.id, params: desc.defaultConfig };\n }\n\n /** Get all active indicator instances with their current params */\n getActiveIndicators(): { instanceId: string; id: string; params: Record<string, unknown>; descriptor: IndicatorDescriptor }[] {\n return this.indicatorEngine.getActiveIndicators();\n }\n\n /** Get current config for a specific indicator instance */\n getIndicatorConfig(instanceId: string): { id: string; params: Record<string, unknown> } | null {\n const config = this.indicatorEngine.getIndicatorConfig(instanceId);\n if (!config) return null;\n return { id: config.id, params: { ...config.params } };\n }\n\n /** Update indicator colors/line widths at runtime */\n updateIndicatorStyle(instanceId: string, style: { colors?: string[]; lineWidths?: number[]; opacity?: number }): void {\n this.indicatorEngine.updateIndicatorStyle(instanceId, style);\n this.engine.requestRender();\n }\n\n // --- Trading ---\n\n setOrders(orders: TradingOrder[]): void {\n if (!this.features.trading) return;\n this.tradingManager.setOrders(orders);\n }\n\n setPositions(positions: TradingPosition[]): void {\n if (!this.features.trading) return;\n this.tradingManager.setPositions(positions);\n }\n\n setDepthData(depth: DepthData | null): void {\n if (!this.features.trading) return;\n this.tradingManager.setDepthData(depth);\n }\n\n setCurrentPrice(price: number): void {\n this.tradingManager.setCurrentPrice(price);\n // Also update standalone price line (visible even without trading feature)\n this.currentPriceLine.setPrice(price);\n this.scheduleRender();\n if (this.features.alerts) this.alertManager.checkPrice(price);\n }\n\n setTradingConfig(config: Partial<TradingConfig>): void {\n if (!this.features.trading) return;\n this.tradingManager.setConfig(config);\n }\n\n // --- Real-time Streaming ---\n\n /**\n * Connect to a real-time data source.\n * Loads history, starts streaming, manages reconnection automatically.\n *\n * @example\n * import { BinanceAdapter } from '@tradecanvas/core';\n * chart.connect({\n * adapter: new BinanceAdapter(),\n * symbol: 'BTCUSDT',\n * timeframe: '1m',\n * });\n */\n async connect(config: StreamConfig): Promise<void> {\n this.disconnectStream();\n\n this.streamManager = new StreamManager();\n\n this.streamManager.on('snapshot', (bars) => {\n this.setData(bars);\n });\n\n this.streamManager.on('barClose', (bar) => {\n this.dataManager.appendBar(bar);\n this.crosshairHandler.setData(this.dataManager.getData());\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.updateViewportAndRender();\n });\n\n this.streamManager.on('barUpdate', (bar) => {\n this.dataManager.updateLastBar(bar);\n this.currentPriceLine.setPrice(bar.close);\n this.scheduleRender();\n });\n\n this.streamManager.on('priceChange', ({ price }) => {\n this.tradingManager.setCurrentPrice(price);\n this.currentPriceLine.setPrice(price);\n this.engine.requestRender(LayerType.Overlay);\n this.engine.requestRender(LayerType.UI);\n });\n\n this.streamManager.on('connectionChange', (info) => {\n this.eventBus.emit('dataUpdate', { connection: info });\n });\n\n this.streamManager.on('error', (err) => {\n this.eventBus.emit('dataUpdate', { error: err.message });\n });\n\n this.autoScrollOnNewBar = config.autoScroll !== false;\n\n await this.streamManager.connect(config);\n\n // Set up bar countdown timer based on timeframe\n const tfMs = this.timeframeToMs(config.timeframe);\n this.barCountdown.setTimeframeMs(tfMs);\n\n // Start countdown refresh interval\n if (this.countdownInterval) clearInterval(this.countdownInterval);\n this.countdownInterval = setInterval(() => {\n if (this.barCountdown.isVisible()) {\n this.engine.requestRender(LayerType.UI);\n }\n }, 1000);\n }\n\n /**\n * Switch symbol or timeframe on an active stream without full reconnect.\n */\n async switchStream(symbol: string, timeframe: TimeFrame): Promise<void> {\n if (!this.streamManager) return;\n await this.streamManager.switchTo(symbol, timeframe);\n }\n\n /**\n * Disconnect the real-time stream.\n */\n disconnectStream(): void {\n if (this.streamManager) {\n this.streamManager.dispose();\n this.streamManager = null;\n }\n }\n\n setBarCountdownVisible(visible: boolean): void {\n this.barCountdown.setVisible(visible);\n this.engine.requestRender(LayerType.UI);\n }\n\n setSessionBreaksVisible(visible: boolean): void {\n this.sessionBreaks.setVisible(visible);\n this.engine.requestRender(LayerType.Background);\n }\n\n // --- Compare symbols ---\n\n addCompareSymbol(id: string, label: string, data: DataSeries, color: string): void {\n this.compareRenderer.addSymbol({ id, label, data, color, visible: true });\n this.engine.requestRender(LayerType.Main);\n }\n\n removeCompareSymbol(id: string): void {\n this.compareRenderer.removeSymbol(id);\n this.engine.requestRender(LayerType.Main);\n }\n\n updateCompareData(id: string, data: DataSeries): void {\n this.compareRenderer.setSymbolData(id, data);\n this.engine.requestRender(LayerType.Main);\n }\n\n setCompareMode(mode: 'percent' | 'absolute'): void {\n this.compareRenderer.setMode(mode);\n this.engine.requestRender(LayerType.Main);\n }\n\n clearCompareSymbols(): void {\n this.compareRenderer.clear();\n this.engine.requestRender(LayerType.Main);\n }\n\n // --- Log scale ---\n\n setLogScale(enabled: boolean): void {\n this.viewport.setLogScale(enabled);\n this.updateViewportAndRender();\n }\n\n isLogScale(): boolean {\n return this.viewport.isLogScale();\n }\n\n setSessionBreaksConfig(config: { color?: string; lineStyle?: 'solid' | 'dashed' | 'dotted'; lineWidth?: number }): void {\n this.sessionBreaks.setConfig(config);\n this.engine.requestRender(LayerType.Background);\n }\n\n getConnectionState(): ConnectionState {\n return this.streamManager?.getConnectionState() ?? 'disconnected';\n }\n\n getConnectionInfo(): ConnectionInfo {\n return this.streamManager?.getConnectionInfo() ?? { state: 'disconnected' };\n }\n\n setAutoScroll(enabled: boolean): void {\n this.autoScrollOnNewBar = enabled;\n }\n\n // --- Viewport ---\n\n scrollTo(timestamp: number): void {\n const data = this.dataManager.getData();\n for (let i = 0; i < data.length; i++) {\n if (data[i].time >= timestamp) {\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\n this.viewport.scrollBy(i * barUnit - this.viewport.getState().offset);\n this.updateViewportAndRender();\n return;\n }\n }\n }\n\n scrollToEnd(): void {\n this.viewport.scrollToEnd();\n this.updateViewportAndRender();\n }\n\n setVisibleRange(fromTimestamp: number, toTimestamp: number): void {\n const data = this.dataManager.getData();\n let fromIdx = 0;\n let toIdx = data.length - 1;\n for (let i = 0; i < data.length; i++) {\n if (data[i].time >= fromTimestamp) { fromIdx = i; break; }\n }\n for (let i = data.length - 1; i >= 0; i--) {\n if (data[i].time <= toTimestamp) { toIdx = i; break; }\n }\n const barCount = toIdx - fromIdx + 1;\n if (barCount > 0) {\n const chartWidth = this.viewport.getState().chartRect.width;\n const targetBarUnit = chartWidth / barCount;\n const newBarWidth = Math.max(2, targetBarUnit - this.viewport.getState().barSpacing);\n this.viewport.zoom(\n (newBarWidth - this.viewport.getState().barWidth) / this.viewport.getState().barWidth,\n chartWidth / 2,\n );\n }\n this.updateViewportAndRender();\n }\n\n zoomIn(): void {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(0.2, chartWidth / 2);\n this.updateViewportAndRender();\n }\n\n zoomOut(): void {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(-0.2, chartWidth / 2);\n this.updateViewportAndRender();\n }\n\n fitContent(): void {\n const data = this.dataManager.getData();\n if (data.length === 0) return;\n this.setVisibleRange(data[0].time, data[data.length - 1].time);\n }\n\n // --- Events ---\n\n on(type: ChartEventType, handler: (event: ChartEvent) => void): void {\n this.eventBus.on(type, handler);\n }\n\n off(type: ChartEventType, handler: (event: ChartEvent) => void): void {\n this.eventBus.off(type, handler);\n }\n\n enableTauriBridge(options?: Partial<TauriBridgeOptions>): void {\n this.eventBus.enableTauriBridge({ enabled: true, ...options });\n }\n\n disableTauriBridge(): void {\n this.eventBus.disableTauriBridge();\n }\n\n // --- Theme ---\n\n setTheme(themeOrName: ThemeName | Theme): void {\n this.themeManager.setTheme(themeOrName);\n this.syncRenderContext();\n this.container.style.backgroundColor = this.themeManager.getTheme().background;\n this.engine.requestRender();\n this.eventBus.emit('themeChange', { theme: themeOrName });\n }\n\n getTheme(): Theme {\n return this.themeManager.getTheme();\n }\n\n // --- Watermark ---\n\n setWatermark(text: string, opts?: { color?: string; fontSize?: number }): void {\n this.watermark.setConfig({ text, ...opts });\n this.engine.requestRender(LayerType.Background);\n }\n\n // --- Auto Scale ---\n\n setAutoScale(enabled: boolean): void {\n this.options.autoScale = enabled;\n this.updateViewportAndRender();\n }\n\n isAutoScale(): boolean {\n return this.options.autoScale !== false;\n }\n\n // --- Crosshair ---\n\n setCrosshairMode(mode: 'normal' | 'magnet' | 'hidden'): void {\n this.crosshairHandler.setMode(mode);\n this.engine.requestRender(LayerType.Overlay);\n }\n\n getCrosshairMode(): string {\n return this.crosshairHandler.getMode();\n }\n\n // --- Grid ---\n\n setGridVisible(visible: boolean): void {\n this.gridRenderer.setVisible(visible);\n this.engine.requestRender(LayerType.Background);\n }\n\n isGridVisible(): boolean {\n return this.gridRenderer.isVisible();\n }\n\n // --- Volume ---\n\n setVolumeVisible(visible: boolean): void {\n this.volumeRenderer.setVisible(visible);\n this.engine.requestRender(LayerType.Main);\n }\n\n // --- Tooltip ---\n\n setTooltipVisible(visible: boolean): void {\n if (!visible) this.crosshairTooltip.hide();\n }\n\n // --- Legend ---\n\n setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void {\n this.chartLegend.setConfig(config);\n this.engine.requestRender(LayerType.UI);\n }\n\n setSymbolName(symbol: string): void {\n this.chartLegend.setSymbol(symbol);\n this.engine.requestRender(LayerType.UI);\n }\n\n // --- Screenshot ---\n\n screenshot(filename?: string): void {\n if (!this.features.screenshot) return;\n Screenshot.download(this.container, filename, this.themeManager.getTheme().background);\n }\n\n screenshotDataURL(): string | null {\n if (!this.features.screenshot) return null;\n return Screenshot.toDataURL(this.container, this.themeManager.getTheme().background);\n }\n\n async screenshotBlob(): Promise<Blob | null> {\n if (!this.features.screenshot) return null;\n return Screenshot.toBlob(this.container, this.themeManager.getTheme().background);\n }\n\n // --- Alerts ---\n\n addAlert(price: number, condition: import('@tradecanvas/core').AlertCondition = 'crossing', message?: string): string | null {\n if (!this.features.alerts) return null;\n const id = this.alertManager.addAlert(price, condition, message);\n this.scheduleAutoSave();\n return id;\n }\n\n removeAlert(id: string): void {\n this.alertManager.removeAlert(id);\n this.scheduleAutoSave();\n }\n\n getAlerts(): import('@tradecanvas/core').PriceAlert[] {\n return this.alertManager.getAlerts();\n }\n\n clearAlerts(): void {\n this.alertManager.clearAlerts();\n this.scheduleAutoSave();\n }\n\n saveAlerts(key: string): void {\n this.alertManager.saveToStorage(key);\n }\n\n loadAlerts(key: string): void {\n this.alertManager.loadFromStorage(key);\n this.engine.requestRender(LayerType.Overlay);\n }\n\n // --- Replay ---\n\n replay(config?: Partial<import('@tradecanvas/core').ReplayConfig>): void {\n if (!this.features.replay) return;\n const data = this.dataManager.getData();\n this.replayManager.load(data);\n this.replayManager.on('bar', ({ bar: _bar, index }) => {\n const slice = data.slice(0, index + 1);\n this.dataManager.setData(slice);\n this.crosshairHandler.setData(slice);\n this.indicatorEngine.recalculateAll(slice);\n this.updateViewportAndRender();\n });\n this.replayManager.play(config);\n }\n\n replayPause(): void { this.replayManager.pause(); }\n replayResume(): void { this.replayManager.resume(); }\n replayStop(): void { this.replayManager.stop(); }\n replaySeek(index: number): void { this.replayManager.seekTo(index); }\n setReplaySpeed(speed: number): void { this.replayManager.setSpeed(speed); }\n getReplayState(): 'playing' | 'paused' | 'stopped' { return this.replayManager.getState(); }\n getReplayProgress(): { current: number; total: number; percent: number } { return this.replayManager.getProgress(); }\n\n // --- Save / Load ---\n\n saveState(key?: string): string | null {\n if (!this.features.saveLoad) return null;\n const snapshot = ChartStateManager.capture(\n {\n getDrawings: () => this.getDrawings(),\n getTheme: () => this.getTheme(),\n getAlerts: () => this.getAlerts(),\n },\n { chartType: this.options.chartType },\n );\n const json = ChartStateManager.serialize(snapshot);\n if (key) ChartStateManager.saveToStorage(key, snapshot);\n return json;\n }\n\n loadState(json: string): void {\n if (!this.features.saveLoad) return;\n const snapshot = ChartStateManager.deserialize(json);\n if (snapshot.chartType) this.setChartType(snapshot.chartType);\n if (snapshot.drawings) this.setDrawings(snapshot.drawings);\n if (snapshot.theme) this.setTheme(snapshot.theme as any);\n if (snapshot.alerts) {\n this.clearAlerts();\n for (const a of snapshot.alerts) {\n this.addAlert(a.price, a.condition, a.message);\n }\n }\n }\n\n loadStateFromStorage(key: string): boolean {\n if (!this.features.saveLoad) return false;\n const snapshot = ChartStateManager.loadFromStorage(key);\n if (!snapshot) return false;\n this.loadState(ChartStateManager.serialize(snapshot));\n return true;\n }\n\n downloadState(filename?: string): void {\n if (!this.features.saveLoad) return;\n const snapshot = ChartStateManager.capture(\n { getDrawings: () => this.getDrawings(), getTheme: () => this.getTheme(), getAlerts: () => this.getAlerts() },\n { chartType: this.options.chartType },\n );\n ChartStateManager.downloadFile(snapshot, filename);\n }\n\n async loadStateFromFile(): Promise<void> {\n if (!this.features.saveLoad) return;\n const snapshot = await ChartStateManager.loadFromFile();\n this.loadState(ChartStateManager.serialize(snapshot));\n }\n\n // --- Locale ---\n\n setLocale(locale: Locale): void {\n setGlobalLocale(locale);\n this.engine.requestRender();\n }\n\n // --- Market ---\n\n setMarket(config: MarketConfig): void {\n this.marketConfig = config;\n\n // Apply market color scheme to theme\n if (config.colorScheme) {\n const base = this.themeManager.getTheme();\n const marketTheme: Theme = {\n ...base,\n candleUp: config.colorScheme.up,\n candleDown: config.colorScheme.down,\n candleUpWick: config.colorScheme.up,\n candleDownWick: config.colorScheme.down,\n volumeUp: config.colorScheme.up.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.up}4D`,\n volumeDown: config.colorScheme.down.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.down}4D`,\n };\n this.themeManager.setTheme(marketTheme);\n }\n\n // Apply price precision to trading, alerts, and price line\n if (config.pricePrecision !== undefined) {\n this.tradingManager.setConfig({ pricePrecision: config.pricePrecision });\n this.alertManager.setPricePrecision(config.pricePrecision);\n this.streamManager?.priceLine.setPricePrecision(config.pricePrecision);\n this.crosshairHandler.setPricePrecision(config.pricePrecision);\n }\n\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n getMarket(): MarketConfig | null {\n return this.marketConfig;\n }\n\n setPriceLimits(referencePrice: number): void {\n if (!this.marketConfig) return;\n const limits = computePriceLimits(referencePrice, this.marketConfig);\n if (limits) {\n this.marketConfig.priceLimits = {\n ...this.marketConfig.priceLimits!,\n referencePrice,\n };\n }\n this.engine.requestRender();\n }\n\n // --- Features ---\n\n /** Get the resolved feature configuration */\n getFeatures(): Readonly<Required<FeaturesConfig>> {\n return this.features;\n }\n\n /** Update feature flags at runtime. Only provided keys are changed. */\n setFeatures(patch: Partial<FeaturesConfig>): void {\n Object.assign(this.features, patch);\n\n // Apply immediate side-effects\n if (patch.crosshair === false) {\n this.crosshairTooltip.hide();\n }\n if (patch.grid !== undefined) {\n this.engine.requestRender(LayerType.Background);\n }\n if (patch.volume !== undefined) {\n this.volumeRenderer.setVisible(patch.volume);\n this.engine.requestRender(LayerType.Main);\n }\n if (patch.drawings === false) {\n this.drawingManager.setActiveTool(null);\n }\n if (patch.trading === false) {\n this.tradingManager.setOrders([]);\n this.tradingManager.setPositions([]);\n }\n\n this.engine.requestRender();\n }\n\n // --- Lifecycle ---\n\n resize(): void {\n const size = this.engine.dprManager.readContainerSize();\n if (size.width <= 0 || size.height <= 0) return;\n this.containerSizeCache = size;\n this.containerSizeCacheTime = Date.now();\n // Resize canvas layers immediately (don't wait for DPRManager's debounced callback)\n const dpr = this.engine.dprManager.getDpr();\n this.engine.layerManager.resize(size, dpr);\n // Check if viewport was at the end before resize\n const wasAtEnd = this.viewport.isAtEnd();\n this.viewport.resize(size.width, size.height);\n this.layoutManager.resize(size.width, size.height);\n this.updateViewportAndRender(wasAtEnd);\n this.eventBus.emit('resize', size);\n }\n\n destroy(): void {\n if (this.countdownInterval) clearInterval(this.countdownInterval);\n this.disableAutoSave();\n this.disconnectStream();\n this.interactionManager.detach();\n this.tradingManager.destroy();\n this.animator.dispose();\n this.crosshairTooltip.destroy();\n this.replayManager.dispose();\n this.undoRedoManager.clear();\n this.engine.destroy();\n this.eventBus.destroy();\n this.container.innerHTML = '';\n }\n\n // --- Internal ---\n\n private createChartRenderer(type: ChartType): ChartRendererInterface {\n switch (type) {\n case 'candlestick': return new CandlestickRenderer();\n case 'heikinAshi': return new CandlestickRenderer(); // Same renderer, different data\n case 'line': return new LineRenderer();\n case 'area': return new AreaRenderer();\n case 'bar': return new BarRenderer();\n case 'hollowCandle': return new HollowCandleRenderer();\n case 'baseline': return new BaselineRenderer();\n case 'renko': return new RenkoRenderer();\n case 'lineBreak': return new CandlestickRenderer(); // Candle renderer on transformed data\n case 'kagi': return new KagiRenderer();\n case 'pointAndFigure': return new PointAndFigureRenderer();\n default: return new CandlestickRenderer();\n }\n }\n\n /** Cached display data. Invalidated when raw data or chart type changes. */\n private getDisplayData(): DataSeries {\n if (this.displayDataCache) return this.displayDataCache;\n\n const raw = this.dataManager.getData();\n if (raw.length === 0) return raw;\n\n let result: DataSeries;\n switch (this.options.chartType) {\n case 'heikinAshi': result = toHeikinAshi(raw); break;\n case 'renko': result = toRenko(raw, { brickSize: 0, useATR: true, atrPeriod: 14 }); break;\n case 'lineBreak': result = toLineBreak(raw, 3); break;\n case 'kagi': result = toKagi(raw, 4); break;\n case 'pointAndFigure': {\n const avgPrice = raw.reduce((s, b) => s + b.close, 0) / raw.length;\n result = toPointAndFigure(raw, avgPrice * 0.01, 3);\n break;\n }\n default: result = raw;\n }\n this.displayDataCache = result;\n return result;\n }\n\n /** Lightweight render for streaming updates. No layout resolve, no indicator recalc. */\n private scheduleRender(): void {\n if (this.renderScheduled) return;\n this.renderScheduled = true;\n requestAnimationFrame(() => {\n this.renderScheduled = false;\n const displayData = this.getDisplayData();\n this.viewport.updateData(displayData, this.options.autoScale !== false);\n this.syncRenderContext();\n this.engine.requestRender();\n });\n }\n\n /** Full update: resolve layout, update viewport, sync context, request render. */\n private updateViewportAndRender(scrollToEnd = false): void {\n // Invalidate layout cache\n this.resolvedLayoutCache = null;\n this.panelInfoCache = null;\n\n const resolved = this.getResolvedLayout();\n this.viewport.setChartRect(resolved.mainChartRect);\n\n const displayData = this.getDisplayData();\n this.viewport.updateData(displayData, this.options.autoScale !== false);\n\n // Scroll to end AFTER updateData so dataLength is current\n if (scrollToEnd) this.viewport.scrollToEnd();\n\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n private getResolvedLayout() {\n if (!this.resolvedLayoutCache) {\n this.resolvedLayoutCache = this.layoutManager.resolve();\n }\n return this.resolvedLayoutCache;\n }\n\n /** Cache container size for 500ms to avoid layout thrashing on rapid calls */\n private cachedContainerSize(): { width: number; height: number } {\n const now = Date.now();\n if (!this.containerSizeCache || now - this.containerSizeCacheTime > 500) {\n this.containerSizeCache = this.engine.dprManager.getContainerSize();\n this.containerSizeCacheTime = now;\n }\n return this.containerSizeCache;\n }\n\n private buildPanelRenderInfos(): import('@tradecanvas/core').PanelRenderInfo[] {\n if (this.panelInfoCache) return this.panelInfoCache;\n\n const resolved = this.getResolvedLayout();\n const mainVP = this.viewport.getState();\n\n const panels = resolved.panels.map((panel) => {\n const output = this.indicatorEngine.getOutput(panel.config.id);\n let min = 0, max = 100;\n\n if (output) {\n let vMin = Infinity, vMax = -Infinity;\n const { from, to } = mainVP.visibleRange;\n let idx = 0;\n for (const [, val] of output.values) {\n if (idx >= from && idx <= to) {\n for (const key in val) {\n const v = val[key];\n if (v !== undefined) {\n if (v < vMin) vMin = v;\n if (v > vMax) vMax = v;\n }\n }\n }\n idx++;\n }\n if (vMin !== Infinity) {\n const range = vMax - vMin || 1;\n min = vMin - range * 0.1;\n max = vMax + range * 0.1;\n }\n }\n\n // Inset the indicator drawing area below the panel header (title + divider)\n const PANEL_HEADER_HEIGHT = 20;\n const insetRect = {\n x: panel.rect.x,\n y: panel.rect.y + PANEL_HEADER_HEIGHT,\n width: panel.rect.width,\n height: Math.max(0, panel.rect.height - PANEL_HEADER_HEIGHT),\n };\n\n return {\n instanceId: panel.config.id,\n rect: panel.rect,\n viewport: {\n ...mainVP,\n chartRect: insetRect,\n priceRange: { min, max },\n },\n };\n });\n\n this.panelInfoCache = panels;\n return panels;\n }\n\n private syncRenderContext(): void {\n const resolved = this.getResolvedLayout();\n const panels = this.features.indicators ? this.buildPanelRenderInfos() : [];\n\n // Compute where the time axis should render: below main chart + all bottom panels\n const bottomPanelHeight = resolved.panels\n .filter(p => p.config.position === 'bottom')\n .reduce((sum, p) => sum + p.rect.height, 0);\n const timeAxisY = resolved.mainChartRect.y + resolved.mainChartRect.height + bottomPanelHeight;\n\n this.engine.setRenderContext({\n chartRenderer: this.chartRenderer,\n gridRenderer: this.features.grid ? this.gridRenderer : null,\n priceAxis: this.features.priceAxis ? this.priceAxis : null,\n timeAxis: this.features.timeAxis ? this.timeAxis : null,\n crosshairHandler: this.features.crosshair ? this.crosshairHandler : null,\n indicatorEngine: this.features.indicators ? this.indicatorEngine : null,\n drawingRenderer: this.features.drawings ? this.drawingRenderer : null,\n tradingRenderer: this.features.trading ? this.tradingRenderer : null,\n currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine,\n chartLegend: this.features.legend ? this.chartLegend : null,\n volumeRenderer: this.features.volume ? this.volumeRenderer : null,\n watermark: this.features.watermark ? this.watermark : null,\n barCountdown: this.barCountdown,\n sessionBreaks: this.sessionBreaks,\n compareRenderer: this.compareRenderer,\n panels,\n priceLimits: this.buildPriceLimits(),\n timeAxisY,\n viewport: this.viewport.getState(),\n theme: this.themeManager.getTheme(),\n data: this.getDisplayData(),\n });\n }\n\n private timeframeToMs(tf: string): number {\n const match = tf.match(/^(\\d+)([smhdwMy])$/);\n if (!match) return 0;\n const n = parseInt(match[1], 10);\n switch (match[2]) {\n case 's': return n * 1000;\n case 'm': return n * 60_000;\n case 'h': return n * 3_600_000;\n case 'd': return n * 86_400_000;\n case 'w': return n * 604_800_000;\n case 'M': return n * 2_592_000_000;\n default: return 0;\n }\n }\n\n private buildPriceLimits() {\n if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null;\n const limits = computePriceLimits(this.marketConfig.priceLimits.referencePrice, this.marketConfig);\n if (!limits) return null;\n return {\n ...limits,\n colors: this.marketConfig.colorScheme ? {\n ceiling: this.marketConfig.colorScheme.ceiling,\n floor: this.marketConfig.colorScheme.floor,\n reference: this.marketConfig.colorScheme.reference,\n } : undefined,\n };\n }\n}\n"],"mappings":"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"}