@tradecanvas/chart 0.9.0 → 0.14.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.
Files changed (68) hide show
  1. package/dist/Chart.d.ts +110 -1
  2. package/dist/Chart.d.ts.map +1 -1
  3. package/dist/{DragDropImporter-6QOjnfSj.js → DragDropImporter-Br2ez5Gz.js} +296 -103
  4. package/dist/DragDropImporter-Br2ez5Gz.js.map +1 -0
  5. package/dist/DragDropImporter-ycI_Tcs6.cjs +2 -0
  6. package/dist/DragDropImporter-ycI_Tcs6.cjs.map +1 -0
  7. package/dist/finance/PerformanceDashboard.d.ts +43 -0
  8. package/dist/finance/PerformanceDashboard.d.ts.map +1 -0
  9. package/dist/finance/index.d.ts +4 -0
  10. package/dist/finance/index.d.ts.map +1 -1
  11. package/dist/finance/performanceData.d.ts +39 -0
  12. package/dist/finance/performanceData.d.ts.map +1 -0
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +3 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +287 -30
  18. package/dist/index.js.map +1 -1
  19. package/dist/io/index.d.ts +2 -0
  20. package/dist/io/index.d.ts.map +1 -1
  21. package/dist/io/resampleOHLCV.d.ts +29 -0
  22. package/dist/io/resampleOHLCV.d.ts.map +1 -0
  23. package/dist/widget/AlertNotifier.d.ts +32 -0
  24. package/dist/widget/AlertNotifier.d.ts.map +1 -0
  25. package/dist/widget/ChartWidget.d.ts +54 -1
  26. package/dist/widget/ChartWidget.d.ts.map +1 -1
  27. package/dist/widget/DrawingFavoritesStore.d.ts +22 -0
  28. package/dist/widget/DrawingFavoritesStore.d.ts.map +1 -0
  29. package/dist/widget/DrawingTemplateStore.d.ts +29 -0
  30. package/dist/widget/DrawingTemplateStore.d.ts.map +1 -0
  31. package/dist/widget/WidgetAlertsPanel.d.ts +58 -0
  32. package/dist/widget/WidgetAlertsPanel.d.ts.map +1 -0
  33. package/dist/widget/WidgetBracketBar.d.ts +21 -0
  34. package/dist/widget/WidgetBracketBar.d.ts.map +1 -0
  35. package/dist/widget/WidgetDataWindow.d.ts +41 -0
  36. package/dist/widget/WidgetDataWindow.d.ts.map +1 -0
  37. package/dist/widget/WidgetDepthLadder.d.ts +29 -0
  38. package/dist/widget/WidgetDepthLadder.d.ts.map +1 -0
  39. package/dist/widget/WidgetDrawingSidebar.d.ts +6 -0
  40. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  41. package/dist/widget/WidgetDrawingStyle.d.ts +36 -0
  42. package/dist/widget/WidgetDrawingStyle.d.ts.map +1 -0
  43. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
  44. package/dist/widget/WidgetIndicatorSettings.d.ts +42 -0
  45. package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -0
  46. package/dist/widget/WidgetObjectTree.d.ts +59 -0
  47. package/dist/widget/WidgetObjectTree.d.ts.map +1 -0
  48. package/dist/widget/WidgetSettings.d.ts +1 -0
  49. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  50. package/dist/widget/WidgetSymbolSearch.d.ts +3 -1
  51. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
  52. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  53. package/dist/widget/icons.d.ts.map +1 -1
  54. package/dist/widget/index.cjs +932 -15
  55. package/dist/widget/index.cjs.map +1 -1
  56. package/dist/widget/index.js +1824 -157
  57. package/dist/widget/index.js.map +1 -1
  58. package/dist/widget/ladderRows.d.ts +21 -0
  59. package/dist/widget/ladderRows.d.ts.map +1 -0
  60. package/dist/widget/types.d.ts +72 -1
  61. package/dist/widget/types.d.ts.map +1 -1
  62. package/dist/widget/widgetConfig.d.ts.map +1 -1
  63. package/dist/widget/widgetShareState.d.ts +26 -0
  64. package/dist/widget/widgetShareState.d.ts.map +1 -0
  65. package/package.json +3 -3
  66. package/dist/DragDropImporter-6QOjnfSj.js.map +0 -1
  67. package/dist/DragDropImporter-CQ3EarQn.cjs +0 -2
  68. package/dist/DragDropImporter-CQ3EarQn.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DragDropImporter-Br2ez5Gz.js","names":[],"sources":["../src/charts/ChartTypeStrategy.ts","../src/charts/IndicatorPriceRange.ts","../src/state/AutoSaveScheduler.ts","../src/DataManager.ts","../src/ThemeManager.ts","../src/layout/LayoutManager.ts","../src/plugins/PluginManager.ts","../src/Chart.ts","../src/io/parseOHLCV.ts","../src/io/DragDropImporter.ts"],"sourcesContent":["import type { ChartType, DataSeries } from '@tradecanvas/commons';\r\nimport {\r\n AreaRenderer,\r\n BarRenderer,\r\n BaselineRenderer,\r\n CandlestickRenderer,\r\n EquivolumeRenderer,\r\n HLCAreaRenderer,\r\n HollowCandleRenderer,\r\n KagiRenderer,\r\n LineRenderer,\r\n LineWithMarkersRenderer,\r\n PointAndFigureRenderer,\r\n RenkoRenderer,\r\n StepLineRenderer,\r\n VolumeCandleRenderer,\r\n toHeikinAshi,\r\n toKagi,\r\n toLineBreak,\r\n toPointAndFigure,\r\n toRangeBars,\r\n toRenko,\r\n} from '@tradecanvas/core';\r\nimport type { ChartRendererInterface } from '@tradecanvas/core';\r\n\r\n/**\r\n * Pure mapping from `ChartType` to the renderer class that draws it. Several\r\n * chart types reuse `CandlestickRenderer` against transformed data\r\n * (heikinAshi, lineBreak, rangeBars).\r\n */\r\nexport function createRendererFor(type: ChartType): ChartRendererInterface {\r\n switch (type) {\r\n case 'candlestick':\r\n case 'heikinAshi':\r\n case 'lineBreak':\r\n case 'rangeBars':\r\n return new CandlestickRenderer();\r\n case 'line':\r\n return new LineRenderer();\r\n case 'area':\r\n return new AreaRenderer();\r\n case 'bar':\r\n return new BarRenderer();\r\n case 'hollowCandle':\r\n return new HollowCandleRenderer();\r\n case 'baseline':\r\n return new BaselineRenderer();\r\n case 'renko':\r\n return new RenkoRenderer();\r\n case 'kagi':\r\n return new KagiRenderer();\r\n case 'pointAndFigure':\r\n return new PointAndFigureRenderer();\r\n case 'volumeCandles':\r\n return new VolumeCandleRenderer();\r\n case 'equivolume':\r\n return new EquivolumeRenderer();\r\n case 'hlcArea':\r\n return new HLCAreaRenderer();\r\n case 'stepLine':\r\n return new StepLineRenderer();\r\n case 'lineWithMarkers':\r\n return new LineWithMarkersRenderer();\r\n default:\r\n return new CandlestickRenderer();\r\n }\r\n}\r\n\r\n/**\r\n * Transform raw OHLC bars into the display series for a given chart type.\r\n * Returns the input unchanged for chart types that render raw OHLC directly.\r\n *\r\n * Centralized so adding a new chart type only requires editing one file.\r\n */\r\nexport function transformDisplayData(type: ChartType, raw: DataSeries): DataSeries {\r\n if (raw.length === 0) return raw;\r\n\r\n switch (type) {\r\n case 'heikinAshi':\r\n return toHeikinAshi(raw);\r\n case 'renko':\r\n return toRenko(raw, { brickSize: 0, useATR: true, atrPeriod: 14 });\r\n case 'lineBreak':\r\n return toLineBreak(raw, 3);\r\n case 'kagi':\r\n return toKagi(raw, 4);\r\n case 'pointAndFigure': {\r\n const avgPrice = averageClose(raw);\r\n return toPointAndFigure(raw, avgPrice * 0.01, 3);\r\n }\r\n case 'rangeBars': {\r\n const avgPrice = averageClose(raw);\r\n return toRangeBars(raw, { rangeSize: avgPrice * 0.005 });\r\n }\r\n default:\r\n return raw;\r\n }\r\n}\r\n\r\n/** Chart types that materially transform raw OHLC into a different series. */\r\nexport function isTransformedChartType(type: ChartType): boolean {\r\n switch (type) {\r\n case 'heikinAshi':\r\n case 'renko':\r\n case 'lineBreak':\r\n case 'kagi':\r\n case 'pointAndFigure':\r\n case 'rangeBars':\r\n return true;\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\nfunction averageClose(raw: DataSeries): number {\r\n let sum = 0;\r\n for (const b of raw) sum += b.close;\r\n return sum / raw.length;\r\n}\r\n","import type { IndicatorOutput } from '@tradecanvas/commons';\r\n\r\nexport interface PriceRange {\r\n min: number;\r\n max: number;\r\n}\r\n\r\nconst DEFAULT_RANGE: PriceRange = { min: 0, max: 100 };\r\nconst PADDING = 0.1;\r\n\r\n/**\r\n * Compute a padded {min, max} price range for an indicator panel from the\r\n * visible slice of its output. Returns a sensible default range when the\r\n * output is empty or has no values inside [from, to].\r\n *\r\n * Pure — no canvas, no viewport object, just the values map and bar bounds.\r\n * Iterates the output's `values` map in insertion order; we treat its index\r\n * (0…N-1) as the bar index, matching how the engine inserts values.\r\n */\r\nexport function computeIndicatorPriceRange(\r\n output: IndicatorOutput | null,\r\n from: number,\r\n to: number,\r\n): PriceRange {\r\n if (!output) return { ...DEFAULT_RANGE };\r\n\r\n let vMin = Infinity;\r\n let vMax = -Infinity;\r\n let idx = 0;\r\n for (const [, val] of output.values) {\r\n if (idx >= from && idx <= to) {\r\n for (const key in val) {\r\n const v = val[key];\r\n if (v !== undefined && Number.isFinite(v)) {\r\n if (v < vMin) vMin = v;\r\n if (v > vMax) vMax = v;\r\n }\r\n }\r\n }\r\n idx++;\r\n }\r\n\r\n if (vMin === Infinity) return { ...DEFAULT_RANGE };\r\n\r\n const range = vMax - vMin || 1;\r\n return {\r\n min: vMin - range * PADDING,\r\n max: vMax + range * PADDING,\r\n };\r\n}\r\n","/**\r\n * Debounced auto-save scheduler. Coalesces a burst of `schedule()` calls into\r\n * a single `save(key)` invocation after `delayMs` of quiet time. Pure state\r\n * machine — owner injects the actual save callback so this stays testable.\r\n */\r\nexport class AutoSaveScheduler {\r\n private timer: ReturnType<typeof setTimeout> | null = null;\r\n private delayMs = 0;\r\n private key: string | null = null;\r\n\r\n constructor(private save: (key: string) => void) {}\r\n\r\n /** Enable auto-save with the given storage key and quiet-time debounce. */\r\n enable(key: string, delayMs: number): void {\r\n this.key = key;\r\n this.delayMs = delayMs;\r\n }\r\n\r\n /** Disable auto-save and cancel any pending fire. */\r\n disable(): void {\r\n this.key = null;\r\n this.delayMs = 0;\r\n this.cancel();\r\n }\r\n\r\n /**\r\n * Reset the quiet-time window. If currently disabled (no key or delay ≤ 0),\r\n * this is a no-op. Subsequent calls within the window restart the timer.\r\n */\r\n schedule(): void {\r\n if (this.delayMs <= 0 || !this.key) return;\r\n if (this.timer) clearTimeout(this.timer);\r\n this.timer = setTimeout(() => {\r\n this.timer = null;\r\n if (this.key) this.save(this.key);\r\n }, this.delayMs);\r\n }\r\n\r\n /** Cancel any pending fire without changing enabled state. */\r\n cancel(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this.delayMs > 0 && this.key !== null;\r\n }\r\n\r\n hasPending(): boolean {\r\n return this.timer !== null;\r\n }\r\n}\r\n","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 {\r\n ChartOptions,\r\n ChartType,\r\n OHLCBar,\r\n DataSeries,\r\n Theme,\r\n ThemeName,\r\n ChartEventType,\r\n ChartEvent,\r\n ChartEventMap,\r\n TauriBridgeOptions,\r\n IndicatorPlugin,\r\n IndicatorDescriptor,\r\n IndicatorOutput,\r\n DrawingToolType,\r\n DrawingState,\r\n DrawingStyle,\r\n DrawingPlugin,\r\n PanelPosition,\r\n TradingOrder,\r\n TradingPosition,\r\n DepthData,\r\n TradingConfig,\r\n MarketConfig,\r\n Locale,\r\n StreamConfig,\r\n ConnectionState,\r\n ConnectionInfo,\r\n TimeFrame,\r\n FeaturesConfig,\r\n} from '@tradecanvas/commons';\r\nimport { LayerType, setLocale as setGlobalLocale, computePriceLimits } from '@tradecanvas/commons';\r\nimport {\r\n RenderEngine,\r\n Viewport,\r\n GridRenderer,\r\n PriceAxis,\r\n TimeAxis,\r\n InteractionManager,\r\n PanHandler,\r\n ZoomHandler,\r\n AxisDragHandler,\r\n AlertDragHandler,\r\n CrosshairHandler,\r\n IndicatorEngine,\r\n registerBuiltInIndicators,\r\n EventBus,\r\n DrawingManager,\r\n DrawingRenderer,\r\n registerBuiltInDrawingTools,\r\n TradingManager,\r\n TradingRenderer,\r\n StreamManager,\r\n ChartLegend,\r\n Screenshot,\r\n Watermark,\r\n BarCountdown,\r\n VolumeRenderer,\r\n VolumeProfileRenderer,\r\n MarketProfileRenderer,\r\n DepthHeatmapRenderer,\r\n PeriodLevelsRenderer,\r\n PivotMarkersRenderer,\r\n AlertManager,\r\n SignalMarkerManager,\r\n TradeZoneManager,\r\n MeasureOverlay,\r\n ReplayManager,\r\n ChartStateManager,\r\n UndoRedoManager,\r\n Animator,\r\n KeyboardHandler,\r\n CrosshairTooltip,\r\n PinnedTooltip,\r\n DataExporter,\r\n SessionBreaks,\r\n SessionShading,\r\n CompareRenderer,\r\n CurrentPriceLine,\r\n xToBarIndex,\r\n findDominantSwing,\r\n} from '@tradecanvas/core';\r\nimport type { ChartRendererInterface } from '@tradecanvas/core';\r\nimport { timeframeToMs } from '@tradecanvas/commons';\r\nimport { createRendererFor, transformDisplayData } from './charts/ChartTypeStrategy.js';\r\nimport { computeIndicatorPriceRange } from './charts/IndicatorPriceRange.js';\r\nimport { AutoSaveScheduler } from './state/AutoSaveScheduler.js';\r\nimport { DataManager } from './DataManager.js';\r\nimport { ThemeManager } from './ThemeManager.js';\r\nimport { LayoutManager } from './layout/LayoutManager.js';\r\nimport { PluginManager } from './plugins/PluginManager.js';\r\n\r\nexport class Chart {\r\n static version = '0.7.0';\r\n\r\n private engine: RenderEngine;\r\n private viewport: Viewport;\r\n private dataManager: DataManager;\r\n private themeManager: ThemeManager;\r\n private layoutManager: LayoutManager;\r\n private pluginManager: PluginManager;\r\n private indicatorEngine: IndicatorEngine;\r\n private drawingManager: DrawingManager;\r\n private drawingRenderer: DrawingRenderer;\r\n private tradingManager: TradingManager;\r\n private tradingRenderer: TradingRenderer;\r\n private eventBus: EventBus;\r\n private streamManager: StreamManager | null = null;\r\n private autoScrollOnNewBar = true;\r\n private displayDataCache: DataSeries | null = null;\r\n private resolvedLayoutCache: import('@tradecanvas/commons').ResolvedLayout | null = null;\r\n private panelInfoCache: import('@tradecanvas/core').PanelRenderInfo[] | null = null;\r\n private renderScheduled = false;\r\n private containerSizeCache: { width: number; height: number } | null = null;\r\n private containerSizeCacheTime = 0;\r\n private chartLegend: ChartLegend;\r\n private watermark: Watermark;\r\n private barCountdown: BarCountdown;\r\n private sessionBreaks: SessionBreaks;\r\n private sessionShading: SessionShading;\r\n private compareRenderer: CompareRenderer;\r\n private countdownInterval: ReturnType<typeof setInterval> | null = null;\r\n private volumeRenderer: VolumeRenderer;\r\n private volumeProfile: VolumeProfileRenderer;\r\n private marketProfile: MarketProfileRenderer;\r\n private depthHeatmap: DepthHeatmapRenderer;\r\n private periodLevels: PeriodLevelsRenderer;\r\n private pivotMarkers: PivotMarkersRenderer;\r\n private alertManager: AlertManager;\r\n private signalMarkerManager: SignalMarkerManager;\r\n private tradeZoneManager: TradeZoneManager;\r\n private measureOverlay: MeasureOverlay;\r\n private replayManager: ReplayManager;\r\n private undoRedoManager: UndoRedoManager;\r\n private autoSaveScheduler = new AutoSaveScheduler((key) => this.saveState(key));\r\n private animator: Animator;\r\n private crosshairTooltip: CrosshairTooltip;\r\n private pinnedTooltip: PinnedTooltip;\r\n private interactionManager: InteractionManager;\r\n private crosshairHandler: CrosshairHandler;\r\n private chartRenderer: ChartRendererInterface;\r\n private gridRenderer: GridRenderer;\r\n private priceAxis: PriceAxis;\r\n private timeAxis: TimeAxis;\r\n private options: ChartOptions;\r\n private features: Required<FeaturesConfig>;\r\n private marketConfig: MarketConfig | null = null;\r\n private container: HTMLElement;\r\n private currentPriceLine: import('@tradecanvas/core').CurrentPriceLine;\r\n private numberLocale: string;\r\n private keyboardHandler: KeyboardHandler | null = null;\r\n private onWindowKeyDown: ((e: KeyboardEvent) => void) | null = null;\r\n private currentSymbol: string = '';\r\n\r\n\r\n constructor(container: HTMLElement, options: ChartOptions) {\r\n this.container = container;\r\n this.options = options;\r\n this.numberLocale = options.numberLocale ?? 'en-US';\r\n\r\n // Resolve feature flags (all default to true)\r\n const f = options.features ?? {};\r\n this.features = {\r\n drawings: f.drawings ?? true,\r\n drawingTools: f.drawingTools ?? [],\r\n drawingMagnet: f.drawingMagnet ?? true,\r\n drawingUndoRedo: f.drawingUndoRedo ?? true,\r\n trading: f.trading ?? true,\r\n tradingContextMenu: f.tradingContextMenu ?? true,\r\n indicators: f.indicators ?? true,\r\n indicatorIds: f.indicatorIds ?? [],\r\n panning: f.panning ?? true,\r\n zooming: f.zooming ?? true,\r\n crosshair: f.crosshair ?? true,\r\n keyboard: f.keyboard ?? true,\r\n priceAxis: f.priceAxis ?? true,\r\n timeAxis: f.timeAxis ?? true,\r\n grid: f.grid ?? (options.grid?.visible ?? true),\r\n legend: f.legend ?? true,\r\n volume: f.volume ?? true,\r\n watermark: f.watermark ?? true,\r\n saveLoad: f.saveLoad ?? true,\r\n screenshot: f.screenshot ?? true,\r\n alerts: f.alerts ?? true,\r\n replay: f.replay ?? true,\r\n sessionBreaks: f.sessionBreaks ?? true,\r\n barCountdown: f.barCountdown ?? true,\r\n compareSymbols: f.compareSymbols ?? true,\r\n dataExport: f.dataExport ?? true,\r\n logScale: f.logScale ?? true,\r\n timeframes: f.timeframes ?? [],\r\n defaultTimeframeFavorites: f.defaultTimeframeFavorites ?? [],\r\n };\r\n\r\n container.style.position = 'relative';\r\n container.style.overflow = 'hidden';\r\n container.tabIndex = 0; // Allow keyboard events\r\n container.style.outline = 'none';\r\n\r\n // Initialize managers\r\n this.dataManager = new DataManager();\r\n this.themeManager = new ThemeManager(options.theme);\r\n this.layoutManager = new LayoutManager();\r\n this.indicatorEngine = new IndicatorEngine();\r\n this.pluginManager = new PluginManager(this.indicatorEngine);\r\n this.eventBus = new EventBus();\r\n\r\n registerBuiltInIndicators(this.indicatorEngine);\r\n\r\n // Drawing tools\r\n this.drawingManager = new DrawingManager();\r\n registerBuiltInDrawingTools(this.drawingManager);\r\n this.drawingRenderer = new DrawingRenderer(this.drawingManager);\r\n this.drawingManager.setRequestRender(() => {\r\n // Sync entire render context so drawings render with same viewport as candles\r\n this.syncRenderContext();\r\n this.engine.requestRender(LayerType.Overlay);\r\n this.scheduleAutoSave();\r\n });\r\n this.drawingManager.setEventCallback((event, data) => {\r\n this.eventBus.emit(event as ChartEventType, data);\r\n });\r\n // Undo/redo\r\n this.undoRedoManager = new UndoRedoManager();\r\n this.drawingManager.setUndoRedoManager(this.undoRedoManager);\r\n this.drawingManager.setDataGetter(() => this.dataManager.getData());\r\n this.drawingManager.setDisplayDataGetter(() => this.getDisplayData());\r\n // Magnet mode\r\n if (options.crosshair?.mode === 'magnet') {\r\n this.drawingManager.setMagnetMode('magnet');\r\n }\r\n\r\n // Trading\r\n this.tradingManager = new TradingManager({\r\n enabled: this.features.trading,\r\n contextMenu: { enabled: this.features.tradingContextMenu },\r\n });\r\n this.tradingRenderer = new TradingRenderer(this.tradingManager);\r\n this.tradingManager.setContainer(container);\r\n this.tradingManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.tradingManager.setEventCallback((event, data) => {\r\n this.eventBus.emit(event as ChartEventType, data);\r\n });\r\n\r\n // Rendering\r\n this.engine = new RenderEngine(container);\r\n const size = this.engine.dprManager.getContainerSize();\r\n this.viewport = new Viewport(\r\n size.width,\r\n size.height,\r\n options.minBarSpacing ?? 2,\r\n options.maxBarSpacing ?? 30,\r\n options.rightMargin ?? 5,\r\n );\r\n this.layoutManager.resize(size.width, size.height);\r\n\r\n // Sync viewport + layout when the container resizes. Without this hook\r\n // the chart's viewport keeps its construction-time chartRect forever\r\n // (which is wrong if the container started at 0 or got resized since),\r\n // and `scrollToEnd` / clampOffset compute against stale dimensions —\r\n // chart sticks at the wrong offset and the user can't scroll to the\r\n // latest bar.\r\n this.engine.onContainerResize = (newSize) => {\r\n if (newSize.width <= 0 || newSize.height <= 0) return;\r\n const wasAtEnd = this.viewport.isAtEnd();\r\n this.viewport.resize(newSize.width, newSize.height);\r\n this.layoutManager.resize(newSize.width, newSize.height);\r\n // wasAtEnd carries the user's intent: if they were tracking the live\r\n // edge before the resize, keep them there afterwards. Otherwise leave\r\n // their scroll position alone.\r\n this.updateViewportAndRender(wasAtEnd);\r\n };\r\n\r\n // Chart renderer\r\n this.chartRenderer = this.createChartRenderer(options.chartType);\r\n this.gridRenderer = new GridRenderer();\r\n if (options.grid?.visible === false) this.gridRenderer.setVisible(false);\r\n this.priceAxis = new PriceAxis();\r\n this.priceAxis.setLocale(this.numberLocale);\r\n this.timeAxis = new TimeAxis();\r\n\r\n // Crosshair\r\n this.crosshairHandler = new CrosshairHandler();\r\n this.crosshairHandler.setLocale(this.numberLocale);\r\n if (options.crosshair?.mode) {\r\n this.crosshairHandler.setMode(options.crosshair.mode);\r\n }\r\n // Crosshair callback — fired via microtask AFTER render, only when bar changes.\r\n // No DOM writes, no layout reads, no extra render requests.\r\n this.crosshairHandler.setCallback((barIndex, point) => {\r\n if (barIndex !== null && point) {\r\n const data = this.dataManager.getData();\r\n const bar = barIndex < data.length ? data[barIndex] : undefined;\r\n\r\n // Update legend (canvas-rendered, will show on next UI paint)\r\n this.chartLegend.setHoverBar(bar ?? null);\r\n\r\n // Update tooltip (DOM, lightweight update only when bar changes)\r\n if (bar) {\r\n this.crosshairTooltip.show(point, bar, this.themeManager.getTheme(), this.cachedContainerSize());\r\n }\r\n\r\n // Refresh the pinned tooltip's delta strip against the hovered bar.\r\n // Cheap when there's nothing pinned (early returns inside reposition).\r\n if (this.pinnedTooltip.isPinned()) {\r\n this.pinnedTooltip.reposition(\r\n this.viewport.getState(),\r\n bar ?? null,\r\n barIndex,\r\n this.themeManager.getTheme(),\r\n );\r\n }\r\n\r\n // Emit for external consumers\r\n this.eventBus.emit('crosshairMove', { point, bar, barIndex });\r\n } else {\r\n this.crosshairTooltip.hide();\r\n this.chartLegend.setHoverBar(null);\r\n }\r\n });\r\n\r\n // Chart legend (OHLCV overlay)\r\n this.chartLegend = new ChartLegend();\r\n this.chartLegend.setChartType(options.chartType);\r\n\r\n // Watermark + Volume\r\n this.watermark = new Watermark();\r\n if (options.watermark) this.watermark.setConfig(options.watermark);\r\n this.volumeRenderer = new VolumeRenderer();\r\n this.volumeProfile = new VolumeProfileRenderer();\r\n this.marketProfile = new MarketProfileRenderer();\r\n this.depthHeatmap = new DepthHeatmapRenderer();\r\n this.periodLevels = new PeriodLevelsRenderer();\r\n this.pivotMarkers = new PivotMarkersRenderer();\r\n\r\n // Bar countdown timer\r\n this.barCountdown = new BarCountdown();\r\n this.sessionBreaks = new SessionBreaks();\r\n this.sessionShading = new SessionShading();\r\n this.compareRenderer = new CompareRenderer();\r\n\r\n // Apply session break config from options\r\n if (options.sessionBreaks) {\r\n this.sessionBreaks.setConfig({\r\n visible: options.sessionBreaks.visible ?? true,\r\n color: options.sessionBreaks.color,\r\n lineStyle: options.sessionBreaks.lineStyle,\r\n lineWidth: options.sessionBreaks.lineWidth,\r\n });\r\n } else if (options.features?.sessionBreaks !== false) {\r\n this.sessionBreaks.setVisible(true);\r\n }\r\n\r\n // Apply log scale from options\r\n if (options.logScale) {\r\n this.viewport.setLogScale(true);\r\n }\r\n\r\n // Animation\r\n this.animator = new Animator();\r\n\r\n // Crosshair tooltip (DOM)\r\n this.crosshairTooltip = new CrosshairTooltip();\r\n this.crosshairTooltip.create(container);\r\n this.pinnedTooltip = new PinnedTooltip();\r\n this.pinnedTooltip.create(container);\r\n\r\n // Keyboard navigation\r\n this.keyboardHandler = new KeyboardHandler({\r\n scrollBars: (count) => {\r\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\r\n this.viewport.scrollBy(count * barUnit);\r\n this.updateViewportAndRender();\r\n },\r\n zoom: (delta) => {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(delta, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n },\r\n goToStart: () => {\r\n this.viewport.scrollBy(-Infinity);\r\n this.updateViewportAndRender();\r\n },\r\n goToEnd: () => {\r\n this.viewport.scrollToEnd();\r\n this.updateViewportAndRender();\r\n },\r\n fitContent: () => this.fitContent(),\r\n });\r\n this.keyboardHandler.setEnabled(this.features.keyboard);\r\n\r\n // Attach keyboard listener to window. Only consume the event when the\r\n // chart actually handles the key AND the container is the focused element\r\n // (or an ancestor) — this prevents the chart from swallowing keystrokes\r\n // intended for inputs elsewhere on the page.\r\n this.onWindowKeyDown = (e: KeyboardEvent) => {\r\n if (!this.keyboardHandler) return;\r\n const active = document.activeElement as HTMLElement | null;\r\n if (active && active !== this.container && !this.container.contains(active)) {\r\n return;\r\n }\r\n // Ignore when typing in a form field that happens to live inside the chart.\r\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) {\r\n return;\r\n }\r\n if (this.keyboardHandler.handleKey(e)) {\r\n e.preventDefault();\r\n }\r\n };\r\n window.addEventListener('keydown', this.onWindowKeyDown);\r\n\r\n // Current price line (standalone, works without StreamManager)\r\n this.currentPriceLine = new CurrentPriceLine();\r\n\r\n // Alerts\r\n this.alertManager = new AlertManager();\r\n this.alertManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.alertManager.on('triggered', (alert) => {\r\n const payload = { id: alert.id, price: alert.price, condition: alert.condition, message: alert.message, triggered: alert.triggered };\r\n this.eventBus.emit('alertTriggered', payload);\r\n // Back-compat: legacy listeners keyed off dataUpdate.\r\n this.eventBus.emit('dataUpdate', { alert: 'triggered', alertId: alert.id, price: alert.price, message: alert.message });\r\n });\r\n this.alertManager.on('added', (alert) => {\r\n this.eventBus.emit('alertAdd', { id: alert.id, price: alert.price, condition: alert.condition, message: alert.message, triggered: alert.triggered });\r\n });\r\n this.alertManager.on('removed', (id) => {\r\n this.eventBus.emit('alertRemove', { id });\r\n });\r\n this.alertManager.on('updated', (alert) => {\r\n this.eventBus.emit('alertUpdate', { id: alert.id, price: alert.price, condition: alert.condition, message: alert.message, triggered: alert.triggered });\r\n });\r\n\r\n // Signal markers\r\n this.signalMarkerManager = new SignalMarkerManager();\r\n this.signalMarkerManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.signalMarkerManager.setDataGetter(() => this.dataManager.getData());\r\n this.signalMarkerManager.on('added', (m) => {\r\n this.eventBus.emit('signalMarkerAdd' as ChartEventType, { id: m.id, source: m.source, direction: m.direction });\r\n });\r\n this.signalMarkerManager.on('removed', (id) => {\r\n this.eventBus.emit('signalMarkerRemove' as ChartEventType, { id });\r\n });\r\n\r\n // Trade zones\r\n this.tradeZoneManager = new TradeZoneManager();\r\n this.tradeZoneManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\r\n this.tradeZoneManager.setDataGetter(() => this.dataManager.getData());\r\n this.tradeZoneManager.on('added', (z) => {\r\n this.eventBus.emit('tradeZoneAdd' as ChartEventType, { id: z.id, direction: z.direction });\r\n });\r\n this.tradeZoneManager.on('removed', (id) => {\r\n this.eventBus.emit('tradeZoneRemove' as ChartEventType, { id });\r\n });\r\n\r\n // Replay\r\n this.replayManager = new ReplayManager();\r\n\r\n // Measure overlay (shift-drag ruler)\r\n this.measureOverlay = new MeasureOverlay();\r\n\r\n // Interaction\r\n this.interactionManager = new InteractionManager(container);\r\n if (this.features.panning) {\r\n this.interactionManager.setPanHandler(\r\n new PanHandler((deltaX) => {\r\n this.viewport.scrollBy(deltaX);\r\n this.updateViewportAndRender();\r\n }),\r\n );\r\n }\r\n if (this.features.zooming) {\r\n this.interactionManager.setZoomHandler(\r\n new ZoomHandler((delta, centerX) => {\r\n this.viewport.zoom(delta, centerX);\r\n this.updateViewportAndRender();\r\n }),\r\n );\r\n\r\n // Axis drag-scaling (TradingView-style):\r\n // drag price axis → scalePriceRange(factor), disables autoScale\r\n // drag time axis → zoom around chart center\r\n // dblclick axis → reset (price: re-enable autoScale; time: fitContent)\r\n const axisDrag = new AxisDragHandler(\r\n (factor) => {\r\n this.options.autoScale = false;\r\n this.viewport.scalePriceRange(factor);\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n },\r\n (factor) => {\r\n const cw = this.viewport.getState().chartRect.width;\r\n // factor > 1 means zoom OUT (compress time). Map to negative delta\r\n // because Viewport.zoom uses (1 + delta) on barWidth — positive\r\n // delta zooms in.\r\n this.viewport.zoom(1 / factor - 1, cw / 2);\r\n this.updateViewportAndRender();\r\n },\r\n );\r\n this.interactionManager.setAxisDragHandler(\r\n axisDrag,\r\n () => this.viewport.getState(),\r\n (axis) => {\r\n if (axis === 'price') {\r\n this.options.autoScale = true;\r\n this.updateViewportAndRender();\r\n } else {\r\n this.fitContent();\r\n }\r\n },\r\n );\r\n }\r\n if (this.features.crosshair) {\r\n this.interactionManager.setCrosshairHandler(this.crosshairHandler);\r\n }\r\n if (this.features.drawings) {\r\n this.interactionManager.setDrawingManager(\r\n this.drawingManager,\r\n // Inject current data so drawing anchors are stored/resolved as real\r\n // timestamps (survives timeframe/symbol switches).\r\n () => ({ ...this.viewport.getState(), data: this.getDisplayData() }),\r\n );\r\n }\r\n if (this.features.trading) {\r\n this.interactionManager.setTradingManager(\r\n this.tradingManager,\r\n () => ({ ...this.viewport.getState(), data: this.getDisplayData() }),\r\n );\r\n }\r\n if (this.features.alerts) {\r\n const alertDrag = new AlertDragHandler(this.alertManager, () => this.viewport.getState());\r\n this.interactionManager.setAlertDragHandler(alertDrag);\r\n }\r\n // Alt-click pins the OHLC tooltip at the bar under the cursor. Hitting\r\n // it a second time on the same bar unpins.\r\n this.interactionManager.setAltClickHandler((pos) => {\r\n const data = this.getDisplayData();\r\n if (data.length === 0) return;\r\n const vp = this.viewport.getState();\r\n const barUnit = vp.barWidth + vp.barSpacing;\r\n const idx = Math.round((vp.offset + pos.x) / barUnit);\r\n if (idx < 0 || idx >= data.length) return;\r\n if (this.pinnedTooltip.isPinned() && this.pinnedTooltip.getPinnedIndex() === idx) {\r\n this.pinnedTooltip.unpin();\r\n } else {\r\n this.pinnedTooltip.pin(data[idx], idx, this.themeManager.getTheme());\r\n }\r\n this.pinnedTooltip.reposition(\r\n this.viewport.getState(),\r\n this.dataManager.getData()[idx] ?? null,\r\n idx,\r\n this.themeManager.getTheme(),\r\n );\r\n this.engine.requestRender(LayerType.Overlay);\r\n });\r\n\r\n this.interactionManager.setClickHandler((pos) => {\r\n const data = this.getDisplayData();\r\n this.eventBus.emit('click', { x: pos.x, y: pos.y });\r\n if (data.length === 0) return;\r\n // Canonical bar mapping (accounts for chartRect.x + bar centering) so the\r\n // clicked bar matches the crosshair / drawings.\r\n const idx = xToBarIndex(pos.x, this.viewport.getState());\r\n if (idx < 0 || idx >= data.length) return;\r\n this.eventBus.emit('barClick', { bar: data[idx], barIndex: idx, point: pos });\r\n });\r\n\r\n this.interactionManager.setEscapeHandler(() => {\r\n if (this.features.trading && this.tradingManager.isBracketActive()) {\r\n this.tradingManager.cancelBracket();\r\n this.eventBus.emit('dataUpdate', { bracket: 'cancelled' });\r\n return;\r\n }\r\n if (this.pinnedTooltip.isPinned()) {\r\n this.pinnedTooltip.unpin();\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n });\r\n\r\n this.interactionManager.setConfirmHandler(() => {\r\n if (this.features.trading && this.tradingManager.isBracketActive()) {\r\n this.tradingManager.confirmBracket();\r\n return true;\r\n }\r\n return false;\r\n });\r\n\r\n // Shift-drag measure tool — transient overlay. Coords resolved via\r\n // viewport + displayData so the ruler sticks to the data during zoom.\r\n this.interactionManager.setMeasureHandlers({\r\n begin: (pos) => {\r\n this.measureOverlay.begin(pos, this.viewport.getState(), this.getDisplayData());\r\n },\r\n move: (pos) => {\r\n this.measureOverlay.update(pos, this.viewport.getState(), this.getDisplayData());\r\n },\r\n end: () => {\r\n this.measureOverlay.end();\r\n },\r\n });\r\n\r\n this.interactionManager.setOverlayDirtyCallback(() => {\r\n this.engine.requestRender(LayerType.Overlay);\r\n // UI also dirties on every pointer move because the crosshair hover\r\n // pills (price + time axis labels) live on the UI layer so they\r\n // can sit above the static axis labels.\r\n this.engine.requestRender(LayerType.UI);\r\n });\r\n this.interactionManager.attach();\r\n\r\n // Set render context\r\n this.syncRenderContext();\r\n this.engine.start();\r\n }\r\n\r\n // --- Data ---\r\n\r\n setData(data: DataSeries): void {\r\n this.dataManager.setData(data);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.displayDataCache = null;\r\n this.sessionBreaks.invalidateCache();\r\n // New data context (symbol / timeframe) — drop stale alert prev-values so\r\n // the next tick seeds cleanly instead of crossing against the old series.\r\n this.alertManager.clearLastValues();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n // Auto-set current price line from last bar's close\r\n if (data.length > 0) {\r\n this.currentPriceLine.setPrice(data[data.length - 1].close);\r\n }\r\n this.updateViewportAndRender(true);\r\n this.eventBus.emit('dataUpdate', { length: data.length });\r\n }\r\n\r\n appendBar(bar: OHLCBar): void {\r\n this.dataManager.appendBar(bar);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.displayDataCache = null;\r\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.updateViewportAndRender();\r\n }\r\n\r\n /**\r\n * Append multiple bars at once (e.g., catch-up after reconnect).\r\n * More efficient than calling appendBar() in a loop — recalculates\r\n * indicators only once at the end.\r\n */\r\n appendBars(bars: OHLCBar[]): void {\r\n if (bars.length === 0) return;\r\n for (const bar of bars) {\r\n this.dataManager.appendBar(bar);\r\n }\r\n this.displayDataCache = null;\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n this.updateViewportAndRender(this.viewport.isAtEnd());\r\n }\r\n\r\n updateLastBar(bar: OHLCBar): void {\r\n this.dataManager.updateLastBar(bar);\r\n this.currentPriceLine.setPrice(bar.close);\r\n // For non-transform chart types, the displayDataCache still points to the\r\n // same raw array (mutated in place), so no need to invalidate.\r\n // Only invalidate for transform types that produce derived arrays.\r\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\r\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\r\n && this.options.chartType !== 'hollowCandle') {\r\n this.displayDataCache = null;\r\n }\r\n // Keep indicator lines in sync with the forming bar. Without this, panel\r\n // + overlay indicators freeze until bar close.\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n }\r\n\r\n /** Merge a price tick into the current last bar (convenience for live feeds) */\r\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\r\n this.dataManager.updateLastBarFromTick(tick);\r\n this.currentPriceLine.setPrice(tick.price);\r\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\r\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\r\n && this.options.chartType !== 'hollowCandle') {\r\n this.displayDataCache = null;\r\n }\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n }\r\n\r\n // --- Chart type ---\r\n\r\n setChartType(type: ChartType): void {\r\n this.options.chartType = type;\r\n this.chartRenderer = this.createChartRenderer(type);\r\n this.chartLegend.setChartType(type);\r\n this.displayDataCache = null;\r\n this.updateViewportAndRender(true);\r\n }\r\n\r\n // --- Indicators ---\r\n\r\n addIndicator(id: string, params: Record<string, number | string | boolean> = {}, position: PanelPosition = 'bottom'): string | null {\r\n if (!this.features.indicators) return null;\r\n if (this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(id)) return null;\r\n const instanceId = this.indicatorEngine.addIndicator(id, params, this.dataManager.getData());\r\n const descriptor = this.indicatorEngine.getAvailableIndicators().find((d) => d.id === id);\r\n if (descriptor?.placement === 'panel') {\r\n this.layoutManager.addPanel(instanceId, position);\r\n // Panel layout changed — must re-resolve layout, update viewport, and sync render context\r\n this.updateViewportAndRender();\r\n } else {\r\n this.engine.requestRender();\r\n }\r\n this.eventBus.emit('indicatorAdd', { instanceId, id });\r\n return instanceId;\r\n }\r\n\r\n updateIndicator(instanceId: string, params: Record<string, number | string | boolean>): void {\r\n this.indicatorEngine.updateIndicator(instanceId, params, this.dataManager.getData());\r\n this.engine.requestRender();\r\n }\r\n\r\n removeIndicator(instanceId: string): void {\r\n const hadPanel = this.layoutManager.getPanels().some(p => p.id === instanceId);\r\n this.indicatorEngine.removeIndicator(instanceId);\r\n this.layoutManager.removePanel(instanceId);\r\n this.eventBus.emit('indicatorRemove', { instanceId });\r\n if (hadPanel) {\r\n this.updateViewportAndRender();\r\n } else {\r\n this.engine.requestRender();\r\n }\r\n }\r\n\r\n getIndicatorOutput(instanceId: string): IndicatorOutput | null {\r\n return this.indicatorEngine.getOutput(instanceId);\r\n }\r\n\r\n registerIndicator(plugin: IndicatorPlugin): void {\r\n this.pluginManager.registerIndicator(plugin);\r\n }\r\n\r\n static indicators(): IndicatorDescriptor[] {\r\n const engine = new IndicatorEngine();\r\n registerBuiltInIndicators(engine);\r\n return engine.getAvailableIndicators();\r\n }\r\n\r\n // --- Panel layout ---\r\n\r\n setPanelPosition(instanceId: string, position: PanelPosition): void {\r\n this.layoutManager.setPanelPosition(instanceId, position);\r\n this.engine.requestRender();\r\n }\r\n\r\n setPanelSize(instanceId: string, size: number): void {\r\n this.layoutManager.setPanelSize(instanceId, size);\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Drawing tools ---\r\n\r\n setDrawingTool(type: DrawingToolType | null): void {\r\n if (!this.features.drawings) return;\r\n // If whitelist is set, check it\r\n if (type && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(type)) return;\r\n this.drawingManager.setActiveTool(type);\r\n }\r\n\r\n getDrawingTool(): DrawingToolType | null {\r\n return this.drawingManager.getActiveTool();\r\n }\r\n\r\n setDrawingStyle(style: Partial<DrawingStyle>): void {\r\n this.drawingManager.setStyle(style);\r\n }\r\n\r\n getDrawingStyle(): DrawingStyle {\r\n return this.drawingManager.getActiveStyle();\r\n }\r\n\r\n getSelectedDrawingId(): string | null {\r\n return this.drawingManager.getSelectedDrawingId();\r\n }\r\n\r\n /** Restyle the selected drawing (or one by id). Returns true if applied. */\r\n setSelectedDrawingStyle(style: Partial<DrawingStyle>, id?: string): boolean {\r\n return this.drawingManager.setSelectedDrawingStyle(style, id);\r\n }\r\n\r\n getDrawings(): DrawingState[] {\r\n return this.drawingManager.getDrawings();\r\n }\r\n\r\n setDrawings(drawings: DrawingState[]): void {\r\n this.drawingManager.setDrawings(drawings);\r\n }\r\n\r\n /** Append a drawing (id auto-assigned, active style applied). Returns the id. */\r\n addDrawing(state: {\r\n type: import('@tradecanvas/commons').DrawingToolType;\r\n anchors: import('@tradecanvas/commons').AnchorPoint[];\r\n style?: Partial<DrawingStyle>;\r\n visible?: boolean;\r\n locked?: boolean;\r\n meta?: Record<string, unknown>;\r\n }): string | null {\r\n if (!this.features.drawings) return null;\r\n const id = this.drawingManager.addDrawing(state);\r\n this.scheduleAutoSave();\r\n return id;\r\n }\r\n\r\n /**\r\n * Draw a Fibonacci retracement over the dominant swing (extreme high/low) in\r\n * the visible range. Returns the new drawing's id, or null if no swing.\r\n */\r\n autoFib(): string | null {\r\n if (!this.features.drawings) return null;\r\n const data = this.getDisplayData();\r\n const vs = this.viewport.getState();\r\n const swing = findDominantSwing(data, vs.visibleRange.from, vs.visibleRange.to);\r\n if (!swing) return null;\r\n return this.addDrawing({ type: 'fibRetracement', anchors: [swing[0], swing[1]] });\r\n }\r\n\r\n removeDrawing(id: string): void {\r\n this.drawingManager.removeDrawing(id);\r\n }\r\n\r\n setDrawingVisible(id: string, visible: boolean): void {\r\n this.drawingManager.setDrawingVisible(id, visible);\r\n }\r\n\r\n setDrawingLocked(id: string, locked: boolean): void {\r\n this.drawingManager.setDrawingLocked(id, locked);\r\n }\r\n\r\n clearDrawings(): void {\r\n this.drawingManager.clearDrawings();\r\n }\r\n\r\n registerDrawingTool(plugin: DrawingPlugin): void {\r\n this.drawingManager.register(plugin);\r\n }\r\n\r\n // --- Undo/Redo ---\r\n\r\n undo(): boolean {\r\n if (!this.features.drawingUndoRedo) return false;\r\n return this.drawingManager.undo();\r\n }\r\n\r\n redo(): boolean {\r\n if (!this.features.drawingUndoRedo) return false;\r\n return this.drawingManager.redo();\r\n }\r\n\r\n getUndoRedoState(): { canUndo: boolean; canRedo: boolean } {\r\n return this.undoRedoManager.getState();\r\n }\r\n\r\n // --- Drawing magnet ---\r\n\r\n setDrawingMagnet(enabled: boolean): void {\r\n this.drawingManager.setMagnetMode(enabled ? 'magnet' : 'none');\r\n }\r\n\r\n getDrawingMagnet(): boolean {\r\n return this.drawingManager.getMagnetMode() === 'magnet';\r\n }\r\n\r\n // --- Bulk drawing operations ---\r\n\r\n lockAllDrawings(): void {\r\n this.drawingManager.lockAllDrawings();\r\n }\r\n\r\n unlockAllDrawings(): void {\r\n this.drawingManager.unlockAllDrawings();\r\n }\r\n\r\n hideAllDrawings(): void {\r\n this.drawingManager.hideAllDrawings();\r\n }\r\n\r\n showAllDrawings(): void {\r\n this.drawingManager.showAllDrawings();\r\n }\r\n\r\n // --- Drawing duplication ---\r\n\r\n duplicateDrawing(id?: string): string | null {\r\n const targetId = id ?? this.drawingManager.getSelectedDrawingId();\r\n if (!targetId) return null;\r\n return this.drawingManager.duplicateDrawing(targetId);\r\n }\r\n\r\n // --- Data export ---\r\n\r\n exportVisibleData(format: 'csv' | 'json' = 'csv', filename?: string): void {\r\n const vp = this.viewport.getState();\r\n const data = this.dataManager.getData();\r\n const from = Math.max(0, vp.visibleRange.from);\r\n const to = Math.min(data.length - 1, vp.visibleRange.to);\r\n const slice = data.slice(from, to + 1);\r\n\r\n if (format === 'json') {\r\n const content = DataExporter.toJSON(slice);\r\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\r\n } else {\r\n const content = DataExporter.toCSV(slice);\r\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\r\n }\r\n }\r\n\r\n exportAllData(format: 'csv' | 'json' = 'csv', filename?: string): void {\r\n const data = this.dataManager.getData();\r\n if (format === 'json') {\r\n const content = DataExporter.toJSON(data);\r\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\r\n } else {\r\n const content = DataExporter.toCSV(data);\r\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\r\n }\r\n }\r\n\r\n // --- Auto-save ---\r\n\r\n setAutoSave(key: string, delayMs = 5000): void {\r\n this.autoSaveScheduler.enable(key, delayMs);\r\n }\r\n\r\n disableAutoSave(): void {\r\n this.autoSaveScheduler.disable();\r\n }\r\n\r\n private scheduleAutoSave(): void {\r\n this.autoSaveScheduler.schedule();\r\n }\r\n\r\n // --- Indicator introspection ---\r\n\r\n getAvailableIndicators(): IndicatorDescriptor[] {\r\n return this.indicatorEngine.getAvailableIndicators();\r\n }\r\n\r\n getIndicatorInputs(id: string): { id: string; params: Record<string, unknown> } | null {\r\n const indicators = this.indicatorEngine.getAvailableIndicators();\r\n const desc = indicators.find(i => i.id === id);\r\n if (!desc) return null;\r\n return { id: desc.id, params: desc.defaultConfig };\r\n }\r\n\r\n /** Get all active indicator instances with their current params */\r\n getActiveIndicators(): { instanceId: string; id: string; params: Record<string, unknown>; descriptor: IndicatorDescriptor; visible: boolean }[] {\r\n return this.indicatorEngine.getActiveIndicators();\r\n }\r\n\r\n /** Show or hide an indicator without removing it. */\r\n setIndicatorVisible(instanceId: string, visible: boolean): void {\r\n if (this.indicatorEngine.setVisible(instanceId, visible) !== null) {\r\n this.updateViewportAndRender();\r\n }\r\n }\r\n\r\n /** Get current config for a specific indicator instance */\r\n getIndicatorConfig(instanceId: string): { id: string; params: Record<string, unknown> } | null {\r\n const config = this.indicatorEngine.getIndicatorConfig(instanceId);\r\n if (!config) return null;\r\n return { id: config.id, params: { ...config.params } };\r\n }\r\n\r\n /** Update indicator colors/line widths at runtime */\r\n updateIndicatorStyle(instanceId: string, style: { colors?: string[]; lineWidths?: number[]; opacity?: number }): void {\r\n this.indicatorEngine.updateIndicatorStyle(instanceId, style);\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Trading ---\r\n\r\n setOrders(orders: TradingOrder[]): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setOrders(orders);\r\n }\r\n\r\n /**\r\n * Begin placing a draggable bracket order (entry + stop-loss + take-profit).\r\n * Defaults the entry to the latest close when `entry` is omitted. Drag the\r\n * three lines to adjust; confirm with Enter (emits `bracketPlace`) or cancel\r\n * with Esc. Returns false if trading is disabled or no price is available.\r\n */\r\n startBracket(side: import('@tradecanvas/commons').OrderSide, entry?: number): boolean {\r\n if (!this.features.trading) return false;\r\n const data = this.dataManager.getData();\r\n const price = entry ?? (data.length > 0 ? data[data.length - 1].close : null);\r\n if (price === null) return false;\r\n this.tradingManager.startBracket(side, price);\r\n return true;\r\n }\r\n\r\n cancelBracket(): void {\r\n if (this.features.trading) this.tradingManager.cancelBracket();\r\n }\r\n\r\n confirmBracket(): boolean {\r\n return this.features.trading ? this.tradingManager.confirmBracket() : false;\r\n }\r\n\r\n isBracketActive(): boolean {\r\n return this.features.trading && this.tradingManager.isBracketActive();\r\n }\r\n\r\n /**\r\n * Emit an `orderPlace` intent (e.g. from a depth-ladder click). The chart\r\n * does not create the order itself — the host listens via\r\n * `chart.on('orderPlace', …)` and submits to its OMS.\r\n */\r\n placeOrderIntent(intent: import('@tradecanvas/commons').OrderPlaceIntent): void {\r\n if (!this.features.trading) return;\r\n this.eventBus.emit('orderPlace', intent);\r\n }\r\n\r\n setPositions(positions: TradingPosition[]): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setPositions(positions);\r\n }\r\n\r\n setDepthData(depth: DepthData | null): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setDepthData(depth);\r\n }\r\n\r\n setCurrentPrice(price: number, _pulseColor?: string): void {\r\n this.tradingManager.setCurrentPrice(price);\r\n // Also update standalone price line (visible even without trading feature)\r\n this.currentPriceLine.setPrice(price);\r\n this.scheduleRender();\r\n if (this.features.alerts) {\r\n this.alertManager.checkPrice(price);\r\n this.feedIndicatorAlerts();\r\n }\r\n }\r\n\r\n /**\r\n * Feed the latest indicator-line values to any indicator-channel alerts.\r\n * Channel format: `<instanceId>:<key>`; instanceIds are `tc_<id>_<n>` and\r\n * built-in keys are colon-free, so the first colon splits them. Values come\r\n * from the recalculated series, so indicator alerts evaluate at bar cadence\r\n * (the live intrabar tick doesn't repaint closed-bar indicator values).\r\n * Cheap — only walks alerts whose channel isn't `'price'`, usually none.\r\n */\r\n private feedIndicatorAlerts(): void {\r\n const alerts = this.alertManager.getAlerts();\r\n const data = this.dataManager.getData();\r\n if (data.length === 0) return;\r\n const lastIdx = data.length - 1;\r\n const seen = new Set<string>();\r\n for (const alert of alerts) {\r\n if (alert.channel === 'price' || seen.has(alert.channel)) continue;\r\n seen.add(alert.channel);\r\n const sep = alert.channel.indexOf(':');\r\n if (sep < 0) continue;\r\n const instanceId = alert.channel.slice(0, sep);\r\n const key = alert.channel.slice(sep + 1);\r\n const point = this.indicatorEngine.getOutput(instanceId)?.series?.[lastIdx];\r\n const value = point?.[key];\r\n if (typeof value === 'number' && Number.isFinite(value)) {\r\n this.alertManager.checkChannel(alert.channel, value);\r\n }\r\n }\r\n }\r\n\r\n setTradingConfig(config: Partial<TradingConfig>): void {\r\n if (!this.features.trading) return;\r\n this.tradingManager.setConfig(config);\r\n }\r\n\r\n // --- Real-time Streaming ---\r\n\r\n /**\r\n * Connect to a real-time data source.\r\n * Loads history, starts streaming, manages reconnection automatically.\r\n *\r\n * @example\r\n * import { BinanceAdapter } from '@tradecanvas/core';\r\n * chart.connect({\r\n * adapter: new BinanceAdapter(),\r\n * symbol: 'BTCUSDT',\r\n * timeframe: '1m',\r\n * });\r\n */\r\n async connect(config: StreamConfig): Promise<void> {\r\n this.disconnectStream();\r\n\r\n this.streamManager = new StreamManager();\r\n\r\n this.streamManager.on('snapshot', (bars) => {\r\n this.setData(bars);\r\n });\r\n\r\n this.streamManager.on('barClose', (bar) => {\r\n this.dataManager.appendBar(bar);\r\n this.crosshairHandler.setData(this.dataManager.getData());\r\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.updateViewportAndRender();\r\n });\r\n\r\n this.streamManager.on('barUpdate', (bar) => {\r\n this.dataManager.updateLastBar(bar);\r\n this.currentPriceLine.setPrice(bar.close);\r\n // Recalculate indicators so panel/overlay series track the forming bar\r\n // instead of freezing until bar close.\r\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\r\n this.scheduleRender();\r\n });\r\n\r\n this.streamManager.on('priceChange', ({ price }) => {\r\n this.tradingManager.setCurrentPrice(price);\r\n this.currentPriceLine.setPrice(price);\r\n this.engine.requestRender(LayerType.Overlay);\r\n this.engine.requestRender(LayerType.UI);\r\n });\r\n\r\n this.streamManager.on('connectionChange', (info) => {\r\n this.eventBus.emit('dataUpdate', { connection: info });\r\n });\r\n\r\n this.streamManager.on('error', (err) => {\r\n this.eventBus.emit('dataUpdate', { error: err.message });\r\n });\r\n\r\n this.autoScrollOnNewBar = config.autoScroll !== false;\r\n this.currentSymbol = config.symbol;\r\n\r\n await this.streamManager.connect(config);\r\n\r\n // Set up bar countdown timer based on timeframe\r\n const tfMs = timeframeToMs(config.timeframe);\r\n this.barCountdown.setTimeframeMs(tfMs);\r\n\r\n // Start countdown refresh interval\r\n if (this.countdownInterval) clearInterval(this.countdownInterval);\r\n this.countdownInterval = setInterval(() => {\r\n if (this.barCountdown.isVisible()) {\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n }, 1000);\r\n }\r\n\r\n /**\r\n * Switch symbol or timeframe on an active stream without full reconnect.\r\n */\r\n async switchStream(symbol: string, timeframe: TimeFrame): Promise<void> {\r\n if (!this.streamManager) return;\r\n this.currentSymbol = symbol;\r\n await this.streamManager.switchTo(symbol, timeframe);\r\n }\r\n\r\n /**\r\n * Switch to a new timeframe. Requires an active stream connection.\r\n * Internally calls switchStream with the current symbol.\r\n */\r\n async setTimeframe(timeframe: TimeFrame): Promise<void> {\r\n if (!this.streamManager) throw new Error('No active stream. Call connect() first.');\r\n await this.switchStream(this.currentSymbol, timeframe);\r\n }\r\n\r\n /**\r\n * Disconnect the real-time stream.\r\n */\r\n disconnectStream(): void {\r\n if (this.streamManager) {\r\n this.streamManager.dispose();\r\n this.streamManager = null;\r\n }\r\n }\r\n\r\n setBarCountdownVisible(visible: boolean): void {\r\n this.barCountdown.setVisible(visible);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n setSessionBreaksVisible(visible: boolean): void {\r\n this.sessionBreaks.setVisible(visible);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n // --- Compare symbols ---\r\n\r\n addCompareSymbol(id: string, label: string, data: DataSeries, color: string): void {\r\n this.compareRenderer.addSymbol({ id, label, data, color, visible: true });\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n removeCompareSymbol(id: string): void {\r\n this.compareRenderer.removeSymbol(id);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n updateCompareData(id: string, data: DataSeries): void {\r\n this.compareRenderer.setSymbolData(id, data);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n setCompareMode(mode: 'percent' | 'absolute'): void {\r\n this.compareRenderer.setMode(mode);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n clearCompareSymbols(): void {\r\n this.compareRenderer.clear();\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Price scale ---\r\n\r\n setLogScale(enabled: boolean): void {\r\n this.viewport.setLogScale(enabled);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n isLogScale(): boolean {\r\n return this.viewport.isLogScale();\r\n }\r\n\r\n /**\r\n * Set the price-scale presentation: `regular`, `logarithmic`, `percentage`\r\n * (axis labels show % change from the first visible bar), or `indexedTo100`\r\n * (rebased so the first visible bar reads as 100).\r\n */\r\n setScaleMode(mode: import('@tradecanvas/commons').PriceScaleMode): void {\r\n this.viewport.setScaleMode(mode);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n getScaleMode(): import('@tradecanvas/commons').PriceScaleMode {\r\n return this.viewport.getScaleMode();\r\n }\r\n\r\n setSessionBreaksConfig(config: { color?: string; lineStyle?: 'solid' | 'dashed' | 'dotted'; lineWidth?: number }): void {\r\n this.sessionBreaks.setConfig(config);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n getConnectionState(): ConnectionState {\r\n return this.streamManager?.getConnectionState() ?? 'disconnected';\r\n }\r\n\r\n getConnectionInfo(): ConnectionInfo {\r\n return this.streamManager?.getConnectionInfo() ?? { state: 'disconnected' };\r\n }\r\n\r\n setAutoScroll(enabled: boolean): void {\r\n this.autoScrollOnNewBar = enabled;\r\n }\r\n\r\n // --- Viewport ---\r\n\r\n scrollTo(timestamp: number): void {\r\n const data = this.dataManager.getData();\r\n for (let i = 0; i < data.length; i++) {\r\n if (data[i].time >= timestamp) {\r\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\r\n this.viewport.scrollBy(i * barUnit - this.viewport.getState().offset);\r\n this.updateViewportAndRender();\r\n return;\r\n }\r\n }\r\n }\r\n\r\n scrollToEnd(): void {\r\n this.viewport.scrollToEnd();\r\n this.updateViewportAndRender();\r\n }\r\n\r\n setVisibleRange(fromTimestamp: number, toTimestamp: number): void {\r\n const data = this.dataManager.getData();\r\n let fromIdx = 0;\r\n let toIdx = data.length - 1;\r\n for (let i = 0; i < data.length; i++) {\r\n if (data[i].time >= fromTimestamp) { fromIdx = i; break; }\r\n }\r\n for (let i = data.length - 1; i >= 0; i--) {\r\n if (data[i].time <= toTimestamp) { toIdx = i; break; }\r\n }\r\n const barCount = toIdx - fromIdx + 1;\r\n if (barCount > 0) {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n const targetBarUnit = chartWidth / barCount;\r\n const newBarWidth = Math.max(2, targetBarUnit - this.viewport.getState().barSpacing);\r\n this.viewport.zoom(\r\n (newBarWidth - this.viewport.getState().barWidth) / this.viewport.getState().barWidth,\r\n chartWidth / 2,\r\n );\r\n }\r\n this.updateViewportAndRender();\r\n }\r\n\r\n zoomIn(): void {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(0.2, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n zoomOut(): void {\r\n const chartWidth = this.viewport.getState().chartRect.width;\r\n this.viewport.zoom(-0.2, chartWidth / 2);\r\n this.updateViewportAndRender();\r\n }\r\n\r\n fitContent(): void {\r\n const data = this.dataManager.getData();\r\n if (data.length === 0) return;\r\n this.setVisibleRange(data[0].time, data[data.length - 1].time);\r\n }\r\n\r\n // --- Events ---\r\n\r\n on<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void {\r\n this.eventBus.on(type, handler as (event: ChartEvent) => void);\r\n }\r\n\r\n off<K extends ChartEventType>(type: K, handler: (event: ChartEvent<K extends keyof ChartEventMap ? ChartEventMap[K] : unknown>) => void): void {\r\n this.eventBus.off(type, handler as (event: ChartEvent) => void);\r\n }\r\n\r\n enableTauriBridge(options?: Partial<TauriBridgeOptions>): void {\r\n this.eventBus.enableTauriBridge({ enabled: true, ...options });\r\n }\r\n\r\n disableTauriBridge(): void {\r\n this.eventBus.disableTauriBridge();\r\n }\r\n\r\n // --- Theme ---\r\n\r\n setTheme(themeOrName: ThemeName | Theme): void {\r\n this.themeManager.setTheme(themeOrName);\r\n this.syncRenderContext();\r\n this.container.style.backgroundColor = this.themeManager.getTheme().background;\r\n this.engine.requestRender();\r\n this.eventBus.emit('themeChange', { theme: themeOrName });\r\n }\r\n\r\n getTheme(): Theme {\r\n return this.themeManager.getTheme();\r\n }\r\n\r\n // --- Watermark ---\r\n\r\n setWatermark(text: string, opts?: { color?: string; fontSize?: number }): void {\r\n this.watermark.setConfig({ text, ...opts });\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n // --- Auto Scale ---\r\n\r\n setAutoScale(enabled: boolean): void {\r\n this.options.autoScale = enabled;\r\n this.updateViewportAndRender();\r\n }\r\n\r\n isAutoScale(): boolean {\r\n return this.options.autoScale !== false;\r\n }\r\n\r\n // --- Crosshair ---\r\n\r\n setCrosshairMode(mode: 'normal' | 'magnet' | 'hidden'): void {\r\n this.crosshairHandler.setMode(mode);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n getCrosshairMode(): string {\r\n return this.crosshairHandler.getMode();\r\n }\r\n\r\n setCrosshairPosition(point: { x: number; y: number } | null): void {\r\n if (point) {\r\n this.crosshairHandler.onPointerMove(point);\r\n }\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n getData(): DataSeries {\r\n return this.dataManager.getData();\r\n }\r\n\r\n // --- Grid ---\r\n\r\n setGridVisible(visible: boolean): void {\r\n this.gridRenderer.setVisible(visible);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n isGridVisible(): boolean {\r\n return this.gridRenderer.isVisible();\r\n }\r\n\r\n // --- Volume ---\r\n\r\n setVolumeVisible(visible: boolean): void {\r\n this.volumeRenderer.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Volume Profile ---\r\n\r\n setVolumeProfileVisible(visible: boolean): void {\r\n this.volumeProfile.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n isVolumeProfileVisible(): boolean {\r\n return this.volumeProfile.isVisible();\r\n }\r\n\r\n setVolumeProfileConfig(config: { buckets?: number; widthRatio?: number; opacity?: number; highlightPoC?: boolean }): void {\r\n if (config.buckets !== undefined) this.volumeProfile.setBuckets(config.buckets);\r\n if (config.widthRatio !== undefined) this.volumeProfile.setWidthRatio(config.widthRatio);\r\n if (config.opacity !== undefined) this.volumeProfile.setOpacity(config.opacity);\r\n if (config.highlightPoC !== undefined) this.volumeProfile.setHighlightPoC(config.highlightPoC);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Market Profile (TPO) ---\r\n\r\n setMarketProfileVisible(visible: boolean): void {\r\n this.marketProfile.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n isMarketProfileVisible(): boolean {\r\n return this.marketProfile.isVisible();\r\n }\r\n\r\n setMarketProfileConfig(config: { buckets?: number; widthRatio?: number; opacity?: number; valueAreaPct?: number; highlightPoC?: boolean; showStats?: boolean; splitBySession?: boolean; letters?: boolean }): void {\r\n if (config.buckets !== undefined) this.marketProfile.setBuckets(config.buckets);\r\n if (config.widthRatio !== undefined) this.marketProfile.setWidthRatio(config.widthRatio);\r\n if (config.opacity !== undefined) this.marketProfile.setOpacity(config.opacity);\r\n if (config.valueAreaPct !== undefined) this.marketProfile.setValueAreaPct(config.valueAreaPct);\r\n if (config.highlightPoC !== undefined) this.marketProfile.setHighlightPoC(config.highlightPoC);\r\n if (config.showStats !== undefined) this.marketProfile.setShowStats(config.showStats);\r\n if (config.splitBySession !== undefined) this.marketProfile.setSplitBySession(config.splitBySession);\r\n if (config.letters !== undefined) this.marketProfile.setLetters(config.letters);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n /** POC / VAH / VAL of the currently rendered Market Profile, or null. */\r\n getMarketProfileStats(): import('@tradecanvas/core').MarketProfileStats | null {\r\n return this.marketProfile.getStats();\r\n }\r\n\r\n // --- Liquidity heatmap ---\r\n\r\n setDepthHeatmapVisible(visible: boolean): void {\r\n this.depthHeatmap.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n isDepthHeatmapVisible(): boolean {\r\n return this.depthHeatmap.isVisible();\r\n }\r\n\r\n setDepthHeatmapConfig(config: { opacity?: number; capacity?: number }): void {\r\n if (config.opacity !== undefined) this.depthHeatmap.setOpacity(config.opacity);\r\n if (config.capacity !== undefined) this.depthHeatmap.setCapacity(config.capacity);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n /**\r\n * Record an order-book snapshot for the liquidity heatmap, stamped at the\r\n * latest bar's time. Call alongside `setDepthData` on each book update.\r\n */\r\n pushDepthSnapshot(depth: import('@tradecanvas/commons').DepthData): void {\r\n const data = this.dataManager.getData();\r\n if (data.length === 0) return;\r\n this.depthHeatmap.push(data[data.length - 1].time, depth);\r\n if (this.depthHeatmap.isVisible()) this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n clearDepthHeatmap(): void {\r\n this.depthHeatmap.clear();\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n // --- Prior-period levels (PDH / PDL / PDC) ---\r\n\r\n setPeriodLevelsVisible(visible: boolean): void {\r\n this.periodLevels.setVisible(visible);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n isPeriodLevelsVisible(): boolean {\r\n return this.periodLevels.isVisible();\r\n }\r\n\r\n setPeriodLevelsPeriod(period: import('@tradecanvas/core').LevelPeriod): void {\r\n this.periodLevels.setPeriod(period);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n\r\n /**\r\n * Set the timezone for time-axis labels and the crosshair time pill.\r\n * `null` = browser-local; a number = fixed UTC offset in minutes (e.g. -300\r\n * for EST, 330 for IST).\r\n */\r\n setTimezoneOffset(minutes: number | null): void {\r\n this.timeAxis.setTimezoneOffset(minutes);\r\n this.crosshairHandler.setTimezoneOffset(minutes);\r\n this.engine.requestRender(LayerType.UI);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n // --- Pivot / swing markers ---\r\n\r\n setPivotMarkersVisible(visible: boolean): void {\r\n this.pivotMarkers.setVisible(visible);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n isPivotMarkersVisible(): boolean {\r\n return this.pivotMarkers.isVisible();\r\n }\r\n\r\n setPivotMarkersConfig(config: { left?: number; right?: number; showLabels?: boolean; structureLabels?: boolean }): void {\r\n if (config.left !== undefined || config.right !== undefined) {\r\n this.pivotMarkers.setStrength(config.left ?? 5, config.right ?? config.left ?? 5);\r\n }\r\n if (config.showLabels !== undefined) this.pivotMarkers.setShowLabels(config.showLabels);\r\n if (config.structureLabels !== undefined) this.pivotMarkers.setStructureLabels(config.structureLabels);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n // --- Session (RTH) shading ---\r\n\r\n setSessionShadingVisible(visible: boolean): void {\r\n this.sessionShading.setVisible(visible);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n isSessionShadingVisible(): boolean {\r\n return this.sessionShading.isVisible();\r\n }\r\n\r\n /** Configure the regular session window (minutes-of-day + tz offset). */\r\n setSessionShadingConfig(config: Partial<import('@tradecanvas/core').SessionHoursConfig>): void {\r\n this.sessionShading.setConfig(config);\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n\r\n // --- Tooltip ---\r\n\r\n setTooltipVisible(visible: boolean): void {\r\n if (!visible) this.crosshairTooltip.hide();\r\n }\r\n\r\n // --- Legend ---\r\n\r\n setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void {\r\n this.chartLegend.setConfig(config);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n setSymbolName(symbol: string): void {\r\n this.chartLegend.setSymbol(symbol);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n /**\r\n * Set a status text displayed in the chart legend area (e.g., \"LIVE . 8ms\").\r\n * Pass null to clear.\r\n */\r\n setStatusText(text: string | null): void {\r\n this.chartLegend.setStatusText(text);\r\n this.engine.requestRender(LayerType.UI);\r\n }\r\n\r\n // --- Screenshot ---\r\n\r\n screenshot(filename?: string): void {\r\n if (!this.features.screenshot) return;\r\n Screenshot.download(this.container, filename, this.themeManager.getTheme().background);\r\n }\r\n\r\n /** Copy the chart image to the clipboard. Returns false if unsupported/blocked. */\r\n async copyScreenshot(): Promise<boolean> {\r\n if (!this.features.screenshot) return false;\r\n try {\r\n const blob = await Screenshot.toBlob(this.container, this.themeManager.getTheme().background);\r\n const ClipboardItemCtor = (globalThis as { ClipboardItem?: typeof ClipboardItem }).ClipboardItem;\r\n if (!blob || !navigator.clipboard?.write || !ClipboardItemCtor) return false;\r\n await navigator.clipboard.write([new ClipboardItemCtor({ 'image/png': blob })]);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n screenshotDataURL(): string | null {\r\n if (!this.features.screenshot) return null;\r\n return Screenshot.toDataURL(this.container, this.themeManager.getTheme().background);\r\n }\r\n\r\n async screenshotBlob(): Promise<Blob | null> {\r\n if (!this.features.screenshot) return null;\r\n return Screenshot.toBlob(this.container, this.themeManager.getTheme().background);\r\n }\r\n\r\n // --- Alerts ---\r\n\r\n addAlert(\r\n price: number,\r\n condition: import('@tradecanvas/core').AlertCondition = 'crossing',\r\n message?: string,\r\n channel = 'price',\r\n label?: string,\r\n ): string | null {\r\n if (!this.features.alerts) return null;\r\n const id = this.alertManager.addAlert(price, condition, message, false, channel, label);\r\n this.scheduleAutoSave();\r\n return id;\r\n }\r\n\r\n removeAlert(id: string): void {\r\n this.alertManager.removeAlert(id);\r\n this.scheduleAutoSave();\r\n }\r\n\r\n getAlerts(): import('@tradecanvas/core').PriceAlert[] {\r\n return this.alertManager.getAlerts();\r\n }\r\n\r\n clearAlerts(): void {\r\n this.alertManager.clearAlerts();\r\n this.scheduleAutoSave();\r\n }\r\n\r\n saveAlerts(key: string): void {\r\n this.alertManager.saveToStorage(key);\r\n }\r\n\r\n loadAlerts(key: string): void {\r\n this.alertManager.loadFromStorage(key);\r\n this.engine.requestRender(LayerType.Overlay);\r\n }\r\n\r\n // --- Signal Markers ---\r\n\r\n addSignalMarker(marker: Omit<import('@tradecanvas/commons').SignalMarker, 'id'> & { id?: string }): string {\r\n return this.signalMarkerManager.addMarker(marker);\r\n }\r\n\r\n removeSignalMarker(id: string): void {\r\n this.signalMarkerManager.removeMarker(id);\r\n }\r\n\r\n getSignalMarkers(): import('@tradecanvas/commons').SignalMarker[] {\r\n return this.signalMarkerManager.getMarkers();\r\n }\r\n\r\n setSignalMarkers(markers: import('@tradecanvas/commons').SignalMarker[]): void {\r\n this.signalMarkerManager.setMarkers(markers);\r\n }\r\n\r\n clearSignalMarkers(): void {\r\n this.signalMarkerManager.clearMarkers();\r\n }\r\n\r\n setSignalMarkerStyle(style: Partial<import('@tradecanvas/commons').SignalMarkerStyle>): void {\r\n this.signalMarkerManager.setStyle(style);\r\n }\r\n\r\n // --- Trade Zones ---\r\n\r\n addTradeZone(zone: Omit<import('@tradecanvas/commons').TradeZone, 'id'> & { id?: string }): string {\r\n return this.tradeZoneManager.addZone(zone);\r\n }\r\n\r\n updateTradeZone(id: string, updates: Partial<Omit<import('@tradecanvas/commons').TradeZone, 'id'>>): void {\r\n this.tradeZoneManager.updateZone(id, updates);\r\n }\r\n\r\n removeTradeZone(id: string): void {\r\n this.tradeZoneManager.removeZone(id);\r\n }\r\n\r\n getTradeZones(): import('@tradecanvas/commons').TradeZone[] {\r\n return this.tradeZoneManager.getZones();\r\n }\r\n\r\n setTradeZones(zones: import('@tradecanvas/commons').TradeZone[]): void {\r\n this.tradeZoneManager.setZones(zones);\r\n }\r\n\r\n clearTradeZones(): void {\r\n this.tradeZoneManager.clearZones();\r\n }\r\n\r\n setTradeZoneStyle(style: Partial<import('@tradecanvas/commons').TradeZoneStyle>): void {\r\n this.tradeZoneManager.setStyle(style);\r\n }\r\n\r\n // --- Replay ---\r\n\r\n replay(config?: Partial<import('@tradecanvas/core').ReplayConfig>): void {\r\n if (!this.features.replay) return;\r\n const data = this.dataManager.getData();\r\n this.replayManager.load(data);\r\n this.replayManager.on('bar', ({ bar: _bar, index }) => {\r\n const slice = data.slice(0, index + 1);\r\n this.dataManager.setData(slice);\r\n this.crosshairHandler.setData(slice);\r\n this.indicatorEngine.recalculateAll(slice);\r\n this.updateViewportAndRender();\r\n });\r\n this.replayManager.play(config);\r\n }\r\n\r\n replayPause(): void { this.replayManager.pause(); }\r\n replayResume(): void { this.replayManager.resume(); }\r\n replayStop(): void { this.replayManager.stop(); }\r\n replaySeek(index: number): void { this.replayManager.seekTo(index); }\r\n setReplaySpeed(speed: number): void { this.replayManager.setSpeed(speed); }\r\n getReplayState(): 'playing' | 'paused' | 'stopped' { return this.replayManager.getState(); }\r\n getReplayProgress(): { current: number; total: number; percent: number } { return this.replayManager.getProgress(); }\r\n\r\n // --- Save / Load ---\r\n\r\n saveState(key?: string): string | null {\r\n if (!this.features.saveLoad) return null;\r\n const snapshot = ChartStateManager.capture(\r\n {\r\n getDrawings: () => this.getDrawings(),\r\n getTheme: () => this.getTheme(),\r\n getAlerts: () => this.getAlerts(),\r\n },\r\n { chartType: this.options.chartType },\r\n );\r\n const json = ChartStateManager.serialize(snapshot);\r\n if (key) ChartStateManager.saveToStorage(key, snapshot);\r\n return json;\r\n }\r\n\r\n loadState(json: string): void {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = ChartStateManager.deserialize(json);\r\n if (snapshot.chartType) this.setChartType(snapshot.chartType);\r\n if (snapshot.drawings) this.setDrawings(snapshot.drawings);\r\n if (snapshot.theme) this.setTheme(snapshot.theme as any);\r\n if (snapshot.alerts) {\r\n this.clearAlerts();\r\n for (const a of snapshot.alerts) {\r\n this.addAlert(a.price, a.condition, a.message);\r\n }\r\n }\r\n }\r\n\r\n loadStateFromStorage(key: string): boolean {\r\n if (!this.features.saveLoad) return false;\r\n const snapshot = ChartStateManager.loadFromStorage(key);\r\n if (!snapshot) return false;\r\n this.loadState(ChartStateManager.serialize(snapshot));\r\n return true;\r\n }\r\n\r\n downloadState(filename?: string): void {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = ChartStateManager.capture(\r\n { getDrawings: () => this.getDrawings(), getTheme: () => this.getTheme(), getAlerts: () => this.getAlerts() },\r\n { chartType: this.options.chartType },\r\n );\r\n ChartStateManager.downloadFile(snapshot, filename);\r\n }\r\n\r\n async loadStateFromFile(): Promise<void> {\r\n if (!this.features.saveLoad) return;\r\n const snapshot = await ChartStateManager.loadFromFile();\r\n this.loadState(ChartStateManager.serialize(snapshot));\r\n }\r\n\r\n // --- Locale ---\r\n\r\n setLocale(locale: Locale): void {\r\n setGlobalLocale(locale);\r\n this.engine.requestRender();\r\n }\r\n\r\n /**\r\n * Update the BCP 47 locale used for number formatting\r\n * (e.g. price axis labels, crosshair value badges).\r\n * Defaults to 'en-US'. Example values: 'de-DE', 'vi-VN', 'fr-FR'.\r\n */\r\n setNumberLocale(locale: string): void {\r\n this.numberLocale = locale;\r\n this.priceAxis.setLocale(locale);\r\n this.crosshairHandler.setLocale(locale);\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n getNumberLocale(): string {\r\n return this.numberLocale;\r\n }\r\n\r\n // --- Market ---\r\n\r\n setMarket(config: MarketConfig): void {\r\n this.marketConfig = config;\r\n\r\n // Apply market color scheme to theme\r\n if (config.colorScheme) {\r\n const base = this.themeManager.getTheme();\r\n const marketTheme: Theme = {\r\n ...base,\r\n candleUp: config.colorScheme.up,\r\n candleDown: config.colorScheme.down,\r\n candleUpWick: config.colorScheme.up,\r\n candleDownWick: config.colorScheme.down,\r\n volumeUp: config.colorScheme.up.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.up}4D`,\r\n volumeDown: config.colorScheme.down.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.down}4D`,\r\n };\r\n this.themeManager.setTheme(marketTheme);\r\n }\r\n\r\n // Apply price precision to trading, alerts, and price line\r\n if (config.pricePrecision !== undefined) {\r\n this.tradingManager.setConfig({ pricePrecision: config.pricePrecision });\r\n this.alertManager.setPricePrecision(config.pricePrecision);\r\n this.streamManager?.priceLine.setPricePrecision(config.pricePrecision);\r\n this.crosshairHandler.setPricePrecision(config.pricePrecision);\r\n }\r\n\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n getMarket(): MarketConfig | null {\r\n return this.marketConfig;\r\n }\r\n\r\n setPriceLimits(referencePrice: number): void {\r\n if (!this.marketConfig) return;\r\n const limits = computePriceLimits(referencePrice, this.marketConfig);\r\n if (limits) {\r\n this.marketConfig.priceLimits = {\r\n ...this.marketConfig.priceLimits!,\r\n referencePrice,\r\n };\r\n }\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Features ---\r\n\r\n /** Get the resolved feature configuration */\r\n getFeatures(): Readonly<Required<FeaturesConfig>> {\r\n return this.features;\r\n }\r\n\r\n /** Update feature flags at runtime. Only provided keys are changed. */\r\n setFeatures(patch: Partial<FeaturesConfig>): void {\r\n Object.assign(this.features, patch);\r\n\r\n // Apply immediate side-effects\r\n if (patch.crosshair === false) {\r\n this.crosshairTooltip.hide();\r\n }\r\n if (patch.grid !== undefined) {\r\n this.engine.requestRender(LayerType.Background);\r\n }\r\n if (patch.volume !== undefined) {\r\n this.volumeRenderer.setVisible(patch.volume);\r\n this.engine.requestRender(LayerType.Main);\r\n }\r\n if (patch.drawings === false) {\r\n this.drawingManager.setActiveTool(null);\r\n }\r\n if (patch.trading === false) {\r\n this.tradingManager.setOrders([]);\r\n this.tradingManager.setPositions([]);\r\n }\r\n if (patch.keyboard !== undefined) {\r\n this.keyboardHandler?.setEnabled(patch.keyboard);\r\n }\r\n\r\n this.engine.requestRender();\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n resize(): void {\r\n const size = this.engine.dprManager.readContainerSize();\r\n if (size.width <= 0 || size.height <= 0) return;\r\n this.containerSizeCache = size;\r\n this.containerSizeCacheTime = Date.now();\r\n // Resize canvas layers immediately (don't wait for DPRManager's debounced callback)\r\n const dpr = this.engine.dprManager.getDpr();\r\n this.engine.layerManager.resize(size, dpr);\r\n // Check if viewport was at the end before resize\r\n const wasAtEnd = this.viewport.isAtEnd();\r\n this.viewport.resize(size.width, size.height);\r\n this.layoutManager.resize(size.width, size.height);\r\n this.updateViewportAndRender(wasAtEnd);\r\n this.eventBus.emit('resize', size);\r\n }\r\n\r\n destroy(): void {\r\n if (this.countdownInterval) clearInterval(this.countdownInterval);\r\n this.disableAutoSave();\r\n this.disconnectStream();\r\n if (this.onWindowKeyDown) {\r\n window.removeEventListener('keydown', this.onWindowKeyDown);\r\n this.onWindowKeyDown = null;\r\n }\r\n this.keyboardHandler = null;\r\n this.interactionManager.detach();\r\n this.tradingManager.destroy();\r\n this.animator.dispose();\r\n this.crosshairTooltip.destroy();\r\n this.pinnedTooltip.destroy();\r\n this.replayManager.dispose();\r\n this.undoRedoManager.clear();\r\n this.engine.destroy();\r\n this.eventBus.destroy();\r\n this.container.innerHTML = '';\r\n }\r\n\r\n // --- Internal ---\r\n\r\n private createChartRenderer(type: ChartType): ChartRendererInterface {\r\n return createRendererFor(type);\r\n }\r\n\r\n /** Cached display data. Invalidated when raw data or chart type changes. */\r\n private getDisplayData(): DataSeries {\r\n if (this.displayDataCache) return this.displayDataCache;\r\n const raw = this.dataManager.getData();\r\n if (raw.length === 0) return raw;\r\n const result = transformDisplayData(this.options.chartType, raw);\r\n this.displayDataCache = result;\r\n return result;\r\n }\r\n\r\n /** Lightweight render for streaming updates. No layout resolve, no indicator recalc. */\r\n private scheduleRender(): void {\r\n if (this.renderScheduled) return;\r\n this.renderScheduled = true;\r\n requestAnimationFrame(() => {\r\n this.renderScheduled = false;\r\n const displayData = this.getDisplayData();\r\n this.viewport.updateData(displayData, this.options.autoScale !== false);\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n });\r\n }\r\n\r\n /** Full update: resolve layout, update viewport, sync context, request render. */\r\n private updateViewportAndRender(scrollToEnd = false): void {\r\n // Invalidate layout cache\r\n this.resolvedLayoutCache = null;\r\n this.panelInfoCache = null;\r\n\r\n const resolved = this.getResolvedLayout();\r\n this.viewport.setChartRect(resolved.mainChartRect);\r\n\r\n const displayData = this.getDisplayData();\r\n this.viewport.updateData(displayData, this.options.autoScale !== false);\r\n\r\n // Baseline for percentage / indexed-to-100 axis labels: the close of the\r\n // first visible bar. Cheap to set every frame; ignored by other modes.\r\n if (displayData.length > 0) {\r\n const vs = this.viewport.getState();\r\n const baseIdx = Math.max(0, Math.min(vs.visibleRange.from, displayData.length - 1));\r\n this.viewport.setScaleBaseline(displayData[baseIdx]?.close);\r\n }\r\n\r\n // Expand price range to include overlay indicator values (BB, Ichimoku, etc.)\r\n if (this.options.autoScale !== false) {\r\n const vs = this.viewport.getState();\r\n const overlayRange = this.indicatorEngine.getOverlayPriceRange(\r\n vs.visibleRange.from,\r\n Math.min(vs.visibleRange.to, displayData.length - 1),\r\n );\r\n if (overlayRange) {\r\n const current = vs.priceRange;\r\n const expandedMin = Math.min(current.min, overlayRange.min);\r\n const expandedMax = Math.max(current.max, overlayRange.max);\r\n if (expandedMin < current.min || expandedMax > current.max) {\r\n const range = expandedMax - expandedMin || 1;\r\n this.viewport.setPriceRange(\r\n expandedMin - range * 0.02,\r\n expandedMax + range * 0.02,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Scroll to end AFTER updateData so dataLength is current\r\n if (scrollToEnd) this.viewport.scrollToEnd();\r\n\r\n this.syncRenderContext();\r\n this.engine.requestRender();\r\n }\r\n\r\n private getResolvedLayout() {\r\n if (!this.resolvedLayoutCache) {\r\n this.resolvedLayoutCache = this.layoutManager.resolve();\r\n }\r\n return this.resolvedLayoutCache;\r\n }\r\n\r\n /** Cache container size for 500ms to avoid layout thrashing on rapid calls */\r\n private cachedContainerSize(): { width: number; height: number } {\r\n const now = Date.now();\r\n if (!this.containerSizeCache || now - this.containerSizeCacheTime > 500) {\r\n this.containerSizeCache = this.engine.dprManager.getContainerSize();\r\n this.containerSizeCacheTime = now;\r\n }\r\n return this.containerSizeCache;\r\n }\r\n\r\n private buildPanelRenderInfos(): import('@tradecanvas/core').PanelRenderInfo[] {\r\n if (this.panelInfoCache) return this.panelInfoCache;\r\n\r\n const resolved = this.getResolvedLayout();\r\n const mainVP = this.viewport.getState();\r\n\r\n const { from, to } = mainVP.visibleRange;\r\n const panels = resolved.panels.map((panel) => {\r\n const output = this.indicatorEngine.getOutput(panel.config.id);\r\n const priceRange = computeIndicatorPriceRange(output, from, to);\r\n\r\n // Inset the indicator drawing area below the panel header (title + divider)\r\n const PANEL_HEADER_HEIGHT = 20;\r\n const insetRect = {\r\n x: panel.rect.x,\r\n y: panel.rect.y + PANEL_HEADER_HEIGHT,\r\n width: panel.rect.width,\r\n height: Math.max(0, panel.rect.height - PANEL_HEADER_HEIGHT),\r\n };\r\n\r\n return {\r\n instanceId: panel.config.id,\r\n rect: panel.rect,\r\n viewport: {\r\n ...mainVP,\r\n chartRect: insetRect,\r\n priceRange,\r\n },\r\n };\r\n });\r\n\r\n this.panelInfoCache = panels;\r\n return panels;\r\n }\r\n\r\n private syncRenderContext(): void {\r\n // Keep the pinned tooltip anchored to its bar through pans / zooms.\r\n if (this.pinnedTooltip.isPinned()) {\r\n this.pinnedTooltip.reposition(\r\n this.viewport.getState(),\r\n null,\r\n null,\r\n this.themeManager.getTheme(),\r\n );\r\n }\r\n\r\n const resolved = this.getResolvedLayout();\r\n const panels = this.features.indicators ? this.buildPanelRenderInfos() : [];\r\n\r\n // Compute where the time axis should render: below main chart + all bottom panels\r\n const bottomPanelHeight = resolved.panels\r\n .filter(p => p.config.position === 'bottom')\r\n .reduce((sum, p) => sum + p.rect.height, 0);\r\n const timeAxisY = resolved.mainChartRect.y + resolved.mainChartRect.height + bottomPanelHeight;\r\n\r\n const displayData = this.getDisplayData();\r\n this.engine.setRenderContext({\r\n chartRenderer: this.chartRenderer,\r\n gridRenderer: this.features.grid ? this.gridRenderer : null,\r\n priceAxis: this.features.priceAxis ? this.priceAxis : null,\r\n timeAxis: this.features.timeAxis ? this.timeAxis : null,\r\n crosshairHandler: this.features.crosshair ? this.crosshairHandler : null,\r\n indicatorEngine: this.features.indicators ? this.indicatorEngine : null,\r\n drawingRenderer: this.features.drawings ? this.drawingRenderer : null,\r\n tradingRenderer: this.features.trading ? this.tradingRenderer : null,\r\n currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine,\r\n chartLegend: this.features.legend ? this.chartLegend : null,\r\n volumeRenderer: this.features.volume ? this.volumeRenderer : null,\r\n volumeProfile: this.volumeProfile,\r\n marketProfile: this.marketProfile,\r\n depthHeatmap: this.depthHeatmap,\r\n periodLevels: this.periodLevels,\r\n pivotMarkers: this.pivotMarkers,\r\n watermark: this.features.watermark ? this.watermark : null,\r\n barCountdown: this.barCountdown,\r\n sessionBreaks: this.sessionBreaks,\r\n sessionShading: this.sessionShading,\r\n compareRenderer: this.compareRenderer,\r\n alertManager: this.features.alerts ? this.alertManager : null,\r\n measureOverlay: this.measureOverlay,\r\n signalMarkerManager: this.signalMarkerManager,\r\n tradeZoneManager: this.tradeZoneManager,\r\n panels,\r\n priceLimits: this.buildPriceLimits(),\r\n timeAxisY,\r\n // Attach data to the viewport so drawings/indicators can treat\r\n // `anchor.time` as a real timestamp and convert via timestampToBarIndex.\r\n viewport: { ...this.viewport.getState(), data: displayData },\r\n theme: this.themeManager.getTheme(),\r\n data: displayData,\r\n numberLocale: this.numberLocale,\r\n });\r\n }\r\n\r\n private buildPriceLimits() {\r\n if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null;\r\n const limits = computePriceLimits(this.marketConfig.priceLimits.referencePrice, this.marketConfig);\r\n if (!limits) return null;\r\n return {\r\n ...limits,\r\n colors: this.marketConfig.colorScheme ? {\r\n ceiling: this.marketConfig.colorScheme.ceiling,\r\n floor: this.marketConfig.colorScheme.floor,\r\n reference: this.marketConfig.colorScheme.reference,\r\n } : undefined,\r\n };\r\n }\r\n}\r\n","import type { OHLCBar, DataSeries } from '@tradecanvas/commons';\n\n/**\n * Best-effort parser for OHLCV CSV / JSON drops.\n *\n * Recognises:\n * - CSV (header-driven, comma / semicolon / tab delimiters)\n * - JSON array of objects (`[{ time, open, high, low, close, volume }]`)\n * - JSON array of arrays (`[[time, open, high, low, close, volume]]`)\n *\n * Time columns auto-detect ISO strings, unix-seconds, and unix-ms. Returned\n * bars are sorted ascending by time and de-duplicated on collision.\n */\nexport interface ParseResult {\n data: DataSeries;\n /** Total rows seen — useful for \"imported 4321 of 5000 rows\" style toasts. */\n rowCount: number;\n /** Rows skipped because of missing/invalid required fields. */\n skipped: number;\n}\n\nconst TIME_KEYS = ['time', 'timestamp', 'date', 'datetime', 't'];\nconst OPEN_KEYS = ['open', 'o'];\nconst HIGH_KEYS = ['high', 'h'];\nconst LOW_KEYS = ['low', 'l'];\nconst CLOSE_KEYS = ['close', 'c'];\nconst VOL_KEYS = ['volume', 'vol', 'v'];\n\nexport function parseOHLCV(text: string): ParseResult {\n const trimmed = text.trim();\n if (!trimmed) return { data: [], rowCount: 0, skipped: 0 };\n\n if (trimmed[0] === '[' || trimmed[0] === '{') {\n return parseJson(trimmed);\n }\n return parseCsv(trimmed);\n}\n\nfunction parseJson(text: string): ParseResult {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (e) {\n throw new Error(`Invalid JSON: ${(e as Error).message}`);\n }\n if (!Array.isArray(raw)) {\n throw new Error('Expected a JSON array of OHLCV rows');\n }\n const bars: OHLCBar[] = [];\n let skipped = 0;\n for (const row of raw) {\n const bar = Array.isArray(row) ? coerceArrayRow(row) : coerceObjectRow(row as Record<string, unknown>);\n if (bar) bars.push(bar); else skipped++;\n }\n return finalize(bars, raw.length, skipped);\n}\n\nfunction parseCsv(text: string): ParseResult {\n const lines = text.split(/\\r?\\n/).filter(l => l.trim().length > 0);\n if (lines.length === 0) return { data: [], rowCount: 0, skipped: 0 };\n\n const delimiter = detectDelimiter(lines[0]);\n const header = splitLine(lines[0], delimiter).map(h => h.trim().toLowerCase());\n\n // If the first row doesn't look like a header (all numeric), assume the\n // canonical order: time, open, high, low, close, volume.\n const looksLikeHeader = header.some(h => isNaN(Number(h)) && h.length > 0);\n const colIdx = looksLikeHeader\n ? buildColumnMap(header)\n : { time: 0, open: 1, high: 2, low: 3, close: 4, volume: 5 };\n\n if (colIdx.time < 0 || colIdx.open < 0 || colIdx.high < 0 || colIdx.low < 0 || colIdx.close < 0) {\n throw new Error('CSV is missing required column(s): time, open, high, low, close');\n }\n\n const bars: OHLCBar[] = [];\n let skipped = 0;\n for (let i = looksLikeHeader ? 1 : 0; i < lines.length; i++) {\n const cols = splitLine(lines[i], delimiter);\n const time = parseTimeCell(cols[colIdx.time]);\n // Empty cells parse to `Number('') === 0`, which would silently produce\n // bogus zero bars. Treat empty as invalid up-front so the row gets\n // skipped instead of polluting the series.\n const open = numCell(cols[colIdx.open]);\n const high = numCell(cols[colIdx.high]);\n const low = numCell(cols[colIdx.low]);\n const close = numCell(cols[colIdx.close]);\n const volume = colIdx.volume >= 0 ? Number(cols[colIdx.volume]) : 0;\n if (time === null || ![open, high, low, close].every(Number.isFinite)) {\n skipped++;\n continue;\n }\n bars.push({ time, open: open!, high: high!, low: low!, close: close!, volume: Number.isFinite(volume) ? volume : 0 });\n }\n\n return finalize(bars, lines.length - (looksLikeHeader ? 1 : 0), skipped);\n}\n\nfunction detectDelimiter(headerLine: string): string {\n const counts: Record<string, number> = { ',': 0, ';': 0, '\\t': 0, '|': 0 };\n for (const ch of headerLine) {\n if (ch in counts) counts[ch]++;\n }\n let best = ',';\n let bestCount = 0;\n for (const [d, n] of Object.entries(counts)) {\n if (n > bestCount) { best = d; bestCount = n; }\n }\n return best;\n}\n\n/** Minimal CSV splitter — handles double-quoted fields, doesn't try to be RFC-perfect. */\nfunction splitLine(line: string, delimiter: string): string[] {\n const out: string[] = [];\n let buf = '';\n let inQuote = false;\n for (let i = 0; i < line.length; i++) {\n const ch = line[i];\n if (ch === '\"') {\n if (inQuote && line[i + 1] === '\"') { buf += '\"'; i++; }\n else inQuote = !inQuote;\n } else if (ch === delimiter && !inQuote) {\n out.push(buf);\n buf = '';\n } else {\n buf += ch;\n }\n }\n out.push(buf);\n return out;\n}\n\nfunction buildColumnMap(header: string[]): { time: number; open: number; high: number; low: number; close: number; volume: number } {\n const find = (keys: string[]) => header.findIndex(h => keys.includes(h));\n return {\n time: find(TIME_KEYS),\n open: find(OPEN_KEYS),\n high: find(HIGH_KEYS),\n low: find(LOW_KEYS),\n close: find(CLOSE_KEYS),\n volume: find(VOL_KEYS),\n };\n}\n\nfunction coerceObjectRow(row: Record<string, unknown>): OHLCBar | null {\n const get = (keys: string[]) => {\n for (const k of keys) {\n if (row[k] !== undefined) return row[k];\n const upper = k.toUpperCase();\n if (row[upper] !== undefined) return row[upper];\n }\n return undefined;\n };\n const time = parseTimeCell(String(get(TIME_KEYS) ?? ''));\n const open = Number(get(OPEN_KEYS));\n const high = Number(get(HIGH_KEYS));\n const low = Number(get(LOW_KEYS));\n const close = Number(get(CLOSE_KEYS));\n const volume = Number(get(VOL_KEYS) ?? 0);\n if (time === null || ![open, high, low, close].every(Number.isFinite)) return null;\n return { time, open, high, low, close, volume: Number.isFinite(volume) ? volume : 0 };\n}\n\nfunction coerceArrayRow(row: unknown[]): OHLCBar | null {\n if (row.length < 5) return null;\n const time = parseTimeCell(String(row[0]));\n const open = Number(row[1]);\n const high = Number(row[2]);\n const low = Number(row[3]);\n const close = Number(row[4]);\n const volume = row.length >= 6 ? Number(row[5]) : 0;\n if (time === null || ![open, high, low, close].every(Number.isFinite)) return null;\n return { time, open, high, low, close, volume: Number.isFinite(volume) ? volume : 0 };\n}\n\n/**\n * Returns milliseconds since epoch, or null if unparseable. Heuristic:\n * - numeric < 1e12 → seconds, multiply by 1000\n * - numeric >= 1e12 → already ms\n * - non-numeric → Date.parse fallback (handles ISO, RFC 2822, etc.)\n */\nfunction numCell(raw: string | undefined): number {\n if (raw === undefined || raw.trim() === '') return NaN;\n return Number(raw);\n}\n\nfunction parseTimeCell(raw: string): number | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n const asNum = Number(trimmed);\n if (Number.isFinite(asNum) && asNum > 0) {\n return asNum < 1e12 ? asNum * 1000 : asNum;\n }\n const parsed = Date.parse(trimmed);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction finalize(bars: OHLCBar[], rowCount: number, skipped: number): ParseResult {\n bars.sort((a, b) => a.time - b.time);\n // De-dup on identical time — keep the last (later rows are typically more\n // authoritative if the source updated a bar after publishing it).\n const out: OHLCBar[] = [];\n for (const bar of bars) {\n if (out.length > 0 && out[out.length - 1].time === bar.time) {\n out[out.length - 1] = bar;\n } else {\n out.push(bar);\n }\n }\n return { data: out, rowCount, skipped };\n}\n","import type { DataSeries } from '@tradecanvas/commons';\nimport { parseOHLCV, type ParseResult } from './parseOHLCV.js';\n\nexport interface DragDropImporterCallbacks {\n /** Called with the parsed series. Hook into chart.setData() here. */\n onData: (data: DataSeries, result: ParseResult, file: File) => void;\n /** Called when parsing throws. Hook a toast/banner here. */\n onError?: (err: Error, file: File) => void;\n}\n\n/**\n * Hooks `dragover` / `drop` on a host element so users can drop a CSV / JSON\n * file onto the chart and get it loaded. A subtle dashed-outline overlay\n * shows up during the drag for visual confirmation.\n *\n * The host owns calling `chart.setData()` via the `onData` callback — the\n * importer stays decoupled from Chart so it can be reused in other surfaces\n * (backtester UI, comparison views, etc.).\n */\nexport class DragDropImporter {\n private host: HTMLElement;\n private overlay: HTMLDivElement | null = null;\n private callbacks: DragDropImporterCallbacks;\n private bound: { dragenter: (e: DragEvent) => void; dragover: (e: DragEvent) => void; dragleave: (e: DragEvent) => void; drop: (e: DragEvent) => void };\n private depth = 0;\n\n constructor(host: HTMLElement, callbacks: DragDropImporterCallbacks) {\n this.host = host;\n this.callbacks = callbacks;\n this.bound = {\n dragenter: (e) => this.onDragEnter(e),\n dragover: (e) => this.onDragOver(e),\n dragleave: (e) => this.onDragLeave(e),\n drop: (e) => this.onDrop(e),\n };\n }\n\n attach(): void {\n this.host.addEventListener('dragenter', this.bound.dragenter);\n this.host.addEventListener('dragover', this.bound.dragover);\n this.host.addEventListener('dragleave', this.bound.dragleave);\n this.host.addEventListener('drop', this.bound.drop);\n }\n\n detach(): void {\n this.host.removeEventListener('dragenter', this.bound.dragenter);\n this.host.removeEventListener('dragover', this.bound.dragover);\n this.host.removeEventListener('dragleave', this.bound.dragleave);\n this.host.removeEventListener('drop', this.bound.drop);\n this.hideOverlay();\n }\n\n private onDragEnter(e: DragEvent): void {\n if (!hasFiles(e)) return;\n e.preventDefault();\n this.depth++;\n this.showOverlay();\n }\n\n private onDragOver(e: DragEvent): void {\n if (!hasFiles(e)) return;\n e.preventDefault();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n }\n\n private onDragLeave(e: DragEvent): void {\n if (!hasFiles(e)) return;\n this.depth = Math.max(0, this.depth - 1);\n if (this.depth === 0) this.hideOverlay();\n }\n\n private async onDrop(e: DragEvent): Promise<void> {\n e.preventDefault();\n this.depth = 0;\n this.hideOverlay();\n\n const file = e.dataTransfer?.files?.[0];\n if (!file) return;\n\n try {\n const text = await file.text();\n const result = parseOHLCV(text);\n if (result.data.length === 0) {\n throw new Error(`No valid OHLCV rows found in \"${file.name}\"`);\n }\n this.callbacks.onData(result.data, result, file);\n } catch (err) {\n this.callbacks.onError?.(err as Error, file);\n }\n }\n\n private showOverlay(): void {\n if (this.overlay) return;\n this.overlay = document.createElement('div');\n Object.assign(this.overlay.style, {\n position: 'absolute',\n inset: '8px',\n zIndex: '90',\n pointerEvents: 'none',\n borderRadius: '10px',\n border: '2px dashed var(--tcw-accent, #4f88ff)',\n background: 'rgba(79, 136, 255, 0.06)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--tcw-accent, #4f88ff)',\n fontSize: '14px',\n fontWeight: '600',\n letterSpacing: '-0.005em',\n fontFamily: 'inherit',\n backdropFilter: 'blur(2px)',\n });\n this.overlay.textContent = 'Drop CSV or JSON to load chart data';\n // The host needs `position: relative` for absolute inset to work; Chart\n // already sets this, but guard for arbitrary hosts.\n const cs = getComputedStyle(this.host);\n if (cs.position === 'static') this.host.style.position = 'relative';\n this.host.appendChild(this.overlay);\n }\n\n private hideOverlay(): void {\n this.overlay?.remove();\n this.overlay = null;\n }\n}\n\nfunction hasFiles(e: DragEvent): boolean {\n return e.dataTransfer?.types?.includes('Files') ?? false;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ let e=require(`@tradecanvas/commons`),t=require(`@tradecanvas/core`);function n(e){switch(e){case`candlestick`:case`heikinAshi`:case`lineBreak`:case`rangeBars`: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`kagi`:return new t.KagiRenderer;case`pointAndFigure`:return new t.PointAndFigureRenderer;case`volumeCandles`:return new t.VolumeCandleRenderer;case`equivolume`:return new t.EquivolumeRenderer;case`hlcArea`:return new t.HLCAreaRenderer;case`stepLine`:return new t.StepLineRenderer;case`lineWithMarkers`:return new t.LineWithMarkersRenderer;default:return new t.CandlestickRenderer}}function r(e,n){if(n.length===0)return n;switch(e){case`heikinAshi`:return(0,t.toHeikinAshi)(n);case`renko`:return(0,t.toRenko)(n,{brickSize:0,useATR:!0,atrPeriod:14});case`lineBreak`:return(0,t.toLineBreak)(n,3);case`kagi`:return(0,t.toKagi)(n,4);case`pointAndFigure`:return(0,t.toPointAndFigure)(n,i(n)*.01,3);case`rangeBars`:return(0,t.toRangeBars)(n,{rangeSize:i(n)*.005});default:return n}}function i(e){let t=0;for(let n of e)t+=n.close;return t/e.length}var a={min:0,max:100},o=.1;function s(e,t,n){if(!e)return{...a};let r=1/0,i=-1/0,s=0;for(let[,a]of e.values){if(s>=t&&s<=n)for(let e in a){let t=a[e];t!==void 0&&Number.isFinite(t)&&(t<r&&(r=t),t>i&&(i=t))}s++}if(r===1/0)return{...a};let c=i-r||1;return{min:r-c*o,max:i+c*o}}var c=class{timer=null;delayMs=0;key=null;constructor(e){this.save=e}enable(e,t){this.key=e,this.delayMs=t}disable(){this.key=null,this.delayMs=0,this.cancel()}schedule(){this.delayMs<=0||!this.key||(this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=null,this.key&&this.save(this.key)},this.delayMs))}cancel(){this.timer&&=(clearTimeout(this.timer),null)}isEnabled(){return this.delayMs>0&&this.key!==null}hasPending(){return this.timer!==null}};function l(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 u(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 d=class{data=[];getData(){return this.data}setData(e){this.data=e.filter(l).map(u)}appendBar(e){l(e)&&this.data.push(u(e))}updateLastBar(e){if(!l(e))return;let t=u(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=[]}},f=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}}},p=200,m=80,h=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?p:e.DEFAULT_PANEL_HEIGHT),minSize:i?m: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?p:e.DEFAULT_PANEL_HEIGHT,r.minSize=i?m: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}},g=class{constructor(e){this.indicatorEngine=e}registerIndicator(e){this.indicatorEngine.register(e)}},_=class{static version=`0.7.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;sessionShading;compareRenderer;countdownInterval=null;volumeRenderer;volumeProfile;marketProfile;depthHeatmap;periodLevels;pivotMarkers;alertManager;signalMarkerManager;tradeZoneManager;measureOverlay;replayManager;undoRedoManager;autoSaveScheduler=new c(e=>this.saveState(e));animator;crosshairTooltip;pinnedTooltip;interactionManager;crosshairHandler;chartRenderer;gridRenderer;priceAxis;timeAxis;options;features;marketConfig=null;container;currentPriceLine;numberLocale;keyboardHandler=null;onWindowKeyDown=null;currentSymbol=``;constructor(n,r){this.container=n,this.options=r,this.numberLocale=r.numberLocale??`en-US`;let i=r.features??{};this.features={drawings:i.drawings??!0,drawingTools:i.drawingTools??[],drawingMagnet:i.drawingMagnet??!0,drawingUndoRedo:i.drawingUndoRedo??!0,trading:i.trading??!0,tradingContextMenu:i.tradingContextMenu??!0,indicators:i.indicators??!0,indicatorIds:i.indicatorIds??[],panning:i.panning??!0,zooming:i.zooming??!0,crosshair:i.crosshair??!0,keyboard:i.keyboard??!0,priceAxis:i.priceAxis??!0,timeAxis:i.timeAxis??!0,grid:i.grid??r.grid?.visible??!0,legend:i.legend??!0,volume:i.volume??!0,watermark:i.watermark??!0,saveLoad:i.saveLoad??!0,screenshot:i.screenshot??!0,alerts:i.alerts??!0,replay:i.replay??!0,sessionBreaks:i.sessionBreaks??!0,barCountdown:i.barCountdown??!0,compareSymbols:i.compareSymbols??!0,dataExport:i.dataExport??!0,logScale:i.logScale??!0,timeframes:i.timeframes??[],defaultTimeframeFavorites:i.defaultTimeframeFavorites??[]},n.style.position=`relative`,n.style.overflow=`hidden`,n.tabIndex=0,n.style.outline=`none`,this.dataManager=new d,this.themeManager=new f(r.theme),this.layoutManager=new h,this.indicatorEngine=new t.IndicatorEngine,this.pluginManager=new g(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({enabled:this.features.trading,contextMenu:{enabled:this.features.tradingContextMenu}}),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 a=this.engine.dprManager.getContainerSize();if(this.viewport=new t.Viewport(a.width,a.height,r.minBarSpacing??2,r.maxBarSpacing??30,r.rightMargin??5),this.layoutManager.resize(a.width,a.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.pinnedTooltip.isPinned()&&this.pinnedTooltip.reposition(this.viewport.getState(),r??null,e,this.themeManager.getTheme()),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.volumeProfile=new t.VolumeProfileRenderer,this.marketProfile=new t.MarketProfileRenderer,this.depthHeatmap=new t.DepthHeatmapRenderer,this.periodLevels=new t.PeriodLevelsRenderer,this.pivotMarkers=new t.PivotMarkersRenderer,this.barCountdown=new t.BarCountdown,this.sessionBreaks=new t.SessionBreaks,this.sessionShading=new t.SessionShading,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.pinnedTooltip=new t.PinnedTooltip,this.pinnedTooltip.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=>{let t={id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered};this.eventBus.emit(`alertTriggered`,t),this.eventBus.emit(`dataUpdate`,{alert:`triggered`,alertId:e.id,price:e.price,message:e.message})}),this.alertManager.on(`added`,e=>{this.eventBus.emit(`alertAdd`,{id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered})}),this.alertManager.on(`removed`,e=>{this.eventBus.emit(`alertRemove`,{id:e})}),this.alertManager.on(`updated`,e=>{this.eventBus.emit(`alertUpdate`,{id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered})}),this.signalMarkerManager=new t.SignalMarkerManager,this.signalMarkerManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.signalMarkerManager.setDataGetter(()=>this.dataManager.getData()),this.signalMarkerManager.on(`added`,e=>{this.eventBus.emit(`signalMarkerAdd`,{id:e.id,source:e.source,direction:e.direction})}),this.signalMarkerManager.on(`removed`,e=>{this.eventBus.emit(`signalMarkerRemove`,{id:e})}),this.tradeZoneManager=new t.TradeZoneManager,this.tradeZoneManager.setRequestRender(()=>this.engine.requestRender(e.LayerType.Overlay)),this.tradeZoneManager.setDataGetter(()=>this.dataManager.getData()),this.tradeZoneManager.on(`added`,e=>{this.eventBus.emit(`tradeZoneAdd`,{id:e.id,direction:e.direction})}),this.tradeZoneManager.on(`removed`,e=>{this.eventBus.emit(`tradeZoneRemove`,{id:e})}),this.replayManager=new t.ReplayManager,this.measureOverlay=new t.MeasureOverlay,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()}));let e=new t.AxisDragHandler(e=>{this.options.autoScale=!1,this.viewport.scalePriceRange(e),this.syncRenderContext(),this.engine.requestRender()},e=>{let t=this.viewport.getState().chartRect.width;this.viewport.zoom(1/e-1,t/2),this.updateViewportAndRender()});this.interactionManager.setAxisDragHandler(e,()=>this.viewport.getState(),e=>{e===`price`?(this.options.autoScale=!0,this.updateViewportAndRender()):this.fitContent()})}if(this.features.crosshair&&this.interactionManager.setCrosshairHandler(this.crosshairHandler),this.features.drawings&&this.interactionManager.setDrawingManager(this.drawingManager,()=>({...this.viewport.getState(),data:this.getDisplayData()})),this.features.trading&&this.interactionManager.setTradingManager(this.tradingManager,()=>({...this.viewport.getState(),data:this.getDisplayData()})),this.features.alerts){let e=new t.AlertDragHandler(this.alertManager,()=>this.viewport.getState());this.interactionManager.setAlertDragHandler(e)}this.interactionManager.setAltClickHandler(t=>{let n=this.getDisplayData();if(n.length===0)return;let r=this.viewport.getState(),i=r.barWidth+r.barSpacing,a=Math.round((r.offset+t.x)/i);a<0||a>=n.length||(this.pinnedTooltip.isPinned()&&this.pinnedTooltip.getPinnedIndex()===a?this.pinnedTooltip.unpin():this.pinnedTooltip.pin(n[a],a,this.themeManager.getTheme()),this.pinnedTooltip.reposition(this.viewport.getState(),this.dataManager.getData()[a]??null,a,this.themeManager.getTheme()),this.engine.requestRender(e.LayerType.Overlay))}),this.interactionManager.setClickHandler(e=>{let n=this.getDisplayData();if(this.eventBus.emit(`click`,{x:e.x,y:e.y}),n.length===0)return;let r=(0,t.xToBarIndex)(e.x,this.viewport.getState());r<0||r>=n.length||this.eventBus.emit(`barClick`,{bar:n[r],barIndex:r,point:e})}),this.interactionManager.setEscapeHandler(()=>{if(this.features.trading&&this.tradingManager.isBracketActive()){this.tradingManager.cancelBracket(),this.eventBus.emit(`dataUpdate`,{bracket:`cancelled`});return}this.pinnedTooltip.isPinned()&&(this.pinnedTooltip.unpin(),this.engine.requestRender(e.LayerType.Overlay))}),this.interactionManager.setConfirmHandler(()=>this.features.trading&&this.tradingManager.isBracketActive()?(this.tradingManager.confirmBracket(),!0):!1),this.interactionManager.setMeasureHandlers({begin:e=>{this.measureOverlay.begin(e,this.viewport.getState(),this.getDisplayData())},move:e=>{this.measureOverlay.update(e,this.viewport.getState(),this.getDisplayData())},end:()=>{this.measureOverlay.end()}}),this.interactionManager.setOverlayDirtyCallback(()=>{this.engine.requestRender(e.LayerType.Overlay),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.alertManager.clearLastValues(),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()}appendBars(e){if(e.length!==0){for(let t of e)this.dataManager.appendBar(t);this.displayDataCache=null,this.indicatorEngine.recalculateAll(this.dataManager.getData()),this.crosshairHandler.setData(this.dataManager.getData()),this.updateViewportAndRender(this.viewport.isAtEnd())}}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)}getDrawingStyle(){return this.drawingManager.getActiveStyle()}getSelectedDrawingId(){return this.drawingManager.getSelectedDrawingId()}setSelectedDrawingStyle(e,t){return this.drawingManager.setSelectedDrawingStyle(e,t)}getDrawings(){return this.drawingManager.getDrawings()}setDrawings(e){this.drawingManager.setDrawings(e)}addDrawing(e){if(!this.features.drawings)return null;let t=this.drawingManager.addDrawing(e);return this.scheduleAutoSave(),t}autoFib(){if(!this.features.drawings)return null;let e=this.getDisplayData(),n=this.viewport.getState(),r=(0,t.findDominantSwing)(e,n.visibleRange.from,n.visibleRange.to);return r?this.addDrawing({type:`fibRetracement`,anchors:[r[0],r[1]]}):null}removeDrawing(e){this.drawingManager.removeDrawing(e)}setDrawingVisible(e,t){this.drawingManager.setDrawingVisible(e,t)}setDrawingLocked(e,t){this.drawingManager.setDrawingLocked(e,t)}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.autoSaveScheduler.enable(e,t)}disableAutoSave(){this.autoSaveScheduler.disable()}scheduleAutoSave(){this.autoSaveScheduler.schedule()}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()}setIndicatorVisible(e,t){this.indicatorEngine.setVisible(e,t)!==null&&this.updateViewportAndRender()}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)}startBracket(e,t){if(!this.features.trading)return!1;let n=this.dataManager.getData(),r=t??(n.length>0?n[n.length-1].close:null);return r===null?!1:(this.tradingManager.startBracket(e,r),!0)}cancelBracket(){this.features.trading&&this.tradingManager.cancelBracket()}confirmBracket(){return this.features.trading?this.tradingManager.confirmBracket():!1}isBracketActive(){return this.features.trading&&this.tradingManager.isBracketActive()}placeOrderIntent(e){this.features.trading&&this.eventBus.emit(`orderPlace`,e)}setPositions(e){this.features.trading&&this.tradingManager.setPositions(e)}setDepthData(e){this.features.trading&&this.tradingManager.setDepthData(e)}setCurrentPrice(e,t){this.tradingManager.setCurrentPrice(e),this.currentPriceLine.setPrice(e),this.scheduleRender(),this.features.alerts&&(this.alertManager.checkPrice(e),this.feedIndicatorAlerts())}feedIndicatorAlerts(){let e=this.alertManager.getAlerts(),t=this.dataManager.getData();if(t.length===0)return;let n=t.length-1,r=new Set;for(let t of e){if(t.channel===`price`||r.has(t.channel))continue;r.add(t.channel);let e=t.channel.indexOf(`:`);if(e<0)continue;let i=t.channel.slice(0,e),a=t.channel.slice(e+1),o=this.indicatorEngine.getOutput(i)?.series?.[n]?.[a];typeof o==`number`&&Number.isFinite(o)&&this.alertManager.checkChannel(t.channel,o)}}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,this.currentSymbol=n.symbol,await this.streamManager.connect(n);let r=(0,e.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&&(this.currentSymbol=e,await this.streamManager.switchTo(e,t))}async setTimeframe(e){if(!this.streamManager)throw Error(`No active stream. Call connect() first.`);await this.switchStream(this.currentSymbol,e)}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()}setScaleMode(e){this.viewport.setScaleMode(e),this.updateViewportAndRender()}getScaleMode(){return this.viewport.getScaleMode()}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()}setCrosshairPosition(t){t&&this.crosshairHandler.onPointerMove(t),this.engine.requestRender(e.LayerType.Overlay)}getData(){return this.dataManager.getData()}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)}setVolumeProfileVisible(t){this.volumeProfile.setVisible(t),this.engine.requestRender(e.LayerType.Main)}isVolumeProfileVisible(){return this.volumeProfile.isVisible()}setVolumeProfileConfig(t){t.buckets!==void 0&&this.volumeProfile.setBuckets(t.buckets),t.widthRatio!==void 0&&this.volumeProfile.setWidthRatio(t.widthRatio),t.opacity!==void 0&&this.volumeProfile.setOpacity(t.opacity),t.highlightPoC!==void 0&&this.volumeProfile.setHighlightPoC(t.highlightPoC),this.engine.requestRender(e.LayerType.Main)}setMarketProfileVisible(t){this.marketProfile.setVisible(t),this.engine.requestRender(e.LayerType.Main)}isMarketProfileVisible(){return this.marketProfile.isVisible()}setMarketProfileConfig(t){t.buckets!==void 0&&this.marketProfile.setBuckets(t.buckets),t.widthRatio!==void 0&&this.marketProfile.setWidthRatio(t.widthRatio),t.opacity!==void 0&&this.marketProfile.setOpacity(t.opacity),t.valueAreaPct!==void 0&&this.marketProfile.setValueAreaPct(t.valueAreaPct),t.highlightPoC!==void 0&&this.marketProfile.setHighlightPoC(t.highlightPoC),t.showStats!==void 0&&this.marketProfile.setShowStats(t.showStats),t.splitBySession!==void 0&&this.marketProfile.setSplitBySession(t.splitBySession),t.letters!==void 0&&this.marketProfile.setLetters(t.letters),this.engine.requestRender(e.LayerType.Main)}getMarketProfileStats(){return this.marketProfile.getStats()}setDepthHeatmapVisible(t){this.depthHeatmap.setVisible(t),this.engine.requestRender(e.LayerType.Main)}isDepthHeatmapVisible(){return this.depthHeatmap.isVisible()}setDepthHeatmapConfig(t){t.opacity!==void 0&&this.depthHeatmap.setOpacity(t.opacity),t.capacity!==void 0&&this.depthHeatmap.setCapacity(t.capacity),this.engine.requestRender(e.LayerType.Main)}pushDepthSnapshot(t){let n=this.dataManager.getData();n.length!==0&&(this.depthHeatmap.push(n[n.length-1].time,t),this.depthHeatmap.isVisible()&&this.engine.requestRender(e.LayerType.Main))}clearDepthHeatmap(){this.depthHeatmap.clear(),this.engine.requestRender(e.LayerType.Main)}setPeriodLevelsVisible(t){this.periodLevels.setVisible(t),this.engine.requestRender(e.LayerType.Main)}isPeriodLevelsVisible(){return this.periodLevels.isVisible()}setPeriodLevelsPeriod(t){this.periodLevels.setPeriod(t),this.engine.requestRender(e.LayerType.Main)}setTimezoneOffset(t){this.timeAxis.setTimezoneOffset(t),this.crosshairHandler.setTimezoneOffset(t),this.engine.requestRender(e.LayerType.UI),this.engine.requestRender(e.LayerType.Overlay)}setPivotMarkersVisible(t){this.pivotMarkers.setVisible(t),this.engine.requestRender(e.LayerType.Overlay)}isPivotMarkersVisible(){return this.pivotMarkers.isVisible()}setPivotMarkersConfig(t){(t.left!==void 0||t.right!==void 0)&&this.pivotMarkers.setStrength(t.left??5,t.right??t.left??5),t.showLabels!==void 0&&this.pivotMarkers.setShowLabels(t.showLabels),t.structureLabels!==void 0&&this.pivotMarkers.setStructureLabels(t.structureLabels),this.engine.requestRender(e.LayerType.Overlay)}setSessionShadingVisible(t){this.sessionShading.setVisible(t),this.engine.requestRender(e.LayerType.Background)}isSessionShadingVisible(){return this.sessionShading.isVisible()}setSessionShadingConfig(t){this.sessionShading.setConfig(t),this.engine.requestRender(e.LayerType.Background)}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)}setStatusText(t){this.chartLegend.setStatusText(t),this.engine.requestRender(e.LayerType.UI)}screenshot(e){this.features.screenshot&&t.Screenshot.download(this.container,e,this.themeManager.getTheme().background)}async copyScreenshot(){if(!this.features.screenshot)return!1;try{let e=await t.Screenshot.toBlob(this.container,this.themeManager.getTheme().background),n=globalThis.ClipboardItem;return!e||!navigator.clipboard?.write||!n?!1:(await navigator.clipboard.write([new n({"image/png":e})]),!0)}catch{return!1}}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,r=`price`,i){if(!this.features.alerts)return null;let a=this.alertManager.addAlert(e,t,n,!1,r,i);return this.scheduleAutoSave(),a}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)}addSignalMarker(e){return this.signalMarkerManager.addMarker(e)}removeSignalMarker(e){this.signalMarkerManager.removeMarker(e)}getSignalMarkers(){return this.signalMarkerManager.getMarkers()}setSignalMarkers(e){this.signalMarkerManager.setMarkers(e)}clearSignalMarkers(){this.signalMarkerManager.clearMarkers()}setSignalMarkerStyle(e){this.signalMarkerManager.setStyle(e)}addTradeZone(e){return this.tradeZoneManager.addZone(e)}updateTradeZone(e,t){this.tradeZoneManager.updateZone(e,t)}removeTradeZone(e){this.tradeZoneManager.removeZone(e)}getTradeZones(){return this.tradeZoneManager.getZones()}setTradeZones(e){this.tradeZoneManager.setZones(e)}clearTradeZones(){this.tradeZoneManager.clearZones()}setTradeZoneStyle(e){this.tradeZoneManager.setStyle(e)}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.pinnedTooltip.destroy(),this.replayManager.dispose(),this.undoRedoManager.clear(),this.engine.destroy(),this.eventBus.destroy(),this.container.innerHTML=``}createChartRenderer(e){return n(e)}getDisplayData(){if(this.displayDataCache)return this.displayDataCache;let e=this.dataManager.getData();if(e.length===0)return e;let t=r(this.options.chartType,e);return this.displayDataCache=t,t}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),n.length>0){let e=this.viewport.getState(),t=Math.max(0,Math.min(e.visibleRange.from,n.length-1));this.viewport.setScaleBaseline(n[t]?.close)}if(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(),{from:n,to:r}=t.visibleRange,i=e.panels.map(e=>{let i=s(this.indicatorEngine.getOutput(e.config.id),n,r),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:i}}});return this.panelInfoCache=i,i}syncRenderContext(){this.pinnedTooltip.isPinned()&&this.pinnedTooltip.reposition(this.viewport.getState(),null,null,this.themeManager.getTheme());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,i=this.getDisplayData();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,volumeProfile:this.volumeProfile,marketProfile:this.marketProfile,depthHeatmap:this.depthHeatmap,periodLevels:this.periodLevels,pivotMarkers:this.pivotMarkers,watermark:this.features.watermark?this.watermark:null,barCountdown:this.barCountdown,sessionBreaks:this.sessionBreaks,sessionShading:this.sessionShading,compareRenderer:this.compareRenderer,alertManager:this.features.alerts?this.alertManager:null,measureOverlay:this.measureOverlay,signalMarkerManager:this.signalMarkerManager,tradeZoneManager:this.tradeZoneManager,panels:t,priceLimits:this.buildPriceLimits(),timeAxisY:r,viewport:{...this.viewport.getState(),data:i},theme:this.themeManager.getTheme(),data:i,numberLocale:this.numberLocale})}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}},v=[`time`,`timestamp`,`date`,`datetime`,`t`],y=[`open`,`o`],b=[`high`,`h`],x=[`low`,`l`],S=[`close`,`c`],C=[`volume`,`vol`,`v`];function w(e){let t=e.trim();return t?t[0]===`[`||t[0]===`{`?T(t):E(t):{data:[],rowCount:0,skipped:0}}function T(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`Invalid JSON: ${e.message}`)}if(!Array.isArray(t))throw Error(`Expected a JSON array of OHLCV rows`);let n=[],r=0;for(let e of t){let t=Array.isArray(e)?j(e):A(e);t?n.push(t):r++}return P(n,t.length,r)}function E(e){let t=e.split(/\r?\n/).filter(e=>e.trim().length>0);if(t.length===0)return{data:[],rowCount:0,skipped:0};let n=D(t[0]),r=O(t[0],n).map(e=>e.trim().toLowerCase()),i=r.some(e=>isNaN(Number(e))&&e.length>0),a=i?k(r):{time:0,open:1,high:2,low:3,close:4,volume:5};if(a.time<0||a.open<0||a.high<0||a.low<0||a.close<0)throw Error(`CSV is missing required column(s): time, open, high, low, close`);let o=[],s=0;for(let e=+!!i;e<t.length;e++){let r=O(t[e],n),i=N(r[a.time]),c=M(r[a.open]),l=M(r[a.high]),u=M(r[a.low]),d=M(r[a.close]),f=a.volume>=0?Number(r[a.volume]):0;if(i===null||![c,l,u,d].every(Number.isFinite)){s++;continue}o.push({time:i,open:c,high:l,low:u,close:d,volume:Number.isFinite(f)?f:0})}return P(o,t.length-+!!i,s)}function D(e){let t={",":0,";":0," ":0,"|":0};for(let n of e)n in t&&t[n]++;let n=`,`,r=0;for(let[e,i]of Object.entries(t))i>r&&(n=e,r=i);return n}function O(e,t){let n=[],r=``,i=!1;for(let a=0;a<e.length;a++){let o=e[a];o===`"`?i&&e[a+1]===`"`?(r+=`"`,a++):i=!i:o===t&&!i?(n.push(r),r=``):r+=o}return n.push(r),n}function k(e){let t=t=>e.findIndex(e=>t.includes(e));return{time:t(v),open:t(y),high:t(b),low:t(x),close:t(S),volume:t(C)}}function A(e){let t=t=>{for(let n of t){if(e[n]!==void 0)return e[n];let t=n.toUpperCase();if(e[t]!==void 0)return e[t]}},n=N(String(t(v)??``)),r=Number(t(y)),i=Number(t(b)),a=Number(t(x)),o=Number(t(S)),s=Number(t(C)??0);return n===null||![r,i,a,o].every(Number.isFinite)?null:{time:n,open:r,high:i,low:a,close:o,volume:Number.isFinite(s)?s:0}}function j(e){if(e.length<5)return null;let t=N(String(e[0])),n=Number(e[1]),r=Number(e[2]),i=Number(e[3]),a=Number(e[4]),o=e.length>=6?Number(e[5]):0;return t===null||![n,r,i,a].every(Number.isFinite)?null:{time:t,open:n,high:r,low:i,close:a,volume:Number.isFinite(o)?o:0}}function M(e){return e===void 0||e.trim()===``?NaN:Number(e)}function N(e){let t=e.trim();if(!t)return null;let n=Number(t);if(Number.isFinite(n)&&n>0)return n<0xe8d4a51000?n*1e3:n;let r=Date.parse(t);return Number.isFinite(r)?r:null}function P(e,t,n){e.sort((e,t)=>e.time-t.time);let r=[];for(let t of e)r.length>0&&r[r.length-1].time===t.time?r[r.length-1]=t:r.push(t);return{data:r,rowCount:t,skipped:n}}var F=class{host;overlay=null;callbacks;bound;depth=0;constructor(e,t){this.host=e,this.callbacks=t,this.bound={dragenter:e=>this.onDragEnter(e),dragover:e=>this.onDragOver(e),dragleave:e=>this.onDragLeave(e),drop:e=>this.onDrop(e)}}attach(){this.host.addEventListener(`dragenter`,this.bound.dragenter),this.host.addEventListener(`dragover`,this.bound.dragover),this.host.addEventListener(`dragleave`,this.bound.dragleave),this.host.addEventListener(`drop`,this.bound.drop)}detach(){this.host.removeEventListener(`dragenter`,this.bound.dragenter),this.host.removeEventListener(`dragover`,this.bound.dragover),this.host.removeEventListener(`dragleave`,this.bound.dragleave),this.host.removeEventListener(`drop`,this.bound.drop),this.hideOverlay()}onDragEnter(e){I(e)&&(e.preventDefault(),this.depth++,this.showOverlay())}onDragOver(e){I(e)&&(e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect=`copy`))}onDragLeave(e){I(e)&&(this.depth=Math.max(0,this.depth-1),this.depth===0&&this.hideOverlay())}async onDrop(e){e.preventDefault(),this.depth=0,this.hideOverlay();let t=e.dataTransfer?.files?.[0];if(t)try{let e=w(await t.text());if(e.data.length===0)throw Error(`No valid OHLCV rows found in "${t.name}"`);this.callbacks.onData(e.data,e,t)}catch(e){this.callbacks.onError?.(e,t)}}showOverlay(){this.overlay||(this.overlay=document.createElement(`div`),Object.assign(this.overlay.style,{position:`absolute`,inset:`8px`,zIndex:`90`,pointerEvents:`none`,borderRadius:`10px`,border:`2px dashed var(--tcw-accent, #4f88ff)`,background:`rgba(79, 136, 255, 0.06)`,display:`flex`,alignItems:`center`,justifyContent:`center`,color:`var(--tcw-accent, #4f88ff)`,fontSize:`14px`,fontWeight:`600`,letterSpacing:`-0.005em`,fontFamily:`inherit`,backdropFilter:`blur(2px)`}),this.overlay.textContent=`Drop CSV or JSON to load chart data`,getComputedStyle(this.host).position===`static`&&(this.host.style.position=`relative`),this.host.appendChild(this.overlay))}hideOverlay(){this.overlay?.remove(),this.overlay=null}};function I(e){return e.dataTransfer?.types?.includes(`Files`)??!1}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return F}});
2
+ //# sourceMappingURL=DragDropImporter-ycI_Tcs6.cjs.map