@tradecanvas/chart 0.4.0 → 0.6.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.
- package/README.md +120 -9
- package/dist/Chart-CrrTKx3r.js +1027 -0
- package/dist/Chart-CrrTKx3r.js.map +1 -0
- package/dist/Chart-DoR8L8Uk.cjs +2 -0
- package/dist/Chart-DoR8L8Uk.cjs.map +1 -0
- package/dist/Chart.d.ts +22 -8
- package/dist/Chart.d.ts.map +1 -1
- package/dist/charts/ChartTypeStrategy.d.ts +18 -0
- package/dist/charts/ChartTypeStrategy.d.ts.map +1 -0
- package/dist/charts/IndicatorPriceRange.d.ts +16 -0
- package/dist/charts/IndicatorPriceRange.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -1010
- package/dist/index.js.map +1 -1
- package/dist/state/AutoSaveScheduler.d.ts +26 -0
- package/dist/state/AutoSaveScheduler.d.ts.map +1 -0
- package/dist/widget/ChartWidget.d.ts +43 -0
- package/dist/widget/ChartWidget.d.ts.map +1 -0
- package/dist/widget/WidgetDrawingSidebar.d.ts +19 -0
- package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -0
- package/dist/widget/WidgetDropdown.d.ts +18 -0
- package/dist/widget/WidgetDropdown.d.ts.map +1 -0
- package/dist/widget/WidgetSettings.d.ts +25 -0
- package/dist/widget/WidgetSettings.d.ts.map +1 -0
- package/dist/widget/WidgetStatusBar.d.ts +15 -0
- package/dist/widget/WidgetStatusBar.d.ts.map +1 -0
- package/dist/widget/WidgetStyles.d.ts +9 -0
- package/dist/widget/WidgetStyles.d.ts.map +1 -0
- package/dist/widget/WidgetToolbar.d.ts +22 -0
- package/dist/widget/WidgetToolbar.d.ts.map +1 -0
- package/dist/widget/icons.d.ts +2 -0
- package/dist/widget/icons.d.ts.map +1 -0
- package/dist/widget/index.cjs +740 -0
- package/dist/widget/index.cjs.map +1 -0
- package/dist/widget/index.d.ts +3 -0
- package/dist/widget/index.d.ts.map +1 -0
- package/dist/widget/index.js +1058 -0
- package/dist/widget/index.js.map +1 -0
- package/dist/widget/types.d.ts +105 -0
- package/dist/widget/types.d.ts.map +1 -0
- package/dist/widget/widgetConfig.d.ts +16 -0
- package/dist/widget/widgetConfig.d.ts.map +1 -0
- package/package.json +14 -4
package/dist/Chart.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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';
|
|
1
|
+
import { ChartOptions, ChartType, OHLCBar, DataSeries, Theme, ThemeName, ChartEventType, ChartEvent, ChartEventMap, TauriBridgeOptions, IndicatorPlugin, IndicatorDescriptor, IndicatorOutput, DrawingToolType, DrawingState, DrawingStyle, DrawingPlugin, PanelPosition, TradingOrder, TradingPosition, DepthData, TradingConfig, MarketConfig, Locale, StreamConfig, ConnectionState, ConnectionInfo, TimeFrame, FeaturesConfig } from '@tradecanvas/commons';
|
|
2
2
|
export declare class Chart {
|
|
3
3
|
static version: string;
|
|
4
4
|
private engine;
|
|
@@ -31,9 +31,7 @@ export declare class Chart {
|
|
|
31
31
|
private alertManager;
|
|
32
32
|
private replayManager;
|
|
33
33
|
private undoRedoManager;
|
|
34
|
-
private
|
|
35
|
-
private autoSaveDelay;
|
|
36
|
-
private autoSaveKey;
|
|
34
|
+
private autoSaveScheduler;
|
|
37
35
|
private animator;
|
|
38
36
|
private crosshairTooltip;
|
|
39
37
|
private interactionManager;
|
|
@@ -50,9 +48,16 @@ export declare class Chart {
|
|
|
50
48
|
private numberLocale;
|
|
51
49
|
private keyboardHandler;
|
|
52
50
|
private onWindowKeyDown;
|
|
51
|
+
private currentSymbol;
|
|
53
52
|
constructor(container: HTMLElement, options: ChartOptions);
|
|
54
53
|
setData(data: DataSeries): void;
|
|
55
54
|
appendBar(bar: OHLCBar): void;
|
|
55
|
+
/**
|
|
56
|
+
* Append multiple bars at once (e.g., catch-up after reconnect).
|
|
57
|
+
* More efficient than calling appendBar() in a loop — recalculates
|
|
58
|
+
* indicators only once at the end.
|
|
59
|
+
*/
|
|
60
|
+
appendBars(bars: OHLCBar[]): void;
|
|
56
61
|
updateLastBar(bar: OHLCBar): void;
|
|
57
62
|
/** Merge a price tick into the current last bar (convenience for live feeds) */
|
|
58
63
|
updateLastBarFromTick(tick: {
|
|
@@ -121,7 +126,7 @@ export declare class Chart {
|
|
|
121
126
|
setOrders(orders: TradingOrder[]): void;
|
|
122
127
|
setPositions(positions: TradingPosition[]): void;
|
|
123
128
|
setDepthData(depth: DepthData | null): void;
|
|
124
|
-
setCurrentPrice(price: number): void;
|
|
129
|
+
setCurrentPrice(price: number, _pulseColor?: string): void;
|
|
125
130
|
setTradingConfig(config: Partial<TradingConfig>): void;
|
|
126
131
|
/**
|
|
127
132
|
* Connect to a real-time data source.
|
|
@@ -140,6 +145,11 @@ export declare class Chart {
|
|
|
140
145
|
* Switch symbol or timeframe on an active stream without full reconnect.
|
|
141
146
|
*/
|
|
142
147
|
switchStream(symbol: string, timeframe: TimeFrame): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Switch to a new timeframe. Requires an active stream connection.
|
|
150
|
+
* Internally calls switchStream with the current symbol.
|
|
151
|
+
*/
|
|
152
|
+
setTimeframe(timeframe: TimeFrame): Promise<void>;
|
|
143
153
|
/**
|
|
144
154
|
* Disconnect the real-time stream.
|
|
145
155
|
*/
|
|
@@ -167,8 +177,8 @@ export declare class Chart {
|
|
|
167
177
|
zoomIn(): void;
|
|
168
178
|
zoomOut(): void;
|
|
169
179
|
fitContent(): void;
|
|
170
|
-
on(type:
|
|
171
|
-
off(type:
|
|
180
|
+
on<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void;
|
|
181
|
+
off<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void;
|
|
172
182
|
enableTauriBridge(options?: Partial<TauriBridgeOptions>): void;
|
|
173
183
|
disableTauriBridge(): void;
|
|
174
184
|
setTheme(themeOrName: ThemeName | Theme): void;
|
|
@@ -187,6 +197,11 @@ export declare class Chart {
|
|
|
187
197
|
setTooltipVisible(visible: boolean): void;
|
|
188
198
|
setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void;
|
|
189
199
|
setSymbolName(symbol: string): void;
|
|
200
|
+
/**
|
|
201
|
+
* Set a status text displayed in the chart legend area (e.g., "LIVE . 8ms").
|
|
202
|
+
* Pass null to clear.
|
|
203
|
+
*/
|
|
204
|
+
setStatusText(text: string | null): void;
|
|
190
205
|
screenshot(filename?: string): void;
|
|
191
206
|
screenshotDataURL(): string | null;
|
|
192
207
|
screenshotBlob(): Promise<Blob | null>;
|
|
@@ -242,7 +257,6 @@ export declare class Chart {
|
|
|
242
257
|
private cachedContainerSize;
|
|
243
258
|
private buildPanelRenderInfos;
|
|
244
259
|
private syncRenderContext;
|
|
245
|
-
private timeframeToMs;
|
|
246
260
|
private buildPriceLimits;
|
|
247
261
|
}
|
|
248
262
|
//# sourceMappingURL=Chart.d.ts.map
|
package/dist/Chart.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../src/Chart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ChartType, DataSeries } from '@tradecanvas/commons';
|
|
2
|
+
import { ChartRendererInterface } from '@tradecanvas/core';
|
|
3
|
+
/**
|
|
4
|
+
* Pure mapping from `ChartType` to the renderer class that draws it. Several
|
|
5
|
+
* chart types reuse `CandlestickRenderer` against transformed data
|
|
6
|
+
* (heikinAshi, lineBreak, rangeBars).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createRendererFor(type: ChartType): ChartRendererInterface;
|
|
9
|
+
/**
|
|
10
|
+
* Transform raw OHLC bars into the display series for a given chart type.
|
|
11
|
+
* Returns the input unchanged for chart types that render raw OHLC directly.
|
|
12
|
+
*
|
|
13
|
+
* Centralized so adding a new chart type only requires editing one file.
|
|
14
|
+
*/
|
|
15
|
+
export declare function transformDisplayData(type: ChartType, raw: DataSeries): DataSeries;
|
|
16
|
+
/** Chart types that materially transform raw OHLC into a different series. */
|
|
17
|
+
export declare function isTransformedChartType(type: ChartType): boolean;
|
|
18
|
+
//# sourceMappingURL=ChartTypeStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartTypeStrategy.d.ts","sourceRoot":"","sources":["../../src/charts/ChartTypeStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAkBlE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,sBAAsB,CA0BzE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,GAAG,UAAU,CAuBjF;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAY/D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IndicatorOutput } from '@tradecanvas/commons';
|
|
2
|
+
export interface PriceRange {
|
|
3
|
+
min: number;
|
|
4
|
+
max: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Compute a padded {min, max} price range for an indicator panel from the
|
|
8
|
+
* visible slice of its output. Returns a sensible default range when the
|
|
9
|
+
* output is empty or has no values inside [from, to].
|
|
10
|
+
*
|
|
11
|
+
* Pure — no canvas, no viewport object, just the values map and bar bounds.
|
|
12
|
+
* Iterates the output's `values` map in insertion order; we treat its index
|
|
13
|
+
* (0…N-1) as the bar index, matching how the engine inserts values.
|
|
14
|
+
*/
|
|
15
|
+
export declare function computeIndicatorPriceRange(output: IndicatorOutput | null, from: number, to: number): PriceRange;
|
|
16
|
+
//# sourceMappingURL=IndicatorPriceRange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndicatorPriceRange.d.ts","sourceRoot":"","sources":["../../src/charts/IndicatorPriceRange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAKD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,eAAe,GAAG,IAAI,EAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,UAAU,CA0BZ"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +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;numberLocale;keyboardHandler=null;onWindowKeyDown=null;constructor(n,r){this.container=n,this.options=r,this.numberLocale=r.numberLocale??`en-US`;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.priceAxis.setLocale(this.numberLocale),this.timeAxis=new t.TimeAxis,this.crosshairHandler=new t.CrosshairHandler,this.crosshairHandler.setLocale(this.numberLocale),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),this.keyboardHandler=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.keyboardHandler.setEnabled(this.features.keyboard),this.onWindowKeyDown=e=>{if(!this.keyboardHandler)return;let t=document.activeElement;t&&t!==this.container&&!this.container.contains(t)||t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable)||this.keyboardHandler.handleKey(e)&&e.preventDefault()},window.addEventListener(`keydown`,this.onWindowKeyDown),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.indicatorEngine.recalculateAll(this.dataManager.getData()),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.indicatorEngine.recalculateAll(this.dataManager.getData()),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.updateViewportAndRender()):this.engine.requestRender(),this.eventBus.emit(`indicatorAdd`,{instanceId:r,id:e}),r}updateIndicator(e,t){this.indicatorEngine.updateIndicator(e,t,this.dataManager.getData()),this.engine.requestRender()}removeIndicator(e){let t=this.layoutManager.getPanels().some(t=>t.id===e);this.indicatorEngine.removeIndicator(e),this.layoutManager.removePanel(e),this.eventBus.emit(`indicatorRemove`,{instanceId:e}),t?this.updateViewportAndRender():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.indicatorEngine.recalculateAll(this.dataManager.getData()),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()}setNumberLocale(e){this.numberLocale=e,this.priceAxis.setLocale(e),this.crosshairHandler.setLocale(e),this.syncRenderContext(),this.engine.requestRender()}getNumberLocale(){return this.numberLocale}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([])),t.keyboard!==void 0&&this.keyboardHandler?.setEnabled(t.keyboard),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.onWindowKeyDown&&=(window.removeEventListener(`keydown`,this.onWindowKeyDown),null),this.keyboardHandler=null,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();if(this.viewport.updateData(n,this.options.autoScale!==!1),this.options.autoScale!==!1){let e=this.viewport.getState(),t=this.indicatorEngine.getOverlayPriceRange(e.visibleRange.from,Math.min(e.visibleRange.to,n.length-1));if(t){let n=e.priceRange,r=Math.min(n.min,t.min),i=Math.max(n.max,t.max);if(r<n.min||i>n.max){let e=i-r||1;this.viewport.setPriceRange(r-e*.02,i+e*.02)}}}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(),numberLocale:this.numberLocale})}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}},d=class extends t.BaseFinanceChart{options;constructor(e,t){super(e,t.theme),this.options=t,this.requestRender()}renderChart(e,n,r,i){(0,t.renderSparkline)(e,n,r,this.options,i)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}},f=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderDepthChart)(e,n,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},p=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderEquityCurve)(e,n,r,this.options,i,a)}update(e,t){this.options={...this.options,data:e},t!==void 0&&(this.options={...this.options,benchmark:t}),this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},m=class extends t.BaseFinanceChart{options;crosshair=null;cachedRects=[];currentData=[];lastLayoutWidth=0;lastLayoutHeight=0;handleClick=null;constructor(e,n){super(e,n.theme),this.options=n,this.currentData=n.data??[],n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),n.onCellClick&&(this.handleClick=e=>{let t=this.canvas.getBoundingClientRect(),n=e.clientX-t.left,r=e.clientY-t.top;this.onCanvasClick(n,r)},this.canvas.addEventListener(`click`,this.handleClick)),this.recomputeLayout(),this.requestRender()}recomputeLayout(){let e={x:0,y:0,width:this.width,height:this.height},n=this.options.cellPadding??2;this.lastLayoutWidth=this.width,this.lastLayoutHeight=this.height,this.options.weighted?this.cachedRects=(0,t.layoutSquarifiedTreemap)(this.currentData.map(e=>({id:e.id,weight:e.weight??(Math.abs(e.value)||1)})),e,n):this.cachedRects=(0,t.layoutUniformGrid)(this.currentData.map(e=>({id:e.id})),e,n)}onCanvasClick(e,t){if(this.options.onCellClick)for(let n of this.cachedRects){let r=n.rect;if(e>=r.x&&e<=r.x+r.width&&t>=r.y&&t<=r.y+r.height){let e=this.currentData.find(e=>e.id===n.id);e&&this.options.onCellClick(e);return}}}renderChart(e,n,r,i){(n!==this.lastLayoutWidth||r!==this.lastLayoutHeight)&&this.recomputeLayout();let a=this.crosshair?.getPosition()??null;(0,t.renderHeatmap)(e,n,r,this.currentData,this.cachedRects,this.options,i,a)}update(e){this.currentData=e,this.options={...this.options,data:e},this.recomputeLayout(),this.requestRender()}setOptions(e){this.options={...this.options,...e},e.data&&(this.currentData=e.data),this.recomputeLayout(),this.requestRender()}destroy(){this.crosshair?.destroy(),this.handleClick&&this.canvas.removeEventListener(`click`,this.handleClick),super.destroy()}},h=class extends t.BaseFinanceChart{options;crosshair=null;constructor(e,n){super(e,n.theme),this.options=n,n.crosshair!==!1&&(this.crosshair=new t.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,n,r,i){let a=this.crosshair?.getPosition()??null;(0,t.renderWaterfall)(e,n,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},g=500;function _(e){let t=1-e;return 1-t*t*t}var v=class extends t.BaseFinanceChart{options;currentValue;targetValue;animationStart=null;animationFrom=0;animationFrameId=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentValue=t.value,this.targetValue=t.value,this.requestRender()}renderChart(e,n,r,i){(0,t.renderGauge)(e,n,r,this.options,i,this.currentValue)}setValue(e){if(this.options.animate===!1){this.cancelAnimation(),this.currentValue=e,this.targetValue=e,this.options={...this.options,value:e},this.requestRender();return}this.targetValue=e,this.animationFrom=this.currentValue,this.animationStart=performance.now(),this.options={...this.options,value:e},this.startAnimationLoop()}setOptions(e){let t={...this.options,...e};if(e.value!==void 0&&e.value!==this.targetValue){this.options=t,this.setValue(e.value);return}this.options=t,this.requestRender()}startAnimationLoop(){if(this.animationFrameId!==null)return;let e=()=>{if(this.animationFrameId=null,this.animationStart===null)return;let t=this.options.animationDuration??g,n=performance.now()-this.animationStart,r=Math.min(1,n/Math.max(1,t)),i=_(r);this.currentValue=this.animationFrom+(this.targetValue-this.animationFrom)*i,this.requestRender(),r<1?this.animationFrameId=requestAnimationFrame(e):(this.currentValue=this.targetValue,this.animationStart=null)};this.animationFrameId=requestAnimationFrame(e)}cancelAnimation(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStart=null}destroy(){this.cancelAnimation(),super.destroy()}};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,exports.DepthChart=f,Object.defineProperty(exports,`DrawingBase`,{enumerable:!0,get:function(){return t.DrawingBase}}),Object.defineProperty(exports,`Easing`,{enumerable:!0,get:function(){return t.Easing}}),exports.EquityCurveChart=p,exports.GaugeChart=v,exports.HeatmapChart=m,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}}),exports.SparklineChart=d,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}}),exports.WaterfallChart=h,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}});
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./Chart-DoR8L8Uk.cjs`);let t=require(`@tradecanvas/commons`),n=require(`@tradecanvas/core`);var r=class extends n.BaseFinanceChart{options;constructor(e,t){super(e,t.theme),this.options=t,this.requestRender()}renderChart(e,t,r,i){(0,n.renderSparkline)(e,t,r,this.options,i)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}},i=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderDepthChart)(e,t,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},a=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderEquityCurve)(e,t,r,this.options,i,a)}update(e,t){this.options={...this.options,data:e},t!==void 0&&(this.options={...this.options,benchmark:t}),this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},o=class extends n.BaseFinanceChart{options;crosshair=null;cachedRects=[];currentData=[];lastLayoutWidth=0;lastLayoutHeight=0;handleClick=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentData=t.data??[],t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),t.onCellClick&&(this.handleClick=e=>{let t=this.canvas.getBoundingClientRect(),n=e.clientX-t.left,r=e.clientY-t.top;this.onCanvasClick(n,r)},this.canvas.addEventListener(`click`,this.handleClick)),this.recomputeLayout(),this.requestRender()}recomputeLayout(){let e={x:0,y:0,width:this.width,height:this.height},t=this.options.cellPadding??2;if(this.lastLayoutWidth=this.width,this.lastLayoutHeight=this.height,this.options.weighted){let r=this.currentData.map(e=>({id:e.id,weight:e.weight??(Math.abs(e.value)||1)}));this.cachedRects=(0,n.layoutSquarifiedTreemap)(r,e,t)}else this.cachedRects=(0,n.layoutUniformGrid)(this.currentData.map(e=>({id:e.id})),e,t)}onCanvasClick(e,t){if(this.options.onCellClick)for(let n of this.cachedRects){let r=n.rect;if(e>=r.x&&e<=r.x+r.width&&t>=r.y&&t<=r.y+r.height){let e=this.currentData.find(e=>e.id===n.id);e&&this.options.onCellClick(e);return}}}renderChart(e,t,r,i){(t!==this.lastLayoutWidth||r!==this.lastLayoutHeight)&&this.recomputeLayout();let a=this.crosshair?.getPosition()??null;(0,n.renderHeatmap)(e,t,r,this.currentData,this.cachedRects,this.options,i,a)}update(e){this.currentData=e,this.options={...this.options,data:e},this.recomputeLayout(),this.requestRender()}setOptions(e){this.options={...this.options,...e},e.data&&(this.currentData=e.data),this.recomputeLayout(),this.requestRender()}destroy(){this.crosshair?.destroy(),this.handleClick&&this.canvas.removeEventListener(`click`,this.handleClick),super.destroy()}},s=class extends n.BaseFinanceChart{options;crosshair=null;constructor(e,t){super(e,t.theme),this.options=t,t.crosshair!==!1&&(this.crosshair=new n.FinanceCrosshair(this.canvas,()=>this.requestRender())),this.requestRender()}renderChart(e,t,r,i){let a=this.crosshair?.getPosition()??null;(0,n.renderWaterfall)(e,t,r,this.options,i,a)}update(e){this.options={...this.options,data:e},this.requestRender()}setOptions(e){this.options={...this.options,...e},this.requestRender()}destroy(){this.crosshair?.destroy(),super.destroy()}},c=500;function l(e){let t=1-e;return 1-t*t*t}var u=class extends n.BaseFinanceChart{options;currentValue;targetValue;animationStart=null;animationFrom=0;animationFrameId=null;constructor(e,t){super(e,t.theme),this.options=t,this.currentValue=t.value,this.targetValue=t.value,this.requestRender()}renderChart(e,t,r,i){(0,n.renderGauge)(e,t,r,this.options,i,this.currentValue)}setValue(e){if(this.options.animate===!1){this.cancelAnimation(),this.currentValue=e,this.targetValue=e,this.options={...this.options,value:e},this.requestRender();return}this.targetValue=e,this.animationFrom=this.currentValue,this.animationStart=performance.now(),this.options={...this.options,value:e},this.startAnimationLoop()}setOptions(e){let t={...this.options,...e};if(e.value!==void 0&&e.value!==this.targetValue){this.options=t,this.setValue(e.value);return}this.options=t,this.requestRender()}startAnimationLoop(){if(this.animationFrameId!==null)return;let e=()=>{if(this.animationFrameId=null,this.animationStart===null)return;let t=this.options.animationDuration??c,n=performance.now()-this.animationStart,r=Math.min(1,n/Math.max(1,t)),i=l(r);this.currentValue=this.animationFrom+(this.targetValue-this.animationFrom)*i,this.requestRender(),r<1?this.animationFrameId=requestAnimationFrame(e):(this.currentValue=this.targetValue,this.animationStart=null)};this.animationFrameId=requestAnimationFrame(e)}cancelAnimation(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.animationStart=null}destroy(){this.cancelAnimation(),super.destroy()}};Object.defineProperty(exports,`AlertManager`,{enumerable:!0,get:function(){return n.AlertManager}}),Object.defineProperty(exports,`Animator`,{enumerable:!0,get:function(){return n.Animator}}),Object.defineProperty(exports,`BarCountdown`,{enumerable:!0,get:function(){return n.BarCountdown}}),Object.defineProperty(exports,`BinanceAdapter`,{enumerable:!0,get:function(){return n.BinanceAdapter}}),exports.Chart=e.t,Object.defineProperty(exports,`ChartLegend`,{enumerable:!0,get:function(){return n.ChartLegend}}),Object.defineProperty(exports,`ChartStateManager`,{enumerable:!0,get:function(){return n.ChartStateManager}}),Object.defineProperty(exports,`CompareRenderer`,{enumerable:!0,get:function(){return n.CompareRenderer}}),Object.defineProperty(exports,`CrosshairTooltip`,{enumerable:!0,get:function(){return n.CrosshairTooltip}}),Object.defineProperty(exports,`CurrentPriceLine`,{enumerable:!0,get:function(){return n.CurrentPriceLine}}),Object.defineProperty(exports,`DARK_TERMINAL`,{enumerable:!0,get:function(){return t.DARK_TERMINAL}}),Object.defineProperty(exports,`DARK_THEME`,{enumerable:!0,get:function(){return t.DARK_THEME}}),Object.defineProperty(exports,`DEFAULT_DRAWING_STYLE`,{enumerable:!0,get:function(){return t.DEFAULT_DRAWING_STYLE}}),Object.defineProperty(exports,`DEFAULT_LEGEND_CONFIG`,{enumerable:!0,get:function(){return n.DEFAULT_LEGEND_CONFIG}}),Object.defineProperty(exports,`DEFAULT_RECONNECT`,{enumerable:!0,get:function(){return t.DEFAULT_RECONNECT}}),Object.defineProperty(exports,`DEFAULT_STREAM_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_STREAM_CONFIG}}),Object.defineProperty(exports,`DEFAULT_TIMEFRAME_FAVORITES`,{enumerable:!0,get:function(){return t.DEFAULT_TIMEFRAME_FAVORITES}}),Object.defineProperty(exports,`DEFAULT_TRADING_CONFIG`,{enumerable:!0,get:function(){return t.DEFAULT_TRADING_CONFIG}}),Object.defineProperty(exports,`DataExporter`,{enumerable:!0,get:function(){return n.DataExporter}}),exports.DataManager=e.a,exports.DepthChart=i,Object.defineProperty(exports,`DrawingBase`,{enumerable:!0,get:function(){return n.DrawingBase}}),Object.defineProperty(exports,`Easing`,{enumerable:!0,get:function(){return n.Easing}}),exports.EquityCurveChart=a,exports.GaugeChart=u,exports.HeatmapChart=o,Object.defineProperty(exports,`IndicatorBase`,{enumerable:!0,get:function(){return n.IndicatorBase}}),Object.defineProperty(exports,`KeyboardHandler`,{enumerable:!0,get:function(){return n.KeyboardHandler}}),Object.defineProperty(exports,`LIGHT_THEME`,{enumerable:!0,get:function(){return t.LIGHT_THEME}}),exports.LayoutManager=e.r,Object.defineProperty(exports,`MARKET_CRYPTO`,{enumerable:!0,get:function(){return t.MARKET_CRYPTO}}),Object.defineProperty(exports,`MARKET_HNX`,{enumerable:!0,get:function(){return t.MARKET_HNX}}),Object.defineProperty(exports,`MARKET_HOSE`,{enumerable:!0,get:function(){return t.MARKET_HOSE}}),Object.defineProperty(exports,`MARKET_NYSE`,{enumerable:!0,get:function(){return t.MARKET_NYSE}}),Object.defineProperty(exports,`MARKET_UPCOM`,{enumerable:!0,get:function(){return t.MARKET_UPCOM}}),Object.defineProperty(exports,`MockAdapter`,{enumerable:!0,get:function(){return n.MockAdapter}}),exports.PluginManager=e.n,Object.defineProperty(exports,`ReplayManager`,{enumerable:!0,get:function(){return n.ReplayManager}}),Object.defineProperty(exports,`Screenshot`,{enumerable:!0,get:function(){return n.Screenshot}}),Object.defineProperty(exports,`SessionBreaks`,{enumerable:!0,get:function(){return n.SessionBreaks}}),exports.SparklineChart=r,Object.defineProperty(exports,`StreamManager`,{enumerable:!0,get:function(){return n.StreamManager}}),Object.defineProperty(exports,`TIMEFRAMES_CRYPTO`,{enumerable:!0,get:function(){return t.TIMEFRAMES_CRYPTO}}),Object.defineProperty(exports,`TIMEFRAMES_FOREX`,{enumerable:!0,get:function(){return t.TIMEFRAMES_FOREX}}),Object.defineProperty(exports,`TIMEFRAMES_STOCK`,{enumerable:!0,get:function(){return t.TIMEFRAMES_STOCK}}),exports.ThemeManager=e.i,Object.defineProperty(exports,`TickAggregator`,{enumerable:!0,get:function(){return n.TickAggregator}}),Object.defineProperty(exports,`UndoRedoManager`,{enumerable:!0,get:function(){return n.UndoRedoManager}}),Object.defineProperty(exports,`VN_COLORS`,{enumerable:!0,get:function(){return t.VN_COLORS}}),Object.defineProperty(exports,`VolumeRenderer`,{enumerable:!0,get:function(){return n.VolumeRenderer}}),exports.WaterfallChart=s,Object.defineProperty(exports,`Watermark`,{enumerable:!0,get:function(){return n.Watermark}}),Object.defineProperty(exports,`computePriceLimits`,{enumerable:!0,get:function(){return t.computePriceLimits}}),Object.defineProperty(exports,`createVNTheme`,{enumerable:!0,get:function(){return t.createVNTheme}}),Object.defineProperty(exports,`formatNumber`,{enumerable:!0,get:function(){return t.formatNumber}}),Object.defineProperty(exports,`formatVND`,{enumerable:!0,get:function(){return t.formatVND}}),Object.defineProperty(exports,`formatVolumeLoc`,{enumerable:!0,get:function(){return t.formatVolumeLoc}}),Object.defineProperty(exports,`getCurrentSession`,{enumerable:!0,get:function(){return t.getCurrentSession}}),Object.defineProperty(exports,`getLocale`,{enumerable:!0,get:function(){return t.getLocale}}),Object.defineProperty(exports,`normalizeBar`,{enumerable:!0,get:function(){return t.normalizeBar}}),Object.defineProperty(exports,`normalizeBarTime`,{enumerable:!0,get:function(){return t.normalizeBarTime}}),Object.defineProperty(exports,`registerLocale`,{enumerable:!0,get:function(){return t.registerLocale}}),Object.defineProperty(exports,`setLocale`,{enumerable:!0,get:function(){return t.setLocale}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return t.t}}),Object.defineProperty(exports,`toHeikinAshi`,{enumerable:!0,get:function(){return n.toHeikinAshi}}),Object.defineProperty(exports,`toKagi`,{enumerable:!0,get:function(){return n.toKagi}}),Object.defineProperty(exports,`toLineBreak`,{enumerable:!0,get:function(){return n.toLineBreak}}),Object.defineProperty(exports,`toPointAndFigure`,{enumerable:!0,get:function(){return n.toPointAndFigure}}),Object.defineProperty(exports,`toRangeBars`,{enumerable:!0,get:function(){return n.toRangeBars}}),Object.defineProperty(exports,`toRenko`,{enumerable:!0,get:function(){return n.toRenko}});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +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","../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.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 private numberLocale: string;\n private keyboardHandler: KeyboardHandler | null = null;\n private onWindowKeyDown: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: ChartOptions) {\n this.container = container;\n this.options = options;\n this.numberLocale = options.numberLocale ?? 'en-US';\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.priceAxis.setLocale(this.numberLocale);\n this.timeAxis = new TimeAxis();\n\n // Crosshair\n this.crosshairHandler = new CrosshairHandler();\n this.crosshairHandler.setLocale(this.numberLocale);\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 this.keyboardHandler = 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 this.keyboardHandler.setEnabled(this.features.keyboard);\n\n // Attach keyboard listener to window. Only consume the event when the\n // chart actually handles the key AND the container is the focused element\n // (or an ancestor) — this prevents the chart from swallowing keystrokes\n // intended for inputs elsewhere on the page.\n this.onWindowKeyDown = (e: KeyboardEvent) => {\n if (!this.keyboardHandler) return;\n const active = document.activeElement as HTMLElement | null;\n if (active && active !== this.container && !this.container.contains(active)) {\n return;\n }\n // Ignore when typing in a form field that happens to live inside the chart.\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) {\n return;\n }\n if (this.keyboardHandler.handleKey(e)) {\n e.preventDefault();\n }\n };\n window.addEventListener('keydown', this.onWindowKeyDown);\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 // Keep indicator lines in sync with the forming bar. Without this, panel\n // + overlay indicators freeze until bar close.\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\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.indicatorEngine.recalculateAll(this.dataManager.getData());\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 // Panel layout changed — must re-resolve layout, update viewport, and sync render context\n this.updateViewportAndRender();\n } else {\n this.engine.requestRender();\n }\n this.eventBus.emit('indicatorAdd', { instanceId, id });\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 const hadPanel = this.layoutManager.getPanels().some(p => p.id === instanceId);\n this.indicatorEngine.removeIndicator(instanceId);\n this.layoutManager.removePanel(instanceId);\n this.eventBus.emit('indicatorRemove', { instanceId });\n if (hadPanel) {\n this.updateViewportAndRender();\n } else {\n this.engine.requestRender();\n }\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 // Recalculate indicators so panel/overlay series track the forming bar\n // instead of freezing until bar close.\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\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 /**\n * Update the BCP 47 locale used for number formatting\n * (e.g. price axis labels, crosshair value badges).\n * Defaults to 'en-US'. Example values: 'de-DE', 'vi-VN', 'fr-FR'.\n */\n setNumberLocale(locale: string): void {\n this.numberLocale = locale;\n this.priceAxis.setLocale(locale);\n this.crosshairHandler.setLocale(locale);\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n getNumberLocale(): string {\n return this.numberLocale;\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 if (patch.keyboard !== undefined) {\n this.keyboardHandler?.setEnabled(patch.keyboard);\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 if (this.onWindowKeyDown) {\n window.removeEventListener('keydown', this.onWindowKeyDown);\n this.onWindowKeyDown = null;\n }\n this.keyboardHandler = null;\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 // Expand price range to include overlay indicator values (BB, Ichimoku, etc.)\n if (this.options.autoScale !== false) {\n const vs = this.viewport.getState();\n const overlayRange = this.indicatorEngine.getOverlayPriceRange(\n vs.visibleRange.from,\n Math.min(vs.visibleRange.to, displayData.length - 1),\n );\n if (overlayRange) {\n const current = vs.priceRange;\n const expandedMin = Math.min(current.min, overlayRange.min);\n const expandedMax = Math.max(current.max, overlayRange.max);\n if (expandedMin < current.min || expandedMax > current.max) {\n const range = expandedMax - expandedMin || 1;\n this.viewport.setPriceRange(\n expandedMin - range * 0.02,\n expandedMax + range * 0.02,\n );\n }\n }\n }\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 numberLocale: this.numberLocale,\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","import type { SparklineOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\n\nexport class SparklineChart extends BaseFinanceChart {\n private options: SparklineOptions;\n\n constructor(container: HTMLElement, options: SparklineOptions) {\n super(container, options.theme);\n this.options = options;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderSparkline(ctx, width, height, this.options, theme);\n }\n\n update(data: number[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<SparklineOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n}\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\n\nexport class DepthChart extends BaseFinanceChart {\n private options: DepthChartOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: DepthChartOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderDepthChart(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: DepthData): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<DepthChartOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\n\nexport class EquityCurveChart extends BaseFinanceChart {\n private options: EquityCurveOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: EquityCurveOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\n this.options = { ...this.options, data };\n if (benchmark !== undefined) {\n this.options = { ...this.options, benchmark };\n }\n this.requestRender();\n }\n\n setOptions(opts: Partial<EquityCurveOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\nimport {\n BaseFinanceChart,\n FinanceCrosshair,\n layoutUniformGrid,\n layoutSquarifiedTreemap,\n renderHeatmap,\n} from '@tradecanvas/core';\nimport type { LayoutRect } from '@tradecanvas/core';\n\nexport class HeatmapChart extends BaseFinanceChart {\n private options: HeatmapOptions;\n private crosshair: FinanceCrosshair | null = null;\n private cachedRects: LayoutRect[] = [];\n private currentData: HeatmapCell[] = [];\n private lastLayoutWidth = 0;\n private lastLayoutHeight = 0;\n private handleClick: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: HeatmapOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentData = options.data ?? [];\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n if (options.onCellClick) {\n this.handleClick = (e: MouseEvent) => {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n this.onCanvasClick(x, y);\n };\n this.canvas.addEventListener('click', this.handleClick);\n }\n\n this.recomputeLayout();\n this.requestRender();\n }\n\n private recomputeLayout(): void {\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\n const padding = this.options.cellPadding ?? 2;\n this.lastLayoutWidth = this.width;\n this.lastLayoutHeight = this.height;\n\n if (this.options.weighted) {\n const weighted = this.currentData.map(c => ({\n id: c.id,\n weight: c.weight ?? (Math.abs(c.value) || 1),\n }));\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\n } else {\n this.cachedRects = layoutUniformGrid(\n this.currentData.map(c => ({ id: c.id })),\n bounds,\n padding,\n );\n }\n }\n\n private onCanvasClick(x: number, y: number): void {\n if (!this.options.onCellClick) return;\n\n for (const lr of this.cachedRects) {\n const r = lr.rect;\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\n const cell = this.currentData.find(c => c.id === lr.id);\n if (cell) this.options.onCellClick(cell);\n return;\n }\n }\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\n this.recomputeLayout();\n }\n\n const pos = this.crosshair?.getPosition() ?? null;\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\n }\n\n update(data: HeatmapCell[]): void {\n this.currentData = data;\n this.options = { ...this.options, data };\n this.recomputeLayout();\n this.requestRender();\n }\n\n setOptions(opts: Partial<HeatmapOptions>): void {\n this.options = { ...this.options, ...opts };\n if (opts.data) {\n this.currentData = opts.data;\n }\n this.recomputeLayout();\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n if (this.handleClick) {\n this.canvas.removeEventListener('click', this.handleClick);\n }\n super.destroy();\n }\n}\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\n\nexport class WaterfallChart extends BaseFinanceChart {\n private options: WaterfallOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: WaterfallOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderWaterfall(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: WaterfallBar[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<WaterfallOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\n\nconst DEFAULT_ANIMATION_MS = 500;\n\nfunction easeOutCubic(t: number): number {\n const inv = 1 - t;\n return 1 - inv * inv * inv;\n}\n\nexport class GaugeChart extends BaseFinanceChart {\n private options: GaugeOptions;\n private currentValue: number;\n private targetValue: number;\n private animationStart: number | null = null;\n private animationFrom = 0;\n private animationFrameId: number | null = null;\n\n constructor(container: HTMLElement, options: GaugeOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentValue = options.value;\n this.targetValue = options.value;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\n }\n\n setValue(value: number): void {\n const animate = this.options.animate !== false;\n if (!animate) {\n this.cancelAnimation();\n this.currentValue = value;\n this.targetValue = value;\n this.options = { ...this.options, value };\n this.requestRender();\n return;\n }\n\n this.targetValue = value;\n this.animationFrom = this.currentValue;\n this.animationStart = performance.now();\n this.options = { ...this.options, value };\n this.startAnimationLoop();\n }\n\n setOptions(opts: Partial<GaugeOptions>): void {\n const next = { ...this.options, ...opts };\n // If `value` is part of the partial, route through animation path\n if (opts.value !== undefined && opts.value !== this.targetValue) {\n this.options = next;\n this.setValue(opts.value);\n return;\n }\n this.options = next;\n this.requestRender();\n }\n\n private startAnimationLoop(): void {\n if (this.animationFrameId !== null) return;\n const step = (): void => {\n this.animationFrameId = null;\n if (this.animationStart === null) return;\n\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\n const elapsed = performance.now() - this.animationStart;\n const t = Math.min(1, elapsed / Math.max(1, duration));\n const eased = easeOutCubic(t);\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\n\n this.requestRender();\n\n if (t < 1) {\n this.animationFrameId = requestAnimationFrame(step);\n } else {\n this.currentValue = this.targetValue;\n this.animationStart = null;\n }\n };\n this.animationFrameId = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.animationStart = null;\n }\n\n destroy(): void {\n this.cancelAnimation();\n super.destroy();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.ts"],"sourcesContent":["import type { SparklineOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\n\nexport class SparklineChart extends BaseFinanceChart {\n private options: SparklineOptions;\n\n constructor(container: HTMLElement, options: SparklineOptions) {\n super(container, options.theme);\n this.options = options;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderSparkline(ctx, width, height, this.options, theme);\n }\n\n update(data: number[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<SparklineOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n}\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\n\nexport class DepthChart extends BaseFinanceChart {\n private options: DepthChartOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: DepthChartOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderDepthChart(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: DepthData): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<DepthChartOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\n\nexport class EquityCurveChart extends BaseFinanceChart {\n private options: EquityCurveOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: EquityCurveOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\n this.options = { ...this.options, data };\n if (benchmark !== undefined) {\n this.options = { ...this.options, benchmark };\n }\n this.requestRender();\n }\n\n setOptions(opts: Partial<EquityCurveOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\nimport {\n BaseFinanceChart,\n FinanceCrosshair,\n layoutUniformGrid,\n layoutSquarifiedTreemap,\n renderHeatmap,\n} from '@tradecanvas/core';\nimport type { LayoutRect } from '@tradecanvas/core';\n\nexport class HeatmapChart extends BaseFinanceChart {\n private options: HeatmapOptions;\n private crosshair: FinanceCrosshair | null = null;\n private cachedRects: LayoutRect[] = [];\n private currentData: HeatmapCell[] = [];\n private lastLayoutWidth = 0;\n private lastLayoutHeight = 0;\n private handleClick: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: HeatmapOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentData = options.data ?? [];\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n if (options.onCellClick) {\n this.handleClick = (e: MouseEvent) => {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n this.onCanvasClick(x, y);\n };\n this.canvas.addEventListener('click', this.handleClick);\n }\n\n this.recomputeLayout();\n this.requestRender();\n }\n\n private recomputeLayout(): void {\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\n const padding = this.options.cellPadding ?? 2;\n this.lastLayoutWidth = this.width;\n this.lastLayoutHeight = this.height;\n\n if (this.options.weighted) {\n const weighted = this.currentData.map(c => ({\n id: c.id,\n weight: c.weight ?? (Math.abs(c.value) || 1),\n }));\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\n } else {\n this.cachedRects = layoutUniformGrid(\n this.currentData.map(c => ({ id: c.id })),\n bounds,\n padding,\n );\n }\n }\n\n private onCanvasClick(x: number, y: number): void {\n if (!this.options.onCellClick) return;\n\n for (const lr of this.cachedRects) {\n const r = lr.rect;\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\n const cell = this.currentData.find(c => c.id === lr.id);\n if (cell) this.options.onCellClick(cell);\n return;\n }\n }\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\n this.recomputeLayout();\n }\n\n const pos = this.crosshair?.getPosition() ?? null;\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\n }\n\n update(data: HeatmapCell[]): void {\n this.currentData = data;\n this.options = { ...this.options, data };\n this.recomputeLayout();\n this.requestRender();\n }\n\n setOptions(opts: Partial<HeatmapOptions>): void {\n this.options = { ...this.options, ...opts };\n if (opts.data) {\n this.currentData = opts.data;\n }\n this.recomputeLayout();\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n if (this.handleClick) {\n this.canvas.removeEventListener('click', this.handleClick);\n }\n super.destroy();\n }\n}\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\n\nexport class WaterfallChart extends BaseFinanceChart {\n private options: WaterfallOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: WaterfallOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderWaterfall(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: WaterfallBar[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<WaterfallOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\n\nconst DEFAULT_ANIMATION_MS = 500;\n\nfunction easeOutCubic(t: number): number {\n const inv = 1 - t;\n return 1 - inv * inv * inv;\n}\n\nexport class GaugeChart extends BaseFinanceChart {\n private options: GaugeOptions;\n private currentValue: number;\n private targetValue: number;\n private animationStart: number | null = null;\n private animationFrom = 0;\n private animationFrameId: number | null = null;\n\n constructor(container: HTMLElement, options: GaugeOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentValue = options.value;\n this.targetValue = options.value;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\n }\n\n setValue(value: number): void {\n const animate = this.options.animate !== false;\n if (!animate) {\n this.cancelAnimation();\n this.currentValue = value;\n this.targetValue = value;\n this.options = { ...this.options, value };\n this.requestRender();\n return;\n }\n\n this.targetValue = value;\n this.animationFrom = this.currentValue;\n this.animationStart = performance.now();\n this.options = { ...this.options, value };\n this.startAnimationLoop();\n }\n\n setOptions(opts: Partial<GaugeOptions>): void {\n const next = { ...this.options, ...opts };\n // If `value` is part of the partial, route through animation path\n if (opts.value !== undefined && opts.value !== this.targetValue) {\n this.options = next;\n this.setValue(opts.value);\n return;\n }\n this.options = next;\n this.requestRender();\n }\n\n private startAnimationLoop(): void {\n if (this.animationFrameId !== null) return;\n const step = (): void => {\n this.animationFrameId = null;\n if (this.animationStart === null) return;\n\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\n const elapsed = performance.now() - this.animationStart;\n const t = Math.min(1, elapsed / Math.max(1, duration));\n const eased = easeOutCubic(t);\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\n\n this.requestRender();\n\n if (t < 1) {\n this.animationFrameId = requestAnimationFrame(step);\n } else {\n this.currentValue = this.targetValue;\n this.animationStart = null;\n }\n };\n this.animationFrameId = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.animationStart = null;\n }\n\n destroy(): void {\n this.cancelAnimation();\n super.destroy();\n }\n}\n"],"mappings":"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"}
|