@tradecanvas/chart 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -9
- package/dist/Chart-CrrTKx3r.js +1027 -0
- package/dist/Chart-CrrTKx3r.js.map +1 -0
- package/dist/Chart-DoR8L8Uk.cjs +2 -0
- package/dist/Chart-DoR8L8Uk.cjs.map +1 -0
- package/dist/Chart.d.ts +22 -8
- package/dist/Chart.d.ts.map +1 -1
- package/dist/charts/ChartTypeStrategy.d.ts +18 -0
- package/dist/charts/ChartTypeStrategy.d.ts.map +1 -0
- package/dist/charts/IndicatorPriceRange.d.ts +16 -0
- package/dist/charts/IndicatorPriceRange.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -1010
- package/dist/index.js.map +1 -1
- package/dist/state/AutoSaveScheduler.d.ts +26 -0
- package/dist/state/AutoSaveScheduler.d.ts.map +1 -0
- package/dist/widget/ChartWidget.d.ts +43 -0
- package/dist/widget/ChartWidget.d.ts.map +1 -0
- package/dist/widget/WidgetDrawingSidebar.d.ts +19 -0
- package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -0
- package/dist/widget/WidgetDropdown.d.ts +18 -0
- package/dist/widget/WidgetDropdown.d.ts.map +1 -0
- package/dist/widget/WidgetSettings.d.ts +25 -0
- package/dist/widget/WidgetSettings.d.ts.map +1 -0
- package/dist/widget/WidgetStatusBar.d.ts +15 -0
- package/dist/widget/WidgetStatusBar.d.ts.map +1 -0
- package/dist/widget/WidgetStyles.d.ts +9 -0
- package/dist/widget/WidgetStyles.d.ts.map +1 -0
- package/dist/widget/WidgetToolbar.d.ts +22 -0
- package/dist/widget/WidgetToolbar.d.ts.map +1 -0
- package/dist/widget/icons.d.ts +2 -0
- package/dist/widget/icons.d.ts.map +1 -0
- package/dist/widget/index.cjs +740 -0
- package/dist/widget/index.cjs.map +1 -0
- package/dist/widget/index.d.ts +3 -0
- package/dist/widget/index.d.ts.map +1 -0
- package/dist/widget/index.js +1058 -0
- package/dist/widget/index.js.map +1 -0
- package/dist/widget/types.d.ts +105 -0
- package/dist/widget/types.d.ts.map +1 -0
- package/dist/widget/widgetConfig.d.ts +16 -0
- package/dist/widget/widgetConfig.d.ts.map +1 -0
- package/package.json +14 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/DataManager.ts","../src/ThemeManager.ts","../src/layout/LayoutManager.ts","../src/plugins/PluginManager.ts","../src/Chart.ts","../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.ts"],"sourcesContent":["import type { OHLCBar, DataSeries } from '@tradecanvas/commons';\nimport { mergeBar } from '@tradecanvas/commons';\n\n/** Validate a single OHLC bar. Returns true if bar is usable. */\nfunction isValidBar(bar: OHLCBar): boolean {\n if (!bar || typeof bar.time !== 'number') return false;\n const { open, high, low, close } = bar;\n // Reject NaN / Infinity\n if (!isFinite(open) || !isFinite(high) || !isFinite(low) || !isFinite(close)) return false;\n // Reject negative prices\n if (open < 0 || high < 0 || low < 0 || close < 0) return false;\n // High must be >= low\n if (high < low) return false;\n // Volume (optional) must be non-negative if present\n if (bar.volume !== undefined && (!isFinite(bar.volume) || bar.volume < 0)) return false;\n return true;\n}\n\n/** Sanitize a bar: clamp high/low to envelope OHLC values. */\nfunction sanitizeBar(bar: OHLCBar): OHLCBar {\n return {\n ...bar,\n high: Math.max(bar.open, bar.high, bar.low, bar.close),\n low: Math.min(bar.open, bar.high, bar.low, bar.close),\n volume: bar.volume !== undefined ? Math.max(0, bar.volume) : 0,\n };\n}\n\nexport class DataManager {\n private data: DataSeries = [];\n\n getData(): DataSeries {\n return this.data;\n }\n\n setData(data: DataSeries): void {\n // Filter out completely invalid bars, sanitize the rest\n this.data = data\n .filter(isValidBar)\n .map(sanitizeBar);\n }\n\n appendBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n this.data.push(sanitizeBar(bar));\n }\n\n updateLastBar(bar: OHLCBar): void {\n if (!isValidBar(bar)) return;\n const sanitized = sanitizeBar(bar);\n if (this.data.length === 0) {\n this.data.push(sanitized);\n return;\n }\n this.data[this.data.length - 1] = sanitized;\n }\n\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\n if (this.data.length === 0) return;\n if (!isFinite(tick.price) || tick.price < 0) return;\n if (tick.volume !== undefined && (!isFinite(tick.volume) || tick.volume < 0)) return;\n this.data[this.data.length - 1] = mergeBar(this.data[this.data.length - 1], tick);\n }\n\n getLength(): number {\n return this.data.length;\n }\n\n clear(): void {\n this.data = [];\n }\n}\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\n\nexport class ThemeManager {\n private theme: Theme;\n\n constructor(themeOrName?: ThemeName | Theme) {\n if (!themeOrName || themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n\n getTheme(): Theme {\n return this.theme;\n }\n\n setTheme(themeOrName: ThemeName | Theme): void {\n if (themeOrName === 'dark') {\n this.theme = { ...DARK_THEME };\n } else if (themeOrName === 'light') {\n this.theme = { ...LIGHT_THEME };\n } else {\n this.theme = { ...themeOrName };\n }\n }\n}\n","import type { PanelPosition, PanelConfig, ResolvedLayout, ResolvedPanel, DividerRect, Rect } from '@tradecanvas/commons';\nimport { DEFAULT_PANEL_HEIGHT, MIN_PANEL_HEIGHT, PRICE_AXIS_WIDTH, TIME_AXIS_HEIGHT } from '@tradecanvas/commons';\n\nconst DEFAULT_PANEL_WIDTH = 200;\nconst MIN_PANEL_WIDTH = 80;\n\nexport class LayoutManager {\n private panels: PanelConfig[] = [];\n private containerWidth = 0;\n private containerHeight = 0;\n\n resize(width: number, height: number): void {\n this.containerWidth = width;\n this.containerHeight = height;\n }\n\n addPanel(instanceId: string, position: PanelPosition = 'bottom', size?: number): void {\n const isVertical = position === 'left' || position === 'right';\n this.panels.push({\n id: instanceId,\n position,\n size: size ?? (isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT),\n minSize: isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT,\n content: { type: 'indicator', indicatorInstanceId: instanceId },\n });\n }\n\n removePanel(instanceId: string): void {\n this.panels = this.panels.filter((p) => p.id !== instanceId);\n }\n\n setPanelPosition(instanceId: string, position: PanelPosition): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n const wasVertical = panel.position === 'left' || panel.position === 'right';\n const isVertical = position === 'left' || position === 'right';\n panel.position = position;\n if (wasVertical !== isVertical) {\n panel.size = isVertical ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_HEIGHT;\n panel.minSize = isVertical ? MIN_PANEL_WIDTH : MIN_PANEL_HEIGHT;\n }\n }\n }\n\n setPanelSize(instanceId: string, size: number): void {\n const panel = this.panels.find((p) => p.id === instanceId);\n if (panel) {\n panel.size = Math.max(panel.minSize, size);\n }\n }\n\n getPanels(): PanelConfig[] {\n return this.panels;\n }\n\n resolve(): ResolvedLayout {\n const leftPanels = this.panels.filter((p) => p.position === 'left');\n const rightPanels = this.panels.filter((p) => p.position === 'right');\n const topPanels = this.panels.filter((p) => p.position === 'top');\n const bottomPanels = this.panels.filter((p) => p.position === 'bottom');\n\n const leftWidth = leftPanels.reduce((s, p) => s + p.size, 0);\n const rightWidth = rightPanels.reduce((s, p) => s + p.size, 0);\n const topHeight = topPanels.reduce((s, p) => s + p.size, 0);\n const bottomHeight = bottomPanels.reduce((s, p) => s + p.size, 0);\n\n const mainChartRect: Rect = {\n x: leftWidth,\n y: topHeight,\n width: Math.max(0, this.containerWidth - leftWidth - rightWidth - PRICE_AXIS_WIDTH),\n height: Math.max(0, this.containerHeight - topHeight - bottomHeight - TIME_AXIS_HEIGHT),\n };\n\n const resolvedPanels: ResolvedPanel[] = [];\n const dividers: DividerRect[] = [];\n\n // Left panels (stacked vertically)\n let x = 0;\n for (const panel of leftPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x + panel.size - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n // Top panels (stacked horizontally, full width minus left/right)\n let y = 0;\n for (const panel of topPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y + panel.size - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Bottom panels\n y = mainChartRect.y + mainChartRect.height;\n for (const panel of bottomPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x: leftWidth, y, width: mainChartRect.width, height: panel.size },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: leftWidth, y: y - 2, width: mainChartRect.width, height: 4 },\n orientation: 'horizontal',\n });\n y += panel.size;\n }\n\n // Right panels\n x = leftWidth + mainChartRect.width + PRICE_AXIS_WIDTH;\n for (const panel of rightPanels) {\n resolvedPanels.push({\n config: panel,\n rect: { x, y: 0, width: panel.size, height: this.containerHeight - TIME_AXIS_HEIGHT },\n });\n dividers.push({\n panelId: panel.id,\n rect: { x: x - 2, y: 0, width: 4, height: this.containerHeight },\n orientation: 'vertical',\n });\n x += panel.size;\n }\n\n return { mainChartRect, panels: resolvedPanels, dividers };\n }\n\n getMainChartRect(): Rect {\n return this.resolve().mainChartRect;\n }\n}\n","import type { IndicatorPlugin } from '@tradecanvas/commons';\nimport type { IndicatorEngine } from '@tradecanvas/core';\n\nexport class PluginManager {\n constructor(private indicatorEngine: IndicatorEngine) {}\n\n registerIndicator(plugin: IndicatorPlugin): void {\n this.indicatorEngine.register(plugin);\n }\n}\n","import type {\n ChartOptions,\n ChartType,\n OHLCBar,\n DataSeries,\n Theme,\n ThemeName,\n ChartEventType,\n ChartEvent,\n TauriBridgeOptions,\n IndicatorPlugin,\n IndicatorDescriptor,\n IndicatorOutput,\n DrawingToolType,\n DrawingState,\n DrawingStyle,\n DrawingPlugin,\n PanelPosition,\n TradingOrder,\n TradingPosition,\n DepthData,\n TradingConfig,\n MarketConfig,\n Locale,\n StreamConfig,\n ConnectionState,\n ConnectionInfo,\n TimeFrame,\n FeaturesConfig,\n} from '@tradecanvas/commons';\nimport { LayerType, setLocale as setGlobalLocale, computePriceLimits } from '@tradecanvas/commons';\nimport {\n RenderEngine,\n Viewport,\n CandlestickRenderer,\n LineRenderer,\n AreaRenderer,\n BarRenderer,\n GridRenderer,\n PriceAxis,\n TimeAxis,\n InteractionManager,\n PanHandler,\n ZoomHandler,\n CrosshairHandler,\n IndicatorEngine,\n registerBuiltInIndicators,\n EventBus,\n DrawingManager,\n DrawingRenderer,\n registerBuiltInDrawingTools,\n TradingManager,\n TradingRenderer,\n StreamManager,\n ChartLegend,\n Screenshot,\n Watermark,\n BarCountdown,\n VolumeRenderer,\n AlertManager,\n ReplayManager,\n ChartStateManager,\n UndoRedoManager,\n Animator,\n KeyboardHandler,\n CrosshairTooltip,\n HollowCandleRenderer,\n BaselineRenderer,\n RenkoRenderer,\n KagiRenderer,\n PointAndFigureRenderer,\n toHeikinAshi,\n toRenko,\n toLineBreak,\n toKagi,\n toPointAndFigure,\n DataExporter,\n SessionBreaks,\n CompareRenderer,\n CurrentPriceLine,\n} from '@tradecanvas/core';\nimport type { ChartRendererInterface } from '@tradecanvas/core';\nimport { DataManager } from './DataManager.js';\nimport { ThemeManager } from './ThemeManager.js';\nimport { LayoutManager } from './layout/LayoutManager.js';\nimport { PluginManager } from './plugins/PluginManager.js';\n\nexport class Chart {\n static version = '0.3.0';\n\n private engine: RenderEngine;\n private viewport: Viewport;\n private dataManager: DataManager;\n private themeManager: ThemeManager;\n private layoutManager: LayoutManager;\n private pluginManager: PluginManager;\n private indicatorEngine: IndicatorEngine;\n private drawingManager: DrawingManager;\n private drawingRenderer: DrawingRenderer;\n private tradingManager: TradingManager;\n private tradingRenderer: TradingRenderer;\n private eventBus: EventBus;\n private streamManager: StreamManager | null = null;\n private autoScrollOnNewBar = true;\n private displayDataCache: DataSeries | null = null;\n private resolvedLayoutCache: import('@tradecanvas/commons').ResolvedLayout | null = null;\n private panelInfoCache: import('@tradecanvas/core').PanelRenderInfo[] | null = null;\n private renderScheduled = false;\n private containerSizeCache: { width: number; height: number } | null = null;\n private containerSizeCacheTime = 0;\n private chartLegend: ChartLegend;\n private watermark: Watermark;\n private barCountdown: BarCountdown;\n private sessionBreaks: SessionBreaks;\n private compareRenderer: CompareRenderer;\n private countdownInterval: ReturnType<typeof setInterval> | null = null;\n private volumeRenderer: VolumeRenderer;\n private alertManager: AlertManager;\n private replayManager: ReplayManager;\n private undoRedoManager: UndoRedoManager;\n private autoSaveTimer: ReturnType<typeof setTimeout> | null = null;\n private autoSaveDelay = 0; // 0 = disabled\n private autoSaveKey: string | null = null;\n private animator: Animator;\n private crosshairTooltip: CrosshairTooltip;\n private interactionManager: InteractionManager;\n private crosshairHandler: CrosshairHandler;\n private chartRenderer: ChartRendererInterface;\n private gridRenderer: GridRenderer;\n private priceAxis: PriceAxis;\n private timeAxis: TimeAxis;\n private options: ChartOptions;\n private features: Required<FeaturesConfig>;\n private marketConfig: MarketConfig | null = null;\n private container: HTMLElement;\n private currentPriceLine: import('@tradecanvas/core').CurrentPriceLine;\n private numberLocale: string;\n private keyboardHandler: KeyboardHandler | null = null;\n private onWindowKeyDown: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: ChartOptions) {\n this.container = container;\n this.options = options;\n this.numberLocale = options.numberLocale ?? 'en-US';\n\n // Resolve feature flags (all default to true)\n const f = options.features ?? {};\n this.features = {\n drawings: f.drawings ?? true,\n drawingTools: f.drawingTools ?? [],\n drawingMagnet: f.drawingMagnet ?? true,\n drawingUndoRedo: f.drawingUndoRedo ?? true,\n trading: f.trading ?? true,\n tradingContextMenu: f.tradingContextMenu ?? true,\n indicators: f.indicators ?? true,\n indicatorIds: f.indicatorIds ?? [],\n panning: f.panning ?? true,\n zooming: f.zooming ?? true,\n crosshair: f.crosshair ?? true,\n keyboard: f.keyboard ?? true,\n priceAxis: f.priceAxis ?? true,\n timeAxis: f.timeAxis ?? true,\n grid: f.grid ?? (options.grid?.visible ?? true),\n legend: f.legend ?? true,\n volume: f.volume ?? true,\n watermark: f.watermark ?? true,\n saveLoad: f.saveLoad ?? true,\n screenshot: f.screenshot ?? true,\n alerts: f.alerts ?? true,\n replay: f.replay ?? true,\n sessionBreaks: f.sessionBreaks ?? true,\n barCountdown: f.barCountdown ?? true,\n compareSymbols: f.compareSymbols ?? true,\n dataExport: f.dataExport ?? true,\n logScale: f.logScale ?? true,\n timeframes: f.timeframes ?? [],\n defaultTimeframeFavorites: f.defaultTimeframeFavorites ?? [],\n };\n\n container.style.position = 'relative';\n container.style.overflow = 'hidden';\n container.tabIndex = 0; // Allow keyboard events\n container.style.outline = 'none';\n\n // Initialize managers\n this.dataManager = new DataManager();\n this.themeManager = new ThemeManager(options.theme);\n this.layoutManager = new LayoutManager();\n this.indicatorEngine = new IndicatorEngine();\n this.pluginManager = new PluginManager(this.indicatorEngine);\n this.eventBus = new EventBus();\n\n registerBuiltInIndicators(this.indicatorEngine);\n\n // Drawing tools\n this.drawingManager = new DrawingManager();\n registerBuiltInDrawingTools(this.drawingManager);\n this.drawingRenderer = new DrawingRenderer(this.drawingManager);\n this.drawingManager.setRequestRender(() => {\n // Sync entire render context so drawings render with same viewport as candles\n this.syncRenderContext();\n this.engine.requestRender(LayerType.Overlay);\n this.scheduleAutoSave();\n });\n this.drawingManager.setEventCallback((event, data) => {\n this.eventBus.emit(event as ChartEventType, data);\n });\n // Undo/redo\n this.undoRedoManager = new UndoRedoManager();\n this.drawingManager.setUndoRedoManager(this.undoRedoManager);\n this.drawingManager.setDataGetter(() => this.dataManager.getData());\n this.drawingManager.setDisplayDataGetter(() => this.getDisplayData());\n // Magnet mode\n if (options.crosshair?.mode === 'magnet') {\n this.drawingManager.setMagnetMode('magnet');\n }\n\n // Trading\n this.tradingManager = new TradingManager();\n this.tradingRenderer = new TradingRenderer(this.tradingManager);\n this.tradingManager.setContainer(container);\n this.tradingManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\n this.tradingManager.setEventCallback((event, data) => {\n this.eventBus.emit(event as ChartEventType, data);\n });\n\n // Rendering\n this.engine = new RenderEngine(container);\n const size = this.engine.dprManager.getContainerSize();\n this.viewport = new Viewport(\n size.width,\n size.height,\n options.minBarSpacing ?? 2,\n options.maxBarSpacing ?? 30,\n options.rightMargin ?? 5,\n );\n this.layoutManager.resize(size.width, size.height);\n\n // Sync viewport + layout when the container resizes. Without this hook\n // the chart's viewport keeps its construction-time chartRect forever\n // (which is wrong if the container started at 0 or got resized since),\n // and `scrollToEnd` / clampOffset compute against stale dimensions —\n // chart sticks at the wrong offset and the user can't scroll to the\n // latest bar.\n this.engine.onContainerResize = (newSize) => {\n if (newSize.width <= 0 || newSize.height <= 0) return;\n const wasAtEnd = this.viewport.isAtEnd();\n this.viewport.resize(newSize.width, newSize.height);\n this.layoutManager.resize(newSize.width, newSize.height);\n // wasAtEnd carries the user's intent: if they were tracking the live\n // edge before the resize, keep them there afterwards. Otherwise leave\n // their scroll position alone.\n this.updateViewportAndRender(wasAtEnd);\n };\n\n // Chart renderer\n this.chartRenderer = this.createChartRenderer(options.chartType);\n this.gridRenderer = new GridRenderer();\n if (options.grid?.visible === false) this.gridRenderer.setVisible(false);\n this.priceAxis = new PriceAxis();\n this.priceAxis.setLocale(this.numberLocale);\n this.timeAxis = new TimeAxis();\n\n // Crosshair\n this.crosshairHandler = new CrosshairHandler();\n this.crosshairHandler.setLocale(this.numberLocale);\n if (options.crosshair?.mode) {\n this.crosshairHandler.setMode(options.crosshair.mode);\n }\n // Crosshair callback — fired via microtask AFTER render, only when bar changes.\n // No DOM writes, no layout reads, no extra render requests.\n this.crosshairHandler.setCallback((barIndex, point) => {\n if (barIndex !== null && point) {\n const data = this.dataManager.getData();\n const bar = barIndex < data.length ? data[barIndex] : undefined;\n\n // Update legend (canvas-rendered, will show on next UI paint)\n this.chartLegend.setHoverBar(bar ?? null);\n\n // Update tooltip (DOM, lightweight update only when bar changes)\n if (bar) {\n this.crosshairTooltip.show(point, bar, this.themeManager.getTheme(), this.cachedContainerSize());\n }\n\n // Emit for external consumers\n this.eventBus.emit('crosshairMove', { point, bar, barIndex });\n } else {\n this.crosshairTooltip.hide();\n this.chartLegend.setHoverBar(null);\n }\n });\n\n // Chart legend (OHLCV overlay)\n this.chartLegend = new ChartLegend();\n this.chartLegend.setChartType(options.chartType);\n\n // Watermark + Volume\n this.watermark = new Watermark();\n if (options.watermark) this.watermark.setConfig(options.watermark);\n this.volumeRenderer = new VolumeRenderer();\n\n // Bar countdown timer\n this.barCountdown = new BarCountdown();\n this.sessionBreaks = new SessionBreaks();\n this.compareRenderer = new CompareRenderer();\n\n // Apply session break config from options\n if (options.sessionBreaks) {\n this.sessionBreaks.setConfig({\n visible: options.sessionBreaks.visible ?? true,\n color: options.sessionBreaks.color,\n lineStyle: options.sessionBreaks.lineStyle,\n lineWidth: options.sessionBreaks.lineWidth,\n });\n } else if (options.features?.sessionBreaks !== false) {\n this.sessionBreaks.setVisible(true);\n }\n\n // Apply log scale from options\n if (options.logScale) {\n this.viewport.setLogScale(true);\n }\n\n // Animation\n this.animator = new Animator();\n\n // Crosshair tooltip (DOM)\n this.crosshairTooltip = new CrosshairTooltip();\n this.crosshairTooltip.create(container);\n\n // Keyboard navigation\n this.keyboardHandler = new KeyboardHandler({\n scrollBars: (count) => {\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\n this.viewport.scrollBy(count * barUnit);\n this.updateViewportAndRender();\n },\n zoom: (delta) => {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(delta, chartWidth / 2);\n this.updateViewportAndRender();\n },\n goToStart: () => {\n this.viewport.scrollBy(-Infinity);\n this.updateViewportAndRender();\n },\n goToEnd: () => {\n this.viewport.scrollToEnd();\n this.updateViewportAndRender();\n },\n fitContent: () => this.fitContent(),\n });\n this.keyboardHandler.setEnabled(this.features.keyboard);\n\n // Attach keyboard listener to window. Only consume the event when the\n // chart actually handles the key AND the container is the focused element\n // (or an ancestor) — this prevents the chart from swallowing keystrokes\n // intended for inputs elsewhere on the page.\n this.onWindowKeyDown = (e: KeyboardEvent) => {\n if (!this.keyboardHandler) return;\n const active = document.activeElement as HTMLElement | null;\n if (active && active !== this.container && !this.container.contains(active)) {\n return;\n }\n // Ignore when typing in a form field that happens to live inside the chart.\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) {\n return;\n }\n if (this.keyboardHandler.handleKey(e)) {\n e.preventDefault();\n }\n };\n window.addEventListener('keydown', this.onWindowKeyDown);\n\n // Current price line (standalone, works without StreamManager)\n this.currentPriceLine = new CurrentPriceLine();\n\n // Alerts\n this.alertManager = new AlertManager();\n this.alertManager.setRequestRender(() => this.engine.requestRender(LayerType.Overlay));\n this.alertManager.on('triggered', (alert) => {\n this.eventBus.emit('dataUpdate', { alert: 'triggered', alertId: alert.id, price: alert.price, message: alert.message });\n });\n\n // Replay\n this.replayManager = new ReplayManager();\n\n // Interaction\n this.interactionManager = new InteractionManager(container);\n if (this.features.panning) {\n this.interactionManager.setPanHandler(\n new PanHandler((deltaX) => {\n this.viewport.scrollBy(deltaX);\n this.updateViewportAndRender();\n }),\n );\n }\n if (this.features.zooming) {\n this.interactionManager.setZoomHandler(\n new ZoomHandler((delta, centerX) => {\n this.viewport.zoom(delta, centerX);\n this.updateViewportAndRender();\n }),\n );\n }\n if (this.features.crosshair) {\n this.interactionManager.setCrosshairHandler(this.crosshairHandler);\n }\n if (this.features.drawings) {\n this.interactionManager.setDrawingManager(\n this.drawingManager,\n () => this.viewport.getState(),\n );\n }\n if (this.features.trading) {\n this.interactionManager.setTradingManager(\n this.tradingManager,\n () => this.viewport.getState(),\n );\n }\n this.interactionManager.setOverlayDirtyCallback(() => {\n this.engine.requestRender(LayerType.Overlay);\n // Also refresh UI layer for panel crosshair value labels\n if (this.layoutManager.getPanels().length > 0) {\n this.engine.requestRender(LayerType.UI);\n }\n });\n this.interactionManager.attach();\n\n // Set render context\n this.syncRenderContext();\n this.engine.start();\n }\n\n // --- Data ---\n\n setData(data: DataSeries): void {\n this.dataManager.setData(data);\n this.crosshairHandler.setData(this.dataManager.getData());\n this.displayDataCache = null;\n this.sessionBreaks.invalidateCache();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n // Auto-set current price line from last bar's close\n if (data.length > 0) {\n this.currentPriceLine.setPrice(data[data.length - 1].close);\n }\n this.updateViewportAndRender(true);\n this.eventBus.emit('dataUpdate', { length: data.length });\n }\n\n appendBar(bar: OHLCBar): void {\n this.dataManager.appendBar(bar);\n this.crosshairHandler.setData(this.dataManager.getData());\n this.displayDataCache = null;\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.updateViewportAndRender();\n }\n\n updateLastBar(bar: OHLCBar): void {\n this.dataManager.updateLastBar(bar);\n this.currentPriceLine.setPrice(bar.close);\n // For non-transform chart types, the displayDataCache still points to the\n // same raw array (mutated in place), so no need to invalidate.\n // Only invalidate for transform types that produce derived arrays.\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\n && this.options.chartType !== 'hollowCandle') {\n this.displayDataCache = null;\n }\n // Keep indicator lines in sync with the forming bar. Without this, panel\n // + overlay indicators freeze until bar close.\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.scheduleRender();\n }\n\n /** Merge a price tick into the current last bar (convenience for live feeds) */\n updateLastBarFromTick(tick: { price: number; volume?: number; time: number }): void {\n this.dataManager.updateLastBarFromTick(tick);\n this.currentPriceLine.setPrice(tick.price);\n if (this.options.chartType !== 'candlestick' && this.options.chartType !== 'line'\n && this.options.chartType !== 'area' && this.options.chartType !== 'bar'\n && this.options.chartType !== 'hollowCandle') {\n this.displayDataCache = null;\n }\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.scheduleRender();\n }\n\n // --- Chart type ---\n\n setChartType(type: ChartType): void {\n this.options.chartType = type;\n this.chartRenderer = this.createChartRenderer(type);\n this.chartLegend.setChartType(type);\n this.displayDataCache = null;\n this.updateViewportAndRender(true);\n }\n\n // --- Indicators ---\n\n addIndicator(id: string, params: Record<string, number | string | boolean> = {}, position: PanelPosition = 'bottom'): string | null {\n if (!this.features.indicators) return null;\n if (this.features.indicatorIds.length > 0 && !this.features.indicatorIds.includes(id)) return null;\n const instanceId = this.indicatorEngine.addIndicator(id, params, this.dataManager.getData());\n const descriptor = this.indicatorEngine.getAvailableIndicators().find((d) => d.id === id);\n if (descriptor?.placement === 'panel') {\n this.layoutManager.addPanel(instanceId, position);\n // Panel layout changed — must re-resolve layout, update viewport, and sync render context\n this.updateViewportAndRender();\n } else {\n this.engine.requestRender();\n }\n this.eventBus.emit('indicatorAdd', { instanceId, id });\n return instanceId;\n }\n\n updateIndicator(instanceId: string, params: Record<string, number | string | boolean>): void {\n this.indicatorEngine.updateIndicator(instanceId, params, this.dataManager.getData());\n this.engine.requestRender();\n }\n\n removeIndicator(instanceId: string): void {\n const hadPanel = this.layoutManager.getPanels().some(p => p.id === instanceId);\n this.indicatorEngine.removeIndicator(instanceId);\n this.layoutManager.removePanel(instanceId);\n this.eventBus.emit('indicatorRemove', { instanceId });\n if (hadPanel) {\n this.updateViewportAndRender();\n } else {\n this.engine.requestRender();\n }\n }\n\n getIndicatorOutput(instanceId: string): IndicatorOutput | null {\n return this.indicatorEngine.getOutput(instanceId);\n }\n\n registerIndicator(plugin: IndicatorPlugin): void {\n this.pluginManager.registerIndicator(plugin);\n }\n\n static indicators(): IndicatorDescriptor[] {\n const engine = new IndicatorEngine();\n registerBuiltInIndicators(engine);\n return engine.getAvailableIndicators();\n }\n\n // --- Panel layout ---\n\n setPanelPosition(instanceId: string, position: PanelPosition): void {\n this.layoutManager.setPanelPosition(instanceId, position);\n this.engine.requestRender();\n }\n\n setPanelSize(instanceId: string, size: number): void {\n this.layoutManager.setPanelSize(instanceId, size);\n this.engine.requestRender();\n }\n\n // --- Drawing tools ---\n\n setDrawingTool(type: DrawingToolType | null): void {\n if (!this.features.drawings) return;\n // If whitelist is set, check it\n if (type && this.features.drawingTools.length > 0 && !this.features.drawingTools.includes(type)) return;\n this.drawingManager.setActiveTool(type);\n }\n\n getDrawingTool(): DrawingToolType | null {\n return this.drawingManager.getActiveTool();\n }\n\n setDrawingStyle(style: Partial<DrawingStyle>): void {\n this.drawingManager.setStyle(style);\n }\n\n getDrawings(): DrawingState[] {\n return this.drawingManager.getDrawings();\n }\n\n setDrawings(drawings: DrawingState[]): void {\n this.drawingManager.setDrawings(drawings);\n }\n\n removeDrawing(id: string): void {\n this.drawingManager.removeDrawing(id);\n }\n\n clearDrawings(): void {\n this.drawingManager.clearDrawings();\n }\n\n registerDrawingTool(plugin: DrawingPlugin): void {\n this.drawingManager.register(plugin);\n }\n\n // --- Undo/Redo ---\n\n undo(): boolean {\n if (!this.features.drawingUndoRedo) return false;\n return this.drawingManager.undo();\n }\n\n redo(): boolean {\n if (!this.features.drawingUndoRedo) return false;\n return this.drawingManager.redo();\n }\n\n getUndoRedoState(): { canUndo: boolean; canRedo: boolean } {\n return this.undoRedoManager.getState();\n }\n\n // --- Drawing magnet ---\n\n setDrawingMagnet(enabled: boolean): void {\n this.drawingManager.setMagnetMode(enabled ? 'magnet' : 'none');\n }\n\n getDrawingMagnet(): boolean {\n return this.drawingManager.getMagnetMode() === 'magnet';\n }\n\n // --- Bulk drawing operations ---\n\n lockAllDrawings(): void {\n this.drawingManager.lockAllDrawings();\n }\n\n unlockAllDrawings(): void {\n this.drawingManager.unlockAllDrawings();\n }\n\n hideAllDrawings(): void {\n this.drawingManager.hideAllDrawings();\n }\n\n showAllDrawings(): void {\n this.drawingManager.showAllDrawings();\n }\n\n // --- Drawing duplication ---\n\n duplicateDrawing(id?: string): string | null {\n const targetId = id ?? this.drawingManager.getSelectedDrawingId();\n if (!targetId) return null;\n return this.drawingManager.duplicateDrawing(targetId);\n }\n\n // --- Data export ---\n\n exportVisibleData(format: 'csv' | 'json' = 'csv', filename?: string): void {\n const vp = this.viewport.getState();\n const data = this.dataManager.getData();\n const from = Math.max(0, vp.visibleRange.from);\n const to = Math.min(data.length - 1, vp.visibleRange.to);\n const slice = data.slice(from, to + 1);\n\n if (format === 'json') {\n const content = DataExporter.toJSON(slice);\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\n } else {\n const content = DataExporter.toCSV(slice);\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\n }\n }\n\n exportAllData(format: 'csv' | 'json' = 'csv', filename?: string): void {\n const data = this.dataManager.getData();\n if (format === 'json') {\n const content = DataExporter.toJSON(data);\n DataExporter.download(content, filename ?? 'chart-data.json', 'application/json');\n } else {\n const content = DataExporter.toCSV(data);\n DataExporter.download(content, filename ?? 'chart-data.csv', 'text/csv');\n }\n }\n\n // --- Auto-save ---\n\n setAutoSave(key: string, delayMs = 5000): void {\n this.autoSaveKey = key;\n this.autoSaveDelay = delayMs;\n }\n\n disableAutoSave(): void {\n this.autoSaveDelay = 0;\n this.autoSaveKey = null;\n if (this.autoSaveTimer) {\n clearTimeout(this.autoSaveTimer);\n this.autoSaveTimer = null;\n }\n }\n\n private scheduleAutoSave(): void {\n if (this.autoSaveDelay <= 0 || !this.autoSaveKey) return;\n if (this.autoSaveTimer) clearTimeout(this.autoSaveTimer);\n this.autoSaveTimer = setTimeout(() => {\n this.autoSaveTimer = null;\n if (this.autoSaveKey) {\n this.saveState(this.autoSaveKey);\n }\n }, this.autoSaveDelay);\n }\n\n // --- Indicator introspection ---\n\n getAvailableIndicators(): IndicatorDescriptor[] {\n return this.indicatorEngine.getAvailableIndicators();\n }\n\n getIndicatorInputs(id: string): { id: string; params: Record<string, unknown> } | null {\n const indicators = this.indicatorEngine.getAvailableIndicators();\n const desc = indicators.find(i => i.id === id);\n if (!desc) return null;\n return { id: desc.id, params: desc.defaultConfig };\n }\n\n /** Get all active indicator instances with their current params */\n getActiveIndicators(): { instanceId: string; id: string; params: Record<string, unknown>; descriptor: IndicatorDescriptor }[] {\n return this.indicatorEngine.getActiveIndicators();\n }\n\n /** Get current config for a specific indicator instance */\n getIndicatorConfig(instanceId: string): { id: string; params: Record<string, unknown> } | null {\n const config = this.indicatorEngine.getIndicatorConfig(instanceId);\n if (!config) return null;\n return { id: config.id, params: { ...config.params } };\n }\n\n /** Update indicator colors/line widths at runtime */\n updateIndicatorStyle(instanceId: string, style: { colors?: string[]; lineWidths?: number[]; opacity?: number }): void {\n this.indicatorEngine.updateIndicatorStyle(instanceId, style);\n this.engine.requestRender();\n }\n\n // --- Trading ---\n\n setOrders(orders: TradingOrder[]): void {\n if (!this.features.trading) return;\n this.tradingManager.setOrders(orders);\n }\n\n setPositions(positions: TradingPosition[]): void {\n if (!this.features.trading) return;\n this.tradingManager.setPositions(positions);\n }\n\n setDepthData(depth: DepthData | null): void {\n if (!this.features.trading) return;\n this.tradingManager.setDepthData(depth);\n }\n\n setCurrentPrice(price: number): void {\n this.tradingManager.setCurrentPrice(price);\n // Also update standalone price line (visible even without trading feature)\n this.currentPriceLine.setPrice(price);\n this.scheduleRender();\n if (this.features.alerts) this.alertManager.checkPrice(price);\n }\n\n setTradingConfig(config: Partial<TradingConfig>): void {\n if (!this.features.trading) return;\n this.tradingManager.setConfig(config);\n }\n\n // --- Real-time Streaming ---\n\n /**\n * Connect to a real-time data source.\n * Loads history, starts streaming, manages reconnection automatically.\n *\n * @example\n * import { BinanceAdapter } from '@tradecanvas/core';\n * chart.connect({\n * adapter: new BinanceAdapter(),\n * symbol: 'BTCUSDT',\n * timeframe: '1m',\n * });\n */\n async connect(config: StreamConfig): Promise<void> {\n this.disconnectStream();\n\n this.streamManager = new StreamManager();\n\n this.streamManager.on('snapshot', (bars) => {\n this.setData(bars);\n });\n\n this.streamManager.on('barClose', (bar) => {\n this.dataManager.appendBar(bar);\n this.crosshairHandler.setData(this.dataManager.getData());\n if (this.autoScrollOnNewBar) this.viewport.scrollToEnd();\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.updateViewportAndRender();\n });\n\n this.streamManager.on('barUpdate', (bar) => {\n this.dataManager.updateLastBar(bar);\n this.currentPriceLine.setPrice(bar.close);\n // Recalculate indicators so panel/overlay series track the forming bar\n // instead of freezing until bar close.\n this.indicatorEngine.recalculateAll(this.dataManager.getData());\n this.scheduleRender();\n });\n\n this.streamManager.on('priceChange', ({ price }) => {\n this.tradingManager.setCurrentPrice(price);\n this.currentPriceLine.setPrice(price);\n this.engine.requestRender(LayerType.Overlay);\n this.engine.requestRender(LayerType.UI);\n });\n\n this.streamManager.on('connectionChange', (info) => {\n this.eventBus.emit('dataUpdate', { connection: info });\n });\n\n this.streamManager.on('error', (err) => {\n this.eventBus.emit('dataUpdate', { error: err.message });\n });\n\n this.autoScrollOnNewBar = config.autoScroll !== false;\n\n await this.streamManager.connect(config);\n\n // Set up bar countdown timer based on timeframe\n const tfMs = this.timeframeToMs(config.timeframe);\n this.barCountdown.setTimeframeMs(tfMs);\n\n // Start countdown refresh interval\n if (this.countdownInterval) clearInterval(this.countdownInterval);\n this.countdownInterval = setInterval(() => {\n if (this.barCountdown.isVisible()) {\n this.engine.requestRender(LayerType.UI);\n }\n }, 1000);\n }\n\n /**\n * Switch symbol or timeframe on an active stream without full reconnect.\n */\n async switchStream(symbol: string, timeframe: TimeFrame): Promise<void> {\n if (!this.streamManager) return;\n await this.streamManager.switchTo(symbol, timeframe);\n }\n\n /**\n * Disconnect the real-time stream.\n */\n disconnectStream(): void {\n if (this.streamManager) {\n this.streamManager.dispose();\n this.streamManager = null;\n }\n }\n\n setBarCountdownVisible(visible: boolean): void {\n this.barCountdown.setVisible(visible);\n this.engine.requestRender(LayerType.UI);\n }\n\n setSessionBreaksVisible(visible: boolean): void {\n this.sessionBreaks.setVisible(visible);\n this.engine.requestRender(LayerType.Background);\n }\n\n // --- Compare symbols ---\n\n addCompareSymbol(id: string, label: string, data: DataSeries, color: string): void {\n this.compareRenderer.addSymbol({ id, label, data, color, visible: true });\n this.engine.requestRender(LayerType.Main);\n }\n\n removeCompareSymbol(id: string): void {\n this.compareRenderer.removeSymbol(id);\n this.engine.requestRender(LayerType.Main);\n }\n\n updateCompareData(id: string, data: DataSeries): void {\n this.compareRenderer.setSymbolData(id, data);\n this.engine.requestRender(LayerType.Main);\n }\n\n setCompareMode(mode: 'percent' | 'absolute'): void {\n this.compareRenderer.setMode(mode);\n this.engine.requestRender(LayerType.Main);\n }\n\n clearCompareSymbols(): void {\n this.compareRenderer.clear();\n this.engine.requestRender(LayerType.Main);\n }\n\n // --- Log scale ---\n\n setLogScale(enabled: boolean): void {\n this.viewport.setLogScale(enabled);\n this.updateViewportAndRender();\n }\n\n isLogScale(): boolean {\n return this.viewport.isLogScale();\n }\n\n setSessionBreaksConfig(config: { color?: string; lineStyle?: 'solid' | 'dashed' | 'dotted'; lineWidth?: number }): void {\n this.sessionBreaks.setConfig(config);\n this.engine.requestRender(LayerType.Background);\n }\n\n getConnectionState(): ConnectionState {\n return this.streamManager?.getConnectionState() ?? 'disconnected';\n }\n\n getConnectionInfo(): ConnectionInfo {\n return this.streamManager?.getConnectionInfo() ?? { state: 'disconnected' };\n }\n\n setAutoScroll(enabled: boolean): void {\n this.autoScrollOnNewBar = enabled;\n }\n\n // --- Viewport ---\n\n scrollTo(timestamp: number): void {\n const data = this.dataManager.getData();\n for (let i = 0; i < data.length; i++) {\n if (data[i].time >= timestamp) {\n const barUnit = this.viewport.getState().barWidth + this.viewport.getState().barSpacing;\n this.viewport.scrollBy(i * barUnit - this.viewport.getState().offset);\n this.updateViewportAndRender();\n return;\n }\n }\n }\n\n scrollToEnd(): void {\n this.viewport.scrollToEnd();\n this.updateViewportAndRender();\n }\n\n setVisibleRange(fromTimestamp: number, toTimestamp: number): void {\n const data = this.dataManager.getData();\n let fromIdx = 0;\n let toIdx = data.length - 1;\n for (let i = 0; i < data.length; i++) {\n if (data[i].time >= fromTimestamp) { fromIdx = i; break; }\n }\n for (let i = data.length - 1; i >= 0; i--) {\n if (data[i].time <= toTimestamp) { toIdx = i; break; }\n }\n const barCount = toIdx - fromIdx + 1;\n if (barCount > 0) {\n const chartWidth = this.viewport.getState().chartRect.width;\n const targetBarUnit = chartWidth / barCount;\n const newBarWidth = Math.max(2, targetBarUnit - this.viewport.getState().barSpacing);\n this.viewport.zoom(\n (newBarWidth - this.viewport.getState().barWidth) / this.viewport.getState().barWidth,\n chartWidth / 2,\n );\n }\n this.updateViewportAndRender();\n }\n\n zoomIn(): void {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(0.2, chartWidth / 2);\n this.updateViewportAndRender();\n }\n\n zoomOut(): void {\n const chartWidth = this.viewport.getState().chartRect.width;\n this.viewport.zoom(-0.2, chartWidth / 2);\n this.updateViewportAndRender();\n }\n\n fitContent(): void {\n const data = this.dataManager.getData();\n if (data.length === 0) return;\n this.setVisibleRange(data[0].time, data[data.length - 1].time);\n }\n\n // --- Events ---\n\n on(type: ChartEventType, handler: (event: ChartEvent) => void): void {\n this.eventBus.on(type, handler);\n }\n\n off(type: ChartEventType, handler: (event: ChartEvent) => void): void {\n this.eventBus.off(type, handler);\n }\n\n enableTauriBridge(options?: Partial<TauriBridgeOptions>): void {\n this.eventBus.enableTauriBridge({ enabled: true, ...options });\n }\n\n disableTauriBridge(): void {\n this.eventBus.disableTauriBridge();\n }\n\n // --- Theme ---\n\n setTheme(themeOrName: ThemeName | Theme): void {\n this.themeManager.setTheme(themeOrName);\n this.syncRenderContext();\n this.container.style.backgroundColor = this.themeManager.getTheme().background;\n this.engine.requestRender();\n this.eventBus.emit('themeChange', { theme: themeOrName });\n }\n\n getTheme(): Theme {\n return this.themeManager.getTheme();\n }\n\n // --- Watermark ---\n\n setWatermark(text: string, opts?: { color?: string; fontSize?: number }): void {\n this.watermark.setConfig({ text, ...opts });\n this.engine.requestRender(LayerType.Background);\n }\n\n // --- Auto Scale ---\n\n setAutoScale(enabled: boolean): void {\n this.options.autoScale = enabled;\n this.updateViewportAndRender();\n }\n\n isAutoScale(): boolean {\n return this.options.autoScale !== false;\n }\n\n // --- Crosshair ---\n\n setCrosshairMode(mode: 'normal' | 'magnet' | 'hidden'): void {\n this.crosshairHandler.setMode(mode);\n this.engine.requestRender(LayerType.Overlay);\n }\n\n getCrosshairMode(): string {\n return this.crosshairHandler.getMode();\n }\n\n // --- Grid ---\n\n setGridVisible(visible: boolean): void {\n this.gridRenderer.setVisible(visible);\n this.engine.requestRender(LayerType.Background);\n }\n\n isGridVisible(): boolean {\n return this.gridRenderer.isVisible();\n }\n\n // --- Volume ---\n\n setVolumeVisible(visible: boolean): void {\n this.volumeRenderer.setVisible(visible);\n this.engine.requestRender(LayerType.Main);\n }\n\n // --- Tooltip ---\n\n setTooltipVisible(visible: boolean): void {\n if (!visible) this.crosshairTooltip.hide();\n }\n\n // --- Legend ---\n\n setLegend(config: Partial<import('@tradecanvas/core').LegendConfig>): void {\n this.chartLegend.setConfig(config);\n this.engine.requestRender(LayerType.UI);\n }\n\n setSymbolName(symbol: string): void {\n this.chartLegend.setSymbol(symbol);\n this.engine.requestRender(LayerType.UI);\n }\n\n // --- Screenshot ---\n\n screenshot(filename?: string): void {\n if (!this.features.screenshot) return;\n Screenshot.download(this.container, filename, this.themeManager.getTheme().background);\n }\n\n screenshotDataURL(): string | null {\n if (!this.features.screenshot) return null;\n return Screenshot.toDataURL(this.container, this.themeManager.getTheme().background);\n }\n\n async screenshotBlob(): Promise<Blob | null> {\n if (!this.features.screenshot) return null;\n return Screenshot.toBlob(this.container, this.themeManager.getTheme().background);\n }\n\n // --- Alerts ---\n\n addAlert(price: number, condition: import('@tradecanvas/core').AlertCondition = 'crossing', message?: string): string | null {\n if (!this.features.alerts) return null;\n const id = this.alertManager.addAlert(price, condition, message);\n this.scheduleAutoSave();\n return id;\n }\n\n removeAlert(id: string): void {\n this.alertManager.removeAlert(id);\n this.scheduleAutoSave();\n }\n\n getAlerts(): import('@tradecanvas/core').PriceAlert[] {\n return this.alertManager.getAlerts();\n }\n\n clearAlerts(): void {\n this.alertManager.clearAlerts();\n this.scheduleAutoSave();\n }\n\n saveAlerts(key: string): void {\n this.alertManager.saveToStorage(key);\n }\n\n loadAlerts(key: string): void {\n this.alertManager.loadFromStorage(key);\n this.engine.requestRender(LayerType.Overlay);\n }\n\n // --- Replay ---\n\n replay(config?: Partial<import('@tradecanvas/core').ReplayConfig>): void {\n if (!this.features.replay) return;\n const data = this.dataManager.getData();\n this.replayManager.load(data);\n this.replayManager.on('bar', ({ bar: _bar, index }) => {\n const slice = data.slice(0, index + 1);\n this.dataManager.setData(slice);\n this.crosshairHandler.setData(slice);\n this.indicatorEngine.recalculateAll(slice);\n this.updateViewportAndRender();\n });\n this.replayManager.play(config);\n }\n\n replayPause(): void { this.replayManager.pause(); }\n replayResume(): void { this.replayManager.resume(); }\n replayStop(): void { this.replayManager.stop(); }\n replaySeek(index: number): void { this.replayManager.seekTo(index); }\n setReplaySpeed(speed: number): void { this.replayManager.setSpeed(speed); }\n getReplayState(): 'playing' | 'paused' | 'stopped' { return this.replayManager.getState(); }\n getReplayProgress(): { current: number; total: number; percent: number } { return this.replayManager.getProgress(); }\n\n // --- Save / Load ---\n\n saveState(key?: string): string | null {\n if (!this.features.saveLoad) return null;\n const snapshot = ChartStateManager.capture(\n {\n getDrawings: () => this.getDrawings(),\n getTheme: () => this.getTheme(),\n getAlerts: () => this.getAlerts(),\n },\n { chartType: this.options.chartType },\n );\n const json = ChartStateManager.serialize(snapshot);\n if (key) ChartStateManager.saveToStorage(key, snapshot);\n return json;\n }\n\n loadState(json: string): void {\n if (!this.features.saveLoad) return;\n const snapshot = ChartStateManager.deserialize(json);\n if (snapshot.chartType) this.setChartType(snapshot.chartType);\n if (snapshot.drawings) this.setDrawings(snapshot.drawings);\n if (snapshot.theme) this.setTheme(snapshot.theme as any);\n if (snapshot.alerts) {\n this.clearAlerts();\n for (const a of snapshot.alerts) {\n this.addAlert(a.price, a.condition, a.message);\n }\n }\n }\n\n loadStateFromStorage(key: string): boolean {\n if (!this.features.saveLoad) return false;\n const snapshot = ChartStateManager.loadFromStorage(key);\n if (!snapshot) return false;\n this.loadState(ChartStateManager.serialize(snapshot));\n return true;\n }\n\n downloadState(filename?: string): void {\n if (!this.features.saveLoad) return;\n const snapshot = ChartStateManager.capture(\n { getDrawings: () => this.getDrawings(), getTheme: () => this.getTheme(), getAlerts: () => this.getAlerts() },\n { chartType: this.options.chartType },\n );\n ChartStateManager.downloadFile(snapshot, filename);\n }\n\n async loadStateFromFile(): Promise<void> {\n if (!this.features.saveLoad) return;\n const snapshot = await ChartStateManager.loadFromFile();\n this.loadState(ChartStateManager.serialize(snapshot));\n }\n\n // --- Locale ---\n\n setLocale(locale: Locale): void {\n setGlobalLocale(locale);\n this.engine.requestRender();\n }\n\n /**\n * Update the BCP 47 locale used for number formatting\n * (e.g. price axis labels, crosshair value badges).\n * Defaults to 'en-US'. Example values: 'de-DE', 'vi-VN', 'fr-FR'.\n */\n setNumberLocale(locale: string): void {\n this.numberLocale = locale;\n this.priceAxis.setLocale(locale);\n this.crosshairHandler.setLocale(locale);\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n getNumberLocale(): string {\n return this.numberLocale;\n }\n\n // --- Market ---\n\n setMarket(config: MarketConfig): void {\n this.marketConfig = config;\n\n // Apply market color scheme to theme\n if (config.colorScheme) {\n const base = this.themeManager.getTheme();\n const marketTheme: Theme = {\n ...base,\n candleUp: config.colorScheme.up,\n candleDown: config.colorScheme.down,\n candleUpWick: config.colorScheme.up,\n candleDownWick: config.colorScheme.down,\n volumeUp: config.colorScheme.up.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.up}4D`,\n volumeDown: config.colorScheme.down.replace(')', ', 0.3)').replace('rgb(', 'rgba(') || `${config.colorScheme.down}4D`,\n };\n this.themeManager.setTheme(marketTheme);\n }\n\n // Apply price precision to trading, alerts, and price line\n if (config.pricePrecision !== undefined) {\n this.tradingManager.setConfig({ pricePrecision: config.pricePrecision });\n this.alertManager.setPricePrecision(config.pricePrecision);\n this.streamManager?.priceLine.setPricePrecision(config.pricePrecision);\n this.crosshairHandler.setPricePrecision(config.pricePrecision);\n }\n\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n getMarket(): MarketConfig | null {\n return this.marketConfig;\n }\n\n setPriceLimits(referencePrice: number): void {\n if (!this.marketConfig) return;\n const limits = computePriceLimits(referencePrice, this.marketConfig);\n if (limits) {\n this.marketConfig.priceLimits = {\n ...this.marketConfig.priceLimits!,\n referencePrice,\n };\n }\n this.engine.requestRender();\n }\n\n // --- Features ---\n\n /** Get the resolved feature configuration */\n getFeatures(): Readonly<Required<FeaturesConfig>> {\n return this.features;\n }\n\n /** Update feature flags at runtime. Only provided keys are changed. */\n setFeatures(patch: Partial<FeaturesConfig>): void {\n Object.assign(this.features, patch);\n\n // Apply immediate side-effects\n if (patch.crosshair === false) {\n this.crosshairTooltip.hide();\n }\n if (patch.grid !== undefined) {\n this.engine.requestRender(LayerType.Background);\n }\n if (patch.volume !== undefined) {\n this.volumeRenderer.setVisible(patch.volume);\n this.engine.requestRender(LayerType.Main);\n }\n if (patch.drawings === false) {\n this.drawingManager.setActiveTool(null);\n }\n if (patch.trading === false) {\n this.tradingManager.setOrders([]);\n this.tradingManager.setPositions([]);\n }\n if (patch.keyboard !== undefined) {\n this.keyboardHandler?.setEnabled(patch.keyboard);\n }\n\n this.engine.requestRender();\n }\n\n // --- Lifecycle ---\n\n resize(): void {\n const size = this.engine.dprManager.readContainerSize();\n if (size.width <= 0 || size.height <= 0) return;\n this.containerSizeCache = size;\n this.containerSizeCacheTime = Date.now();\n // Resize canvas layers immediately (don't wait for DPRManager's debounced callback)\n const dpr = this.engine.dprManager.getDpr();\n this.engine.layerManager.resize(size, dpr);\n // Check if viewport was at the end before resize\n const wasAtEnd = this.viewport.isAtEnd();\n this.viewport.resize(size.width, size.height);\n this.layoutManager.resize(size.width, size.height);\n this.updateViewportAndRender(wasAtEnd);\n this.eventBus.emit('resize', size);\n }\n\n destroy(): void {\n if (this.countdownInterval) clearInterval(this.countdownInterval);\n this.disableAutoSave();\n this.disconnectStream();\n if (this.onWindowKeyDown) {\n window.removeEventListener('keydown', this.onWindowKeyDown);\n this.onWindowKeyDown = null;\n }\n this.keyboardHandler = null;\n this.interactionManager.detach();\n this.tradingManager.destroy();\n this.animator.dispose();\n this.crosshairTooltip.destroy();\n this.replayManager.dispose();\n this.undoRedoManager.clear();\n this.engine.destroy();\n this.eventBus.destroy();\n this.container.innerHTML = '';\n }\n\n // --- Internal ---\n\n private createChartRenderer(type: ChartType): ChartRendererInterface {\n switch (type) {\n case 'candlestick': return new CandlestickRenderer();\n case 'heikinAshi': return new CandlestickRenderer(); // Same renderer, different data\n case 'line': return new LineRenderer();\n case 'area': return new AreaRenderer();\n case 'bar': return new BarRenderer();\n case 'hollowCandle': return new HollowCandleRenderer();\n case 'baseline': return new BaselineRenderer();\n case 'renko': return new RenkoRenderer();\n case 'lineBreak': return new CandlestickRenderer(); // Candle renderer on transformed data\n case 'kagi': return new KagiRenderer();\n case 'pointAndFigure': return new PointAndFigureRenderer();\n default: return new CandlestickRenderer();\n }\n }\n\n /** Cached display data. Invalidated when raw data or chart type changes. */\n private getDisplayData(): DataSeries {\n if (this.displayDataCache) return this.displayDataCache;\n\n const raw = this.dataManager.getData();\n if (raw.length === 0) return raw;\n\n let result: DataSeries;\n switch (this.options.chartType) {\n case 'heikinAshi': result = toHeikinAshi(raw); break;\n case 'renko': result = toRenko(raw, { brickSize: 0, useATR: true, atrPeriod: 14 }); break;\n case 'lineBreak': result = toLineBreak(raw, 3); break;\n case 'kagi': result = toKagi(raw, 4); break;\n case 'pointAndFigure': {\n const avgPrice = raw.reduce((s, b) => s + b.close, 0) / raw.length;\n result = toPointAndFigure(raw, avgPrice * 0.01, 3);\n break;\n }\n default: result = raw;\n }\n this.displayDataCache = result;\n return result;\n }\n\n /** Lightweight render for streaming updates. No layout resolve, no indicator recalc. */\n private scheduleRender(): void {\n if (this.renderScheduled) return;\n this.renderScheduled = true;\n requestAnimationFrame(() => {\n this.renderScheduled = false;\n const displayData = this.getDisplayData();\n this.viewport.updateData(displayData, this.options.autoScale !== false);\n this.syncRenderContext();\n this.engine.requestRender();\n });\n }\n\n /** Full update: resolve layout, update viewport, sync context, request render. */\n private updateViewportAndRender(scrollToEnd = false): void {\n // Invalidate layout cache\n this.resolvedLayoutCache = null;\n this.panelInfoCache = null;\n\n const resolved = this.getResolvedLayout();\n this.viewport.setChartRect(resolved.mainChartRect);\n\n const displayData = this.getDisplayData();\n this.viewport.updateData(displayData, this.options.autoScale !== false);\n\n // Expand price range to include overlay indicator values (BB, Ichimoku, etc.)\n if (this.options.autoScale !== false) {\n const vs = this.viewport.getState();\n const overlayRange = this.indicatorEngine.getOverlayPriceRange(\n vs.visibleRange.from,\n Math.min(vs.visibleRange.to, displayData.length - 1),\n );\n if (overlayRange) {\n const current = vs.priceRange;\n const expandedMin = Math.min(current.min, overlayRange.min);\n const expandedMax = Math.max(current.max, overlayRange.max);\n if (expandedMin < current.min || expandedMax > current.max) {\n const range = expandedMax - expandedMin || 1;\n this.viewport.setPriceRange(\n expandedMin - range * 0.02,\n expandedMax + range * 0.02,\n );\n }\n }\n }\n\n // Scroll to end AFTER updateData so dataLength is current\n if (scrollToEnd) this.viewport.scrollToEnd();\n\n this.syncRenderContext();\n this.engine.requestRender();\n }\n\n private getResolvedLayout() {\n if (!this.resolvedLayoutCache) {\n this.resolvedLayoutCache = this.layoutManager.resolve();\n }\n return this.resolvedLayoutCache;\n }\n\n /** Cache container size for 500ms to avoid layout thrashing on rapid calls */\n private cachedContainerSize(): { width: number; height: number } {\n const now = Date.now();\n if (!this.containerSizeCache || now - this.containerSizeCacheTime > 500) {\n this.containerSizeCache = this.engine.dprManager.getContainerSize();\n this.containerSizeCacheTime = now;\n }\n return this.containerSizeCache;\n }\n\n private buildPanelRenderInfos(): import('@tradecanvas/core').PanelRenderInfo[] {\n if (this.panelInfoCache) return this.panelInfoCache;\n\n const resolved = this.getResolvedLayout();\n const mainVP = this.viewport.getState();\n\n const panels = resolved.panels.map((panel) => {\n const output = this.indicatorEngine.getOutput(panel.config.id);\n let min = 0, max = 100;\n\n if (output) {\n let vMin = Infinity, vMax = -Infinity;\n const { from, to } = mainVP.visibleRange;\n let idx = 0;\n for (const [, val] of output.values) {\n if (idx >= from && idx <= to) {\n for (const key in val) {\n const v = val[key];\n if (v !== undefined) {\n if (v < vMin) vMin = v;\n if (v > vMax) vMax = v;\n }\n }\n }\n idx++;\n }\n if (vMin !== Infinity) {\n const range = vMax - vMin || 1;\n min = vMin - range * 0.1;\n max = vMax + range * 0.1;\n }\n }\n\n // Inset the indicator drawing area below the panel header (title + divider)\n const PANEL_HEADER_HEIGHT = 20;\n const insetRect = {\n x: panel.rect.x,\n y: panel.rect.y + PANEL_HEADER_HEIGHT,\n width: panel.rect.width,\n height: Math.max(0, panel.rect.height - PANEL_HEADER_HEIGHT),\n };\n\n return {\n instanceId: panel.config.id,\n rect: panel.rect,\n viewport: {\n ...mainVP,\n chartRect: insetRect,\n priceRange: { min, max },\n },\n };\n });\n\n this.panelInfoCache = panels;\n return panels;\n }\n\n private syncRenderContext(): void {\n const resolved = this.getResolvedLayout();\n const panels = this.features.indicators ? this.buildPanelRenderInfos() : [];\n\n // Compute where the time axis should render: below main chart + all bottom panels\n const bottomPanelHeight = resolved.panels\n .filter(p => p.config.position === 'bottom')\n .reduce((sum, p) => sum + p.rect.height, 0);\n const timeAxisY = resolved.mainChartRect.y + resolved.mainChartRect.height + bottomPanelHeight;\n\n this.engine.setRenderContext({\n chartRenderer: this.chartRenderer,\n gridRenderer: this.features.grid ? this.gridRenderer : null,\n priceAxis: this.features.priceAxis ? this.priceAxis : null,\n timeAxis: this.features.timeAxis ? this.timeAxis : null,\n crosshairHandler: this.features.crosshair ? this.crosshairHandler : null,\n indicatorEngine: this.features.indicators ? this.indicatorEngine : null,\n drawingRenderer: this.features.drawings ? this.drawingRenderer : null,\n tradingRenderer: this.features.trading ? this.tradingRenderer : null,\n currentPriceLine: this.streamManager?.priceLine ?? this.currentPriceLine,\n chartLegend: this.features.legend ? this.chartLegend : null,\n volumeRenderer: this.features.volume ? this.volumeRenderer : null,\n watermark: this.features.watermark ? this.watermark : null,\n barCountdown: this.barCountdown,\n sessionBreaks: this.sessionBreaks,\n compareRenderer: this.compareRenderer,\n panels,\n priceLimits: this.buildPriceLimits(),\n timeAxisY,\n viewport: this.viewport.getState(),\n theme: this.themeManager.getTheme(),\n data: this.getDisplayData(),\n numberLocale: this.numberLocale,\n });\n }\n\n private timeframeToMs(tf: string): number {\n const match = tf.match(/^(\\d+)([smhdwMy])$/);\n if (!match) return 0;\n const n = parseInt(match[1], 10);\n switch (match[2]) {\n case 's': return n * 1000;\n case 'm': return n * 60_000;\n case 'h': return n * 3_600_000;\n case 'd': return n * 86_400_000;\n case 'w': return n * 604_800_000;\n case 'M': return n * 2_592_000_000;\n default: return 0;\n }\n }\n\n private buildPriceLimits() {\n if (!this.marketConfig?.priceLimits?.enabled || !this.marketConfig.priceLimits.referencePrice) return null;\n const limits = computePriceLimits(this.marketConfig.priceLimits.referencePrice, this.marketConfig);\n if (!limits) return null;\n return {\n ...limits,\n colors: this.marketConfig.colorScheme ? {\n ceiling: this.marketConfig.colorScheme.ceiling,\n floor: this.marketConfig.colorScheme.floor,\n reference: this.marketConfig.colorScheme.reference,\n } : undefined,\n };\n }\n}\n","import type { SparklineOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\n\nexport class SparklineChart extends BaseFinanceChart {\n private options: SparklineOptions;\n\n constructor(container: HTMLElement, options: SparklineOptions) {\n super(container, options.theme);\n this.options = options;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderSparkline(ctx, width, height, this.options, theme);\n }\n\n update(data: number[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<SparklineOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n}\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\n\nexport class DepthChart extends BaseFinanceChart {\n private options: DepthChartOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: DepthChartOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderDepthChart(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: DepthData): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<DepthChartOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\n\nexport class EquityCurveChart extends BaseFinanceChart {\n private options: EquityCurveOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: EquityCurveOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\n this.options = { ...this.options, data };\n if (benchmark !== undefined) {\n this.options = { ...this.options, benchmark };\n }\n this.requestRender();\n }\n\n setOptions(opts: Partial<EquityCurveOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\nimport {\n BaseFinanceChart,\n FinanceCrosshair,\n layoutUniformGrid,\n layoutSquarifiedTreemap,\n renderHeatmap,\n} from '@tradecanvas/core';\nimport type { LayoutRect } from '@tradecanvas/core';\n\nexport class HeatmapChart extends BaseFinanceChart {\n private options: HeatmapOptions;\n private crosshair: FinanceCrosshair | null = null;\n private cachedRects: LayoutRect[] = [];\n private currentData: HeatmapCell[] = [];\n private lastLayoutWidth = 0;\n private lastLayoutHeight = 0;\n private handleClick: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: HeatmapOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentData = options.data ?? [];\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n if (options.onCellClick) {\n this.handleClick = (e: MouseEvent) => {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n this.onCanvasClick(x, y);\n };\n this.canvas.addEventListener('click', this.handleClick);\n }\n\n this.recomputeLayout();\n this.requestRender();\n }\n\n private recomputeLayout(): void {\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\n const padding = this.options.cellPadding ?? 2;\n this.lastLayoutWidth = this.width;\n this.lastLayoutHeight = this.height;\n\n if (this.options.weighted) {\n const weighted = this.currentData.map(c => ({\n id: c.id,\n weight: c.weight ?? (Math.abs(c.value) || 1),\n }));\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\n } else {\n this.cachedRects = layoutUniformGrid(\n this.currentData.map(c => ({ id: c.id })),\n bounds,\n padding,\n );\n }\n }\n\n private onCanvasClick(x: number, y: number): void {\n if (!this.options.onCellClick) return;\n\n for (const lr of this.cachedRects) {\n const r = lr.rect;\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\n const cell = this.currentData.find(c => c.id === lr.id);\n if (cell) this.options.onCellClick(cell);\n return;\n }\n }\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\n this.recomputeLayout();\n }\n\n const pos = this.crosshair?.getPosition() ?? null;\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\n }\n\n update(data: HeatmapCell[]): void {\n this.currentData = data;\n this.options = { ...this.options, data };\n this.recomputeLayout();\n this.requestRender();\n }\n\n setOptions(opts: Partial<HeatmapOptions>): void {\n this.options = { ...this.options, ...opts };\n if (opts.data) {\n this.currentData = opts.data;\n }\n this.recomputeLayout();\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n if (this.handleClick) {\n this.canvas.removeEventListener('click', this.handleClick);\n }\n super.destroy();\n }\n}\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\n\nexport class WaterfallChart extends BaseFinanceChart {\n private options: WaterfallOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: WaterfallOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderWaterfall(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: WaterfallBar[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<WaterfallOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\n\nconst DEFAULT_ANIMATION_MS = 500;\n\nfunction easeOutCubic(t: number): number {\n const inv = 1 - t;\n return 1 - inv * inv * inv;\n}\n\nexport class GaugeChart extends BaseFinanceChart {\n private options: GaugeOptions;\n private currentValue: number;\n private targetValue: number;\n private animationStart: number | null = null;\n private animationFrom = 0;\n private animationFrameId: number | null = null;\n\n constructor(container: HTMLElement, options: GaugeOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentValue = options.value;\n this.targetValue = options.value;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\n }\n\n setValue(value: number): void {\n const animate = this.options.animate !== false;\n if (!animate) {\n this.cancelAnimation();\n this.currentValue = value;\n this.targetValue = value;\n this.options = { ...this.options, value };\n this.requestRender();\n return;\n }\n\n this.targetValue = value;\n this.animationFrom = this.currentValue;\n this.animationStart = performance.now();\n this.options = { ...this.options, value };\n this.startAnimationLoop();\n }\n\n setOptions(opts: Partial<GaugeOptions>): void {\n const next = { ...this.options, ...opts };\n // If `value` is part of the partial, route through animation path\n if (opts.value !== undefined && opts.value !== this.targetValue) {\n this.options = next;\n this.setValue(opts.value);\n return;\n }\n this.options = next;\n this.requestRender();\n }\n\n private startAnimationLoop(): void {\n if (this.animationFrameId !== null) return;\n const step = (): void => {\n this.animationFrameId = null;\n if (this.animationStart === null) return;\n\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\n const elapsed = performance.now() - this.animationStart;\n const t = Math.min(1, elapsed / Math.max(1, duration));\n const eased = easeOutCubic(t);\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\n\n this.requestRender();\n\n if (t < 1) {\n this.animationFrameId = requestAnimationFrame(step);\n } else {\n this.currentValue = this.targetValue;\n this.animationStart = null;\n }\n };\n this.animationFrameId = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.animationStart = null;\n }\n\n destroy(): void {\n this.cancelAnimation();\n super.destroy();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.ts"],"sourcesContent":["import type { SparklineOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\n\nexport class SparklineChart extends BaseFinanceChart {\n private options: SparklineOptions;\n\n constructor(container: HTMLElement, options: SparklineOptions) {\n super(container, options.theme);\n this.options = options;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderSparkline(ctx, width, height, this.options, theme);\n }\n\n update(data: number[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<SparklineOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n}\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\n\nexport class DepthChart extends BaseFinanceChart {\n private options: DepthChartOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: DepthChartOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderDepthChart(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: DepthData): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<DepthChartOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\n\nexport class EquityCurveChart extends BaseFinanceChart {\n private options: EquityCurveOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: EquityCurveOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\n this.options = { ...this.options, data };\n if (benchmark !== undefined) {\n this.options = { ...this.options, benchmark };\n }\n this.requestRender();\n }\n\n setOptions(opts: Partial<EquityCurveOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\nimport {\n BaseFinanceChart,\n FinanceCrosshair,\n layoutUniformGrid,\n layoutSquarifiedTreemap,\n renderHeatmap,\n} from '@tradecanvas/core';\nimport type { LayoutRect } from '@tradecanvas/core';\n\nexport class HeatmapChart extends BaseFinanceChart {\n private options: HeatmapOptions;\n private crosshair: FinanceCrosshair | null = null;\n private cachedRects: LayoutRect[] = [];\n private currentData: HeatmapCell[] = [];\n private lastLayoutWidth = 0;\n private lastLayoutHeight = 0;\n private handleClick: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: HeatmapOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentData = options.data ?? [];\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n if (options.onCellClick) {\n this.handleClick = (e: MouseEvent) => {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n this.onCanvasClick(x, y);\n };\n this.canvas.addEventListener('click', this.handleClick);\n }\n\n this.recomputeLayout();\n this.requestRender();\n }\n\n private recomputeLayout(): void {\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\n const padding = this.options.cellPadding ?? 2;\n this.lastLayoutWidth = this.width;\n this.lastLayoutHeight = this.height;\n\n if (this.options.weighted) {\n const weighted = this.currentData.map(c => ({\n id: c.id,\n weight: c.weight ?? (Math.abs(c.value) || 1),\n }));\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\n } else {\n this.cachedRects = layoutUniformGrid(\n this.currentData.map(c => ({ id: c.id })),\n bounds,\n padding,\n );\n }\n }\n\n private onCanvasClick(x: number, y: number): void {\n if (!this.options.onCellClick) return;\n\n for (const lr of this.cachedRects) {\n const r = lr.rect;\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\n const cell = this.currentData.find(c => c.id === lr.id);\n if (cell) this.options.onCellClick(cell);\n return;\n }\n }\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\n this.recomputeLayout();\n }\n\n const pos = this.crosshair?.getPosition() ?? null;\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\n }\n\n update(data: HeatmapCell[]): void {\n this.currentData = data;\n this.options = { ...this.options, data };\n this.recomputeLayout();\n this.requestRender();\n }\n\n setOptions(opts: Partial<HeatmapOptions>): void {\n this.options = { ...this.options, ...opts };\n if (opts.data) {\n this.currentData = opts.data;\n }\n this.recomputeLayout();\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n if (this.handleClick) {\n this.canvas.removeEventListener('click', this.handleClick);\n }\n super.destroy();\n }\n}\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\n\nexport class WaterfallChart extends BaseFinanceChart {\n private options: WaterfallOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: WaterfallOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderWaterfall(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: WaterfallBar[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<WaterfallOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\n\nconst DEFAULT_ANIMATION_MS = 500;\n\nfunction easeOutCubic(t: number): number {\n const inv = 1 - t;\n return 1 - inv * inv * inv;\n}\n\nexport class GaugeChart extends BaseFinanceChart {\n private options: GaugeOptions;\n private currentValue: number;\n private targetValue: number;\n private animationStart: number | null = null;\n private animationFrom = 0;\n private animationFrameId: number | null = null;\n\n constructor(container: HTMLElement, options: GaugeOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentValue = options.value;\n this.targetValue = options.value;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\n }\n\n setValue(value: number): void {\n const animate = this.options.animate !== false;\n if (!animate) {\n this.cancelAnimation();\n this.currentValue = value;\n this.targetValue = value;\n this.options = { ...this.options, value };\n this.requestRender();\n return;\n }\n\n this.targetValue = value;\n this.animationFrom = this.currentValue;\n this.animationStart = performance.now();\n this.options = { ...this.options, value };\n this.startAnimationLoop();\n }\n\n setOptions(opts: Partial<GaugeOptions>): void {\n const next = { ...this.options, ...opts };\n // If `value` is part of the partial, route through animation path\n if (opts.value !== undefined && opts.value !== this.targetValue) {\n this.options = next;\n this.setValue(opts.value);\n return;\n }\n this.options = next;\n this.requestRender();\n }\n\n private startAnimationLoop(): void {\n if (this.animationFrameId !== null) return;\n const step = (): void => {\n this.animationFrameId = null;\n if (this.animationStart === null) return;\n\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\n const elapsed = performance.now() - this.animationStart;\n const t = Math.min(1, elapsed / Math.max(1, duration));\n const eased = easeOutCubic(t);\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\n\n this.requestRender();\n\n if (t < 1) {\n this.animationFrameId = requestAnimationFrame(step);\n } else {\n this.currentValue = this.targetValue;\n this.animationStart = null;\n }\n };\n this.animationFrameId = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.animationStart = null;\n }\n\n destroy(): void {\n this.cancelAnimation();\n super.destroy();\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounced auto-save scheduler. Coalesces a burst of `schedule()` calls into
|
|
3
|
+
* a single `save(key)` invocation after `delayMs` of quiet time. Pure state
|
|
4
|
+
* machine — owner injects the actual save callback so this stays testable.
|
|
5
|
+
*/
|
|
6
|
+
export declare class AutoSaveScheduler {
|
|
7
|
+
private save;
|
|
8
|
+
private timer;
|
|
9
|
+
private delayMs;
|
|
10
|
+
private key;
|
|
11
|
+
constructor(save: (key: string) => void);
|
|
12
|
+
/** Enable auto-save with the given storage key and quiet-time debounce. */
|
|
13
|
+
enable(key: string, delayMs: number): void;
|
|
14
|
+
/** Disable auto-save and cancel any pending fire. */
|
|
15
|
+
disable(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Reset the quiet-time window. If currently disabled (no key or delay ≤ 0),
|
|
18
|
+
* this is a no-op. Subsequent calls within the window restart the timer.
|
|
19
|
+
*/
|
|
20
|
+
schedule(): void;
|
|
21
|
+
/** Cancel any pending fire without changing enabled state. */
|
|
22
|
+
cancel(): void;
|
|
23
|
+
isEnabled(): boolean;
|
|
24
|
+
hasPending(): boolean;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AutoSaveScheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoSaveScheduler.d.ts","sourceRoot":"","sources":["../../src/state/AutoSaveScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,iBAAiB;IAKhB,OAAO,CAAC,IAAI;IAJxB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,GAAG,CAAuB;gBAEd,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;IAE/C,2EAA2E;IAC3E,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAK1C,qDAAqD;IACrD,OAAO,IAAI,IAAI;IAMf;;;OAGG;IACH,QAAQ,IAAI,IAAI;IAShB,8DAA8D;IAC9D,MAAM,IAAI,IAAI;IAOd,SAAS,IAAI,OAAO;IAIpB,UAAU,IAAI,OAAO;CAGtB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Theme, TimeFrame } from '@tradecanvas/commons';
|
|
2
|
+
import { Chart } from '../Chart.js';
|
|
3
|
+
import { ChartWidgetOptions } from './types.js';
|
|
4
|
+
export declare class ChartWidget {
|
|
5
|
+
private chart;
|
|
6
|
+
private state;
|
|
7
|
+
private toolbar;
|
|
8
|
+
private sidebar;
|
|
9
|
+
private settings;
|
|
10
|
+
private statusBar;
|
|
11
|
+
private root;
|
|
12
|
+
private chartContainer;
|
|
13
|
+
private destroyed;
|
|
14
|
+
private options;
|
|
15
|
+
private symbolIndex;
|
|
16
|
+
private symbols;
|
|
17
|
+
private settingsState;
|
|
18
|
+
private adapter;
|
|
19
|
+
constructor(container: HTMLElement, options?: ChartWidgetOptions);
|
|
20
|
+
setSymbol(symbol: string): Promise<void>;
|
|
21
|
+
setTimeframe(tf: TimeFrame): Promise<void>;
|
|
22
|
+
setTheme(theme: import('@tradecanvas/commons').ThemeName | Theme): void;
|
|
23
|
+
getChart(): Chart;
|
|
24
|
+
destroy(): void;
|
|
25
|
+
private handleSymbolClick;
|
|
26
|
+
private handleTimeframe;
|
|
27
|
+
private handleChartType;
|
|
28
|
+
private handleAddIndicator;
|
|
29
|
+
private handleRemoveIndicator;
|
|
30
|
+
private handleDrawingTool;
|
|
31
|
+
private handleCancelDrawing;
|
|
32
|
+
private handleToggleMagnet;
|
|
33
|
+
private handleToggleTheme;
|
|
34
|
+
private openSettings;
|
|
35
|
+
private applySettings;
|
|
36
|
+
private resetSettings;
|
|
37
|
+
private connectStream;
|
|
38
|
+
private updateUI;
|
|
39
|
+
private resolveIsDark;
|
|
40
|
+
private resolveTheme;
|
|
41
|
+
private isColorDark;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ChartWidget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartWidget.d.ts","sourceRoot":"","sources":["../../src/widget/ChartWidget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,KAAK,EAAE,kBAAkB,EAAmC,MAAM,YAAY,CAAC;AAQtF,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,OAAO,CAA2D;gBAE9D,SAAS,EAAE,WAAW,EAAE,OAAO,GAAE,kBAAuB;IAkJ9D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,QAAQ,CAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;IASvE,QAAQ,IAAI,KAAK;IAIjB,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,aAAa;YAKP,aAAa;IAwC3B,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;CAUpB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js';
|
|
2
|
+
export declare class WidgetDrawingSidebar {
|
|
3
|
+
private config;
|
|
4
|
+
private callbacks;
|
|
5
|
+
private el;
|
|
6
|
+
private groupWraps;
|
|
7
|
+
private groupButtons;
|
|
8
|
+
private cursorBtn;
|
|
9
|
+
private magnetBtn;
|
|
10
|
+
private flyoutEl;
|
|
11
|
+
constructor(host: HTMLElement, config: SidebarConfig, callbacks: SidebarCallbacks);
|
|
12
|
+
private build;
|
|
13
|
+
private showFlyout;
|
|
14
|
+
private hideFlyout;
|
|
15
|
+
update(state: WidgetState): void;
|
|
16
|
+
private divider;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=WidgetDrawingSidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetDrawingSidebar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetDrawingSidebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO/E,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAA+B;gBAEnC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB;IASjF,OAAO,CAAC,KAAK;IA8Eb,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,UAAU;IAOlB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IA4BhC,OAAO,CAAC,OAAO;IAMf,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class WidgetDropdown {
|
|
2
|
+
private trigger;
|
|
3
|
+
private panel;
|
|
4
|
+
private _isOpen;
|
|
5
|
+
private onOutsideClick;
|
|
6
|
+
private onEscapeKey;
|
|
7
|
+
private onTriggerClick;
|
|
8
|
+
constructor(trigger: HTMLElement, config?: {
|
|
9
|
+
width?: string;
|
|
10
|
+
align?: 'left' | 'right';
|
|
11
|
+
});
|
|
12
|
+
setContent(html: string): void;
|
|
13
|
+
open(): void;
|
|
14
|
+
close(): void;
|
|
15
|
+
isOpen(): boolean;
|
|
16
|
+
destroy(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=WidgetDropdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetDropdown.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetDropdown.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,cAAc,CAAa;gBAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAO;IAwC3F,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,MAAM,IAAI,OAAO;IAIjB,OAAO,IAAI,IAAI;CAMhB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ChartSettingsState, SettingsCallbacks } from './types.js';
|
|
2
|
+
export declare class WidgetSettings {
|
|
3
|
+
private callbacks;
|
|
4
|
+
private backdrop;
|
|
5
|
+
private modal;
|
|
6
|
+
private currentTab;
|
|
7
|
+
private currentSettings;
|
|
8
|
+
private bodyEl;
|
|
9
|
+
private tabButtons;
|
|
10
|
+
constructor(callbacks: SettingsCallbacks);
|
|
11
|
+
open(currentSettings: ChartSettingsState): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
private buildModal;
|
|
14
|
+
private renderTabContent;
|
|
15
|
+
private renderStyleTab;
|
|
16
|
+
private renderDisplayTab;
|
|
17
|
+
private renderScaleTab;
|
|
18
|
+
private patch;
|
|
19
|
+
private section;
|
|
20
|
+
private colorRow;
|
|
21
|
+
private toggleRow;
|
|
22
|
+
private selectRow;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=WidgetSettings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetSettings.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetSettings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMxE,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAA2B;gBAEjC,SAAS,EAAE,iBAAiB;IAIxC,IAAI,CAAC,eAAe,EAAE,kBAAkB,GAAG,IAAI;IAM/C,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,UAAU;IAuFlB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,QAAQ;IA+BhB,OAAO,CAAC,SAAS;IAoBjB,OAAO,CAAC,SAAS;IA4BjB,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class WidgetStatusBar {
|
|
2
|
+
private el;
|
|
3
|
+
private dotEl;
|
|
4
|
+
private messageEl;
|
|
5
|
+
private infoEl;
|
|
6
|
+
constructor(host: HTMLElement);
|
|
7
|
+
update(state: {
|
|
8
|
+
connectionState: string;
|
|
9
|
+
message: string;
|
|
10
|
+
symbol: string;
|
|
11
|
+
timeframe: string;
|
|
12
|
+
}): void;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=WidgetStatusBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetStatusBar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetStatusBar.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAkB;gBAEpB,IAAI,EAAE,WAAW;IAsB7B,MAAM,CAAC,KAAK,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYpG,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inject the widget stylesheet into `document.head`. Reference-counted so
|
|
3
|
+
* multiple `ChartWidget` instances share the same `<style>` tag and the last
|
|
4
|
+
* to detach removes it. CSS lives in a sibling `.css` file and is inlined at
|
|
5
|
+
* build time via Vite's `?raw` query — consumers see a plain string at runtime.
|
|
6
|
+
*/
|
|
7
|
+
export declare function injectWidgetStyles(): void;
|
|
8
|
+
export declare function removeWidgetStyles(): void;
|
|
9
|
+
//# sourceMappingURL=WidgetStyles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetStyles.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetStyles.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAQzC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ToolbarConfig, ToolbarCallbacks, WidgetState } from './types.js';
|
|
2
|
+
export declare class WidgetToolbar {
|
|
3
|
+
private config;
|
|
4
|
+
private callbacks;
|
|
5
|
+
private el;
|
|
6
|
+
private chartTypeDropdown;
|
|
7
|
+
private indicatorDropdown;
|
|
8
|
+
private tfButtons;
|
|
9
|
+
private chipsContainer;
|
|
10
|
+
private themeBtn;
|
|
11
|
+
constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks);
|
|
12
|
+
private build;
|
|
13
|
+
private buildChartTypeMenu;
|
|
14
|
+
private buildIndicatorMenu;
|
|
15
|
+
update(state: WidgetState): void;
|
|
16
|
+
private getActiveIndicatorList;
|
|
17
|
+
private sep;
|
|
18
|
+
private spacer;
|
|
19
|
+
private iconBtn;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=WidgetToolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetToolbar.d.ts","sourceRoot":"","sources":["../../src/widget/WidgetToolbar.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AAIhG,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAkC;gBAEtC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB;IASjF,OAAO,CAAC,KAAK;IA4Eb,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,kBAAkB;IA4B1B,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAwDhC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IASf,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/widget/icons.ts"],"names":[],"mappings":"AA4BA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,MAAM,CAI1D"}
|