@itssumitrai/fin-charter 0.2.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 +96 -0
- package/dist/api/chart-api.d.ts +173 -0
- package/dist/api/export.d.ts +46 -0
- package/dist/api/indicator-api.d.ts +38 -0
- package/dist/api/options.d.ts +226 -0
- package/dist/api/pane-api.d.ts +28 -0
- package/dist/api/series-api.d.ts +115 -0
- package/dist/core/accessibility.d.ts +90 -0
- package/dist/core/alert-line.d.ts +49 -0
- package/dist/core/chart-state.d.ts +39 -0
- package/dist/core/chart-sync.d.ts +83 -0
- package/dist/core/crosshair.d.ts +28 -0
- package/dist/core/css-theme.d.ts +41 -0
- package/dist/core/custom-indicator.d.ts +70 -0
- package/dist/core/data-feed.d.ts +59 -0
- package/dist/core/data-layer.d.ts +38 -0
- package/dist/core/invalidation.d.ts +24 -0
- package/dist/core/market-session.d.ts +11 -0
- package/dist/core/order-line.d.ts +134 -0
- package/dist/core/pane-divider.d.ts +22 -0
- package/dist/core/pane.d.ts +32 -0
- package/dist/core/periodicity.d.ts +6 -0
- package/dist/core/plugin.d.ts +90 -0
- package/dist/core/price-line.d.ts +17 -0
- package/dist/core/price-scale.d.ts +74 -0
- package/dist/core/replay.d.ts +73 -0
- package/dist/core/rtl.d.ts +22 -0
- package/dist/core/segment-tree.d.ts +38 -0
- package/dist/core/series-markers.d.ts +18 -0
- package/dist/core/storage-adapter.d.ts +50 -0
- package/dist/core/streaming-adapter.d.ts +102 -0
- package/dist/core/symbol-resolver.d.ts +32 -0
- package/dist/core/text-label.d.ts +72 -0
- package/dist/core/time-scale.d.ts +109 -0
- package/dist/core/types.d.ts +144 -0
- package/dist/core/undo-redo.d.ts +46 -0
- package/dist/currency/currency.d.ts +8 -0
- package/dist/currency/index.d.ts +2 -0
- package/dist/drawings/arrow.d.ts +10 -0
- package/dist/drawings/base.d.ts +79 -0
- package/dist/drawings/channel.d.ts +10 -0
- package/dist/drawings/crossline.d.ts +10 -0
- package/dist/drawings/ellipse.d.ts +10 -0
- package/dist/drawings/fib-arc.d.ts +10 -0
- package/dist/drawings/fib-fan.d.ts +12 -0
- package/dist/drawings/fib-projection.d.ts +11 -0
- package/dist/drawings/fibonacci.d.ts +11 -0
- package/dist/drawings/horizontal-line.d.ts +10 -0
- package/dist/drawings/index.d.ts +7 -0
- package/dist/drawings/measurement.d.ts +11 -0
- package/dist/drawings/pitchfork.d.ts +12 -0
- package/dist/drawings/ray.d.ts +12 -0
- package/dist/drawings/rectangle.d.ts +10 -0
- package/dist/drawings/text-annotation.d.ts +11 -0
- package/dist/drawings/trendline.d.ts +10 -0
- package/dist/drawings/vertical-line.d.ts +10 -0
- package/dist/formatting/index.d.ts +5 -0
- package/dist/formatting/price-formatter.d.ts +6 -0
- package/dist/formatting/time-formatter.d.ts +7 -0
- package/dist/formatting/volume-formatter.d.ts +1 -0
- package/dist/i18n/i18n.d.ts +6 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/locales/en.d.ts +3 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index10.js +2 -0
- package/dist/index10.js.map +1 -0
- package/dist/index100.js +2 -0
- package/dist/index100.js.map +1 -0
- package/dist/index101.js +2 -0
- package/dist/index101.js.map +1 -0
- package/dist/index102.js +2 -0
- package/dist/index102.js.map +1 -0
- package/dist/index103.js +2 -0
- package/dist/index103.js.map +1 -0
- package/dist/index104.js +2 -0
- package/dist/index104.js.map +1 -0
- package/dist/index105.js +2 -0
- package/dist/index105.js.map +1 -0
- package/dist/index106.js +2 -0
- package/dist/index106.js.map +1 -0
- package/dist/index107.js +2 -0
- package/dist/index107.js.map +1 -0
- package/dist/index108.js +2 -0
- package/dist/index108.js.map +1 -0
- package/dist/index109.js +2 -0
- package/dist/index109.js.map +1 -0
- package/dist/index11.js +2 -0
- package/dist/index11.js.map +1 -0
- package/dist/index110.js +2 -0
- package/dist/index110.js.map +1 -0
- package/dist/index111.js +2 -0
- package/dist/index111.js.map +1 -0
- package/dist/index112.js +2 -0
- package/dist/index112.js.map +1 -0
- package/dist/index113.js +2 -0
- package/dist/index113.js.map +1 -0
- package/dist/index114.js +2 -0
- package/dist/index114.js.map +1 -0
- package/dist/index115.js +2 -0
- package/dist/index115.js.map +1 -0
- package/dist/index116.js +2 -0
- package/dist/index116.js.map +1 -0
- package/dist/index117.js +2 -0
- package/dist/index117.js.map +1 -0
- package/dist/index118.js +2 -0
- package/dist/index118.js.map +1 -0
- package/dist/index119.js +2 -0
- package/dist/index119.js.map +1 -0
- package/dist/index12.js +2 -0
- package/dist/index12.js.map +1 -0
- package/dist/index120.js +2 -0
- package/dist/index120.js.map +1 -0
- package/dist/index121.js +2 -0
- package/dist/index121.js.map +1 -0
- package/dist/index122.js +2 -0
- package/dist/index122.js.map +1 -0
- package/dist/index123.js +2 -0
- package/dist/index123.js.map +1 -0
- package/dist/index124.js +2 -0
- package/dist/index124.js.map +1 -0
- package/dist/index13.js +2 -0
- package/dist/index13.js.map +1 -0
- package/dist/index14.js +2 -0
- package/dist/index14.js.map +1 -0
- package/dist/index15.js +2 -0
- package/dist/index15.js.map +1 -0
- package/dist/index16.js +2 -0
- package/dist/index16.js.map +1 -0
- package/dist/index17.js +2 -0
- package/dist/index17.js.map +1 -0
- package/dist/index18.js +2 -0
- package/dist/index18.js.map +1 -0
- package/dist/index19.js +2 -0
- package/dist/index19.js.map +1 -0
- package/dist/index2.js +2 -0
- package/dist/index2.js.map +1 -0
- package/dist/index20.js +2 -0
- package/dist/index20.js.map +1 -0
- package/dist/index21.js +2 -0
- package/dist/index21.js.map +1 -0
- package/dist/index22.js +2 -0
- package/dist/index22.js.map +1 -0
- package/dist/index23.js +2 -0
- package/dist/index23.js.map +1 -0
- package/dist/index24.js +2 -0
- package/dist/index24.js.map +1 -0
- package/dist/index25.js +2 -0
- package/dist/index25.js.map +1 -0
- package/dist/index26.js +2 -0
- package/dist/index26.js.map +1 -0
- package/dist/index27.js +2 -0
- package/dist/index27.js.map +1 -0
- package/dist/index28.js +2 -0
- package/dist/index28.js.map +1 -0
- package/dist/index29.js +2 -0
- package/dist/index29.js.map +1 -0
- package/dist/index3.js +2 -0
- package/dist/index3.js.map +1 -0
- package/dist/index30.js +2 -0
- package/dist/index30.js.map +1 -0
- package/dist/index31.js +2 -0
- package/dist/index31.js.map +1 -0
- package/dist/index32.js +2 -0
- package/dist/index32.js.map +1 -0
- package/dist/index33.js +2 -0
- package/dist/index33.js.map +1 -0
- package/dist/index34.js +2 -0
- package/dist/index34.js.map +1 -0
- package/dist/index35.js +2 -0
- package/dist/index35.js.map +1 -0
- package/dist/index36.js +2 -0
- package/dist/index36.js.map +1 -0
- package/dist/index37.js +2 -0
- package/dist/index37.js.map +1 -0
- package/dist/index38.js +2 -0
- package/dist/index38.js.map +1 -0
- package/dist/index39.js +2 -0
- package/dist/index39.js.map +1 -0
- package/dist/index4.js +2 -0
- package/dist/index4.js.map +1 -0
- package/dist/index40.js +2 -0
- package/dist/index40.js.map +1 -0
- package/dist/index41.js +2 -0
- package/dist/index41.js.map +1 -0
- package/dist/index42.js +2 -0
- package/dist/index42.js.map +1 -0
- package/dist/index43.js +2 -0
- package/dist/index43.js.map +1 -0
- package/dist/index44.js +2 -0
- package/dist/index44.js.map +1 -0
- package/dist/index45.js +2 -0
- package/dist/index45.js.map +1 -0
- package/dist/index46.js +2 -0
- package/dist/index46.js.map +1 -0
- package/dist/index47.js +2 -0
- package/dist/index47.js.map +1 -0
- package/dist/index48.js +2 -0
- package/dist/index48.js.map +1 -0
- package/dist/index49.js +2 -0
- package/dist/index49.js.map +1 -0
- package/dist/index5.js +2 -0
- package/dist/index5.js.map +1 -0
- package/dist/index50.js +2 -0
- package/dist/index50.js.map +1 -0
- package/dist/index51.js +2 -0
- package/dist/index51.js.map +1 -0
- package/dist/index52.js +2 -0
- package/dist/index52.js.map +1 -0
- package/dist/index53.js +2 -0
- package/dist/index53.js.map +1 -0
- package/dist/index54.js +2 -0
- package/dist/index54.js.map +1 -0
- package/dist/index55.js +2 -0
- package/dist/index55.js.map +1 -0
- package/dist/index56.js +2 -0
- package/dist/index56.js.map +1 -0
- package/dist/index57.js +2 -0
- package/dist/index57.js.map +1 -0
- package/dist/index58.js +2 -0
- package/dist/index58.js.map +1 -0
- package/dist/index59.js +2 -0
- package/dist/index59.js.map +1 -0
- package/dist/index6.js +2 -0
- package/dist/index6.js.map +1 -0
- package/dist/index60.js +2 -0
- package/dist/index60.js.map +1 -0
- package/dist/index61.js +2 -0
- package/dist/index61.js.map +1 -0
- package/dist/index62.js +2 -0
- package/dist/index62.js.map +1 -0
- package/dist/index63.js +2 -0
- package/dist/index63.js.map +1 -0
- package/dist/index64.js +2 -0
- package/dist/index64.js.map +1 -0
- package/dist/index65.js +3 -0
- package/dist/index65.js.map +1 -0
- package/dist/index66.js +2 -0
- package/dist/index66.js.map +1 -0
- package/dist/index67.js +2 -0
- package/dist/index67.js.map +1 -0
- package/dist/index68.js +2 -0
- package/dist/index68.js.map +1 -0
- package/dist/index69.js +2 -0
- package/dist/index69.js.map +1 -0
- package/dist/index7.js +2 -0
- package/dist/index7.js.map +1 -0
- package/dist/index70.js +2 -0
- package/dist/index70.js.map +1 -0
- package/dist/index71.js +2 -0
- package/dist/index71.js.map +1 -0
- package/dist/index72.js +2 -0
- package/dist/index72.js.map +1 -0
- package/dist/index73.js +2 -0
- package/dist/index73.js.map +1 -0
- package/dist/index74.js +2 -0
- package/dist/index74.js.map +1 -0
- package/dist/index75.js +2 -0
- package/dist/index75.js.map +1 -0
- package/dist/index76.js +2 -0
- package/dist/index76.js.map +1 -0
- package/dist/index77.js +2 -0
- package/dist/index77.js.map +1 -0
- package/dist/index78.js +2 -0
- package/dist/index78.js.map +1 -0
- package/dist/index79.js +2 -0
- package/dist/index79.js.map +1 -0
- package/dist/index8.js +2 -0
- package/dist/index8.js.map +1 -0
- package/dist/index80.js +2 -0
- package/dist/index80.js.map +1 -0
- package/dist/index81.js +2 -0
- package/dist/index81.js.map +1 -0
- package/dist/index82.js +2 -0
- package/dist/index82.js.map +1 -0
- package/dist/index83.js +2 -0
- package/dist/index83.js.map +1 -0
- package/dist/index84.js +2 -0
- package/dist/index84.js.map +1 -0
- package/dist/index85.js +2 -0
- package/dist/index85.js.map +1 -0
- package/dist/index86.js +2 -0
- package/dist/index86.js.map +1 -0
- package/dist/index87.js +2 -0
- package/dist/index87.js.map +1 -0
- package/dist/index88.js +2 -0
- package/dist/index88.js.map +1 -0
- package/dist/index89.js +2 -0
- package/dist/index89.js.map +1 -0
- package/dist/index9.js +2 -0
- package/dist/index9.js.map +1 -0
- package/dist/index90.js +2 -0
- package/dist/index90.js.map +1 -0
- package/dist/index91.js +2 -0
- package/dist/index91.js.map +1 -0
- package/dist/index92.js +2 -0
- package/dist/index92.js.map +1 -0
- package/dist/index93.js +2 -0
- package/dist/index93.js.map +1 -0
- package/dist/index94.js +2 -0
- package/dist/index94.js.map +1 -0
- package/dist/index95.js +2 -0
- package/dist/index95.js.map +1 -0
- package/dist/index96.js +2 -0
- package/dist/index96.js.map +1 -0
- package/dist/index97.js +2 -0
- package/dist/index97.js.map +1 -0
- package/dist/index98.js +2 -0
- package/dist/index98.js.map +1 -0
- package/dist/index99.js +2 -0
- package/dist/index99.js.map +1 -0
- package/dist/indicators/adx.d.ts +6 -0
- package/dist/indicators/aroon.d.ts +5 -0
- package/dist/indicators/atr.d.ts +1 -0
- package/dist/indicators/awesome-oscillator.d.ts +1 -0
- package/dist/indicators/bollinger.d.ts +6 -0
- package/dist/indicators/cci.d.ts +1 -0
- package/dist/indicators/chaikin-mf.d.ts +1 -0
- package/dist/indicators/choppiness.d.ts +1 -0
- package/dist/indicators/coppock.d.ts +1 -0
- package/dist/indicators/donchian.d.ts +6 -0
- package/dist/indicators/elder-force.d.ts +1 -0
- package/dist/indicators/ema.d.ts +1 -0
- package/dist/indicators/ichimoku.d.ts +8 -0
- package/dist/indicators/index.d.ts +31 -0
- package/dist/indicators/keltner.d.ts +6 -0
- package/dist/indicators/linear-regression.d.ts +1 -0
- package/dist/indicators/macd.d.ts +6 -0
- package/dist/indicators/mfi.d.ts +1 -0
- package/dist/indicators/obv.d.ts +1 -0
- package/dist/indicators/parabolic-sar.d.ts +1 -0
- package/dist/indicators/pivot-points.d.ts +10 -0
- package/dist/indicators/roc.d.ts +1 -0
- package/dist/indicators/rsi.d.ts +1 -0
- package/dist/indicators/sma.d.ts +1 -0
- package/dist/indicators/stochastic.d.ts +5 -0
- package/dist/indicators/supertrend.d.ts +5 -0
- package/dist/indicators/trix.d.ts +5 -0
- package/dist/indicators/utils.d.ts +20 -0
- package/dist/indicators/volume-profile.d.ts +37 -0
- package/dist/indicators/volume.d.ts +1 -0
- package/dist/indicators/vwap.d.ts +1 -0
- package/dist/indicators/vwma.d.ts +1 -0
- package/dist/indicators/williams-r.d.ts +1 -0
- package/dist/interactions/axis-drag.d.ts +24 -0
- package/dist/interactions/context-menu-handler.d.ts +42 -0
- package/dist/interactions/crosshair.d.ts +20 -0
- package/dist/interactions/drawing-handler.d.ts +39 -0
- package/dist/interactions/event-router.d.ts +37 -0
- package/dist/interactions/keyboard-nav.d.ts +11 -0
- package/dist/interactions/pan-zoom.d.ts +39 -0
- package/dist/interactions/range-selection.d.ts +103 -0
- package/dist/interactions/touch-gestures.d.ts +36 -0
- package/dist/logo.svg +40 -0
- package/dist/market/exchange-map.d.ts +3 -0
- package/dist/market/index.d.ts +4 -0
- package/dist/market/market-calendar.d.ts +4 -0
- package/dist/market/market-definition.d.ts +22 -0
- package/dist/mockServiceWorker.js +349 -0
- package/dist/renderers/area.d.ts +17 -0
- package/dist/renderers/bar-ohlc.d.ts +17 -0
- package/dist/renderers/baseline-delta-mountain.d.ts +22 -0
- package/dist/renderers/baseline.d.ts +19 -0
- package/dist/renderers/candlestick.d.ts +21 -0
- package/dist/renderers/canvas-renderer.d.ts +28 -0
- package/dist/renderers/colored-line.d.ts +15 -0
- package/dist/renderers/colored-mountain.d.ts +18 -0
- package/dist/renderers/column.d.ts +14 -0
- package/dist/renderers/high-low.d.ts +14 -0
- package/dist/renderers/histogram.d.ts +16 -0
- package/dist/renderers/hlc-area.d.ts +16 -0
- package/dist/renderers/hollow-candle.d.ts +18 -0
- package/dist/renderers/kagi.d.ts +22 -0
- package/dist/renderers/line-break.d.ts +20 -0
- package/dist/renderers/line.d.ts +17 -0
- package/dist/renderers/point-figure.d.ts +20 -0
- package/dist/renderers/renderer.d.ts +59 -0
- package/dist/renderers/renko.d.ts +24 -0
- package/dist/renderers/step-line.d.ts +14 -0
- package/dist/renderers/text-cache.d.ts +23 -0
- package/dist/renderers/volume-candle.d.ts +20 -0
- package/dist/renderers/webgl/area-webgl.d.ts +28 -0
- package/dist/renderers/webgl/candlestick-webgl.d.ts +30 -0
- package/dist/renderers/webgl/index.d.ts +7 -0
- package/dist/renderers/webgl/line-webgl.d.ts +23 -0
- package/dist/renderers/webgl/webgl-utils.d.ts +23 -0
- package/dist/timezone/index.d.ts +2 -0
- package/dist/timezone/timezone.d.ts +12 -0
- package/dist/transforms/aggregate.d.ts +2 -0
- package/dist/transforms/heikin-ashi.d.ts +2 -0
- package/dist/transforms/index.d.ts +2 -0
- package/dist/ui/context-menu.d.ts +14 -0
- package/dist/ui/hud.d.ts +43 -0
- package/dist/ui/settings-popup.d.ts +15 -0
- package/package.json +129 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index106.js","names":[],"sources":["../src/api/chart-api.ts"],"sourcesContent":["import type {\n Bar,\n ColumnStore,\n DeepPartial,\n IRenderTarget,\n SeriesType,\n VisibleRange,\n} from '../core/types';\nimport { InvalidationLevel } from '../core/types';\nimport { TimeScale } from '../core/time-scale';\nimport { PriceScale } from '../core/price-scale';\nimport { Crosshair, type CrosshairState } from '../core/crosshair';\nimport { InvalidateMask } from '../core/invalidation';\nimport { DataLayer } from '../core/data-layer';\nimport type { SeriesMarker } from '../core/series-markers';\nimport { type ChartState, CHART_STATE_VERSION, validateChartState } from '../core/chart-state';\nimport { Pane } from '../core/pane';\nimport { PaneDivider, DIVIDER_HEIGHT } from '../core/pane-divider';\nimport { AlertLine, type AlertLineOptions } from '../core/alert-line';\nimport { TextLabel, type TextLabelOptions } from '../core/text-label';\nimport { UndoRedoManager, type Command } from '../core/undo-redo';\nimport {\n RangeSelectionHandler,\n MeasureHandler,\n type RangeSelectionCallback,\n type MeasureCallback,\n} from '../interactions/range-selection';\nimport { EventRouter } from '../interactions/event-router';\nimport { PanZoomHandler } from '../interactions/pan-zoom';\nimport { CrosshairHandler } from '../interactions/crosshair';\nimport { ContextMenuHandler } from '../interactions/context-menu-handler';\nimport type { ContextMenuCallbacks } from '../interactions/context-menu-handler';\n\nimport { DrawingHandler } from '../interactions/drawing-handler';\nimport type { AnchorPoint, DrawingOptions, SerializedDrawing, DrawingPrimitive, DrawingContext } from '../drawings/index';\nimport { DRAWING_REGISTRY, createBuiltinDrawing, BaseDrawing } from '../drawings/index';\nimport type { ISeriesPrimitive } from '../core/types';\n\nimport { HudManager } from '../ui/hud';\nimport type { SettingsField } from '../ui/settings-popup';\n\nimport { CandlestickRenderer } from '../renderers/candlestick';\nimport { LineRenderer } from '../renderers/line';\nimport { AreaRenderer } from '../renderers/area';\nimport { BarOHLCRenderer } from '../renderers/bar-ohlc';\nimport { BaselineRenderer } from '../renderers/baseline';\nimport { HollowCandleRenderer } from '../renderers/hollow-candle';\nimport { HistogramRenderer } from '../renderers/histogram';\nimport { StepLineRenderer } from '../renderers/step-line';\nimport { ColoredLineRenderer } from '../renderers/colored-line';\nimport { ColoredMountainRenderer } from '../renderers/colored-mountain';\nimport { HLCAreaRenderer } from '../renderers/hlc-area';\nimport { HighLowRenderer } from '../renderers/high-low';\nimport { ColumnRenderer } from '../renderers/column';\nimport { VolumeCandleRenderer } from '../renderers/volume-candle';\nimport { BaselineDeltaMountainRenderer } from '../renderers/baseline-delta-mountain';\nimport { RenkoRenderer } from '../renderers/renko';\nimport { KagiRenderer } from '../renderers/kagi';\nimport { LineBreakRenderer } from '../renderers/line-break';\nimport { PointFigureRenderer } from '../renderers/point-figure';\n\nimport { isWebGLAvailable, CandlestickWebGLRenderer, LineWebGLRenderer, AreaWebGLRenderer } from '../renderers/webgl/index';\n\nimport {\n exportCSV as exportCSVFn,\n exportSVG as exportSVGFn,\n exportPDF as exportPDFFn,\n type CSVExportOptions,\n type PDFExportOptions,\n type SeriesInfo,\n type IndicatorInfo,\n} from './export';\n\nimport type { ISeriesApi } from './series-api';\nimport { SeriesApi } from './series-api';\nimport type { IPaneApi } from './pane-api';\nimport { PaneApi } from './pane-api';\nimport type { IIndicatorApi } from './indicator-api';\nimport { IndicatorApi } from './indicator-api';\nimport {\n type ChartOptions,\n type CandlestickSeriesOptions,\n type LineSeriesOptions,\n type AreaSeriesOptions,\n type BarSeriesOptions,\n type BaselineSeriesOptions,\n type HollowCandleSeriesOptions,\n type HistogramSeriesOptions,\n type PaneOptions,\n type SeriesOptionsMap,\n type SeriesOptions,\n type IndicatorType,\n type IndicatorOptions,\n DEFAULT_CHART_OPTIONS,\n DEFAULT_INDICATOR_PARAMS,\n OVERLAY_INDICATORS,\n DARK_THEME,\n LIGHT_THEME,\n COLORFUL_THEME,\n mergeOptions,\n} from './options';\n\nimport { computeSMA } from '../indicators/sma';\nimport { computeEMA } from '../indicators/ema';\nimport { computeRSI } from '../indicators/rsi';\nimport { computeHeikinAshi } from '../transforms/heikin-ashi';\nimport { computeMACD } from '../indicators/macd';\nimport { computeBollinger } from '../indicators/bollinger';\nimport { computeVWAP } from '../indicators/vwap';\nimport { computeStochastic } from '../indicators/stochastic';\nimport { computeATR } from '../indicators/atr';\nimport { computeADX } from '../indicators/adx';\nimport { computeOBV } from '../indicators/obv';\nimport { computeWilliamsR } from '../indicators/williams-r';\nimport { computeIchimoku } from '../indicators/ichimoku';\nimport { computeParabolicSAR } from '../indicators/parabolic-sar';\nimport { computeKeltner } from '../indicators/keltner';\nimport { computeDonchian } from '../indicators/donchian';\nimport { computeCCI } from '../indicators/cci';\nimport { computePivotPoints } from '../indicators/pivot-points';\nimport { computeAroon } from '../indicators/aroon';\nimport { computeAwesomeOscillator } from '../indicators/awesome-oscillator';\nimport { computeChaikinMF } from '../indicators/chaikin-mf';\nimport { computeCoppock } from '../indicators/coppock';\nimport { computeElderForce } from '../indicators/elder-force';\nimport { computeTRIX } from '../indicators/trix';\nimport { computeSupertrend } from '../indicators/supertrend';\nimport { computeVWMA } from '../indicators/vwma';\nimport { computeChoppiness } from '../indicators/choppiness';\nimport { computeMFI } from '../indicators/mfi';\nimport { computeROC } from '../indicators/roc';\nimport { computeLinearRegression } from '../indicators/linear-regression';\nimport type { Periodicity } from '../core/periodicity';\nimport type { MarketSession } from '../core/market-session';\n\nimport { createPriceFormatter } from '../formatting/price-formatter';\nimport { createTimeFormatter } from '../formatting/time-formatter';\nimport { formatVolume } from '../formatting/volume-formatter';\n\n// ─── Axis constants ────────────────────────────────────────────────────────\n\nconst PRICE_AXIS_WIDTH = 60;\nconst TIME_AXIS_HEIGHT = 28;\n\n// ─── Crosshair event callback type ─────────────────────────────────────────\n\nexport type CrosshairMoveCallback = (state: CrosshairState | null) => void;\nexport type ClickCallback = (state: { x: number; y: number; time: number; price: number }) => void;\nexport type DblClickCallback = (state: { x: number; y: number; time: number; price: number }) => void;\n\n// ─── IChartApi ──────────────────────────────────────────────────────────────\n\nexport type VisibleRangeChangeCallback = (range: { from: number; to: number } | null) => void;\n\n// ─── Event callback types ─────────────────────────────────────────────────\n\nexport type DrawingEventType = 'created' | 'modified' | 'removed';\nexport type DrawingEventCallback = (event: { type: DrawingEventType; drawingId: string; drawingType: string }) => void;\n\nexport type IndicatorEventType = 'added' | 'removed';\nexport type IndicatorEventCallback = (event: { type: IndicatorEventType; indicatorId: string; indicatorType: string; paneId: string }) => void;\n\nexport type ResizeCallback = (size: { width: number; height: number }) => void;\n\nexport type SymbolChangeCallback = (symbol: { previous: string; current: string }) => void;\n\nexport type ChartTypeChangeCallback = (chartType: { seriesType: SeriesType }) => void;\n\nexport type PreferencesChangeCallback = (options: DeepPartial<ChartOptions>) => void;\n\nexport type LayoutChangeAction = 'pane-added' | 'pane-removed';\nexport type LayoutChangeCallback = (event: { action: LayoutChangeAction; paneId: string }) => void;\n\n// ─── IDrawingApi ──────────────────────────────────────────────────────────────\n\nexport interface IDrawingApi {\n readonly id: string;\n drawingType(): string;\n points(): AnchorPoint[];\n applyOptions(options: Partial<DrawingOptions>): void;\n options(): DrawingOptions;\n remove(): void;\n}\n\nexport interface IChartApi {\n /** Add a series using a unified options object with a `type` discriminator. */\n addSeries(options: SeriesOptions): ISeriesApi<SeriesType>;\n removeSeries(series: ISeriesApi<SeriesType>): void;\n addPane(options?: PaneOptions): IPaneApi;\n removePane(pane: IPaneApi): void;\n timeScale(): TimeScale;\n priceScale(id?: string): PriceScale;\n applyOptions(options: DeepPartial<ChartOptions>): void;\n options(): ChartOptions;\n resize(width: number, height: number): void;\n remove(): void;\n subscribeCrosshairMove(callback: CrosshairMoveCallback): void;\n unsubscribeCrosshairMove(callback: CrosshairMoveCallback): void;\n subscribeClick(callback: ClickCallback): void;\n unsubscribeClick(callback: ClickCallback): void;\n // ── Feature 1: Range Switcher ─────────────────────────────────────────────\n /** Set the visible time range by Unix timestamps (seconds). Adjusts barSpacing and rightOffset. */\n setVisibleRange(from: number, to: number): void;\n /** Set the visible range by bar indices directly. */\n setVisibleLogicalRange(from: number, to: number): void;\n // ── Feature 2: Go to Realtime ─────────────────────────────────────────────\n /** Reset the view so the latest bar is at the right edge. */\n scrollToRealTime(): void;\n // ── Feature 3: Infinite History Loading ──────────────────────────────────\n subscribeVisibleRangeChange(callback: VisibleRangeChangeCallback): void;\n unsubscribeVisibleRangeChange(callback: VisibleRangeChangeCallback): void;\n // ── Feature 4: Fit Content & Screenshot ──────────────────────────────────\n fitContent(): void;\n takeScreenshot(): HTMLCanvasElement;\n // ── Feature 5: Indicator API ────────────────────────────────────────────\n addIndicator(type: IndicatorType, options: IndicatorOptions): IIndicatorApi;\n removeIndicator(indicator: IIndicatorApi): void;\n // ── Feature 6: Comparison Mode ───────────────────────────────────────────\n /** Enable/disable comparison mode. When on, the Y-axis shows percentage change from the first visible bar. */\n setComparisonMode(enabled: boolean): void;\n isComparisonMode(): boolean;\n // ── Feature 8: Drawing Tools ──────────────────────────────────────────\n addDrawing(type: string, points: AnchorPoint[], options?: DrawingOptions): IDrawingApi;\n removeDrawing(drawing: IDrawingApi): void;\n getDrawings(): IDrawingApi[];\n setActiveDrawingTool(type: string | null): void;\n registerDrawingType(type: string, factory: (id: string, points: AnchorPoint[], options: DrawingOptions) => ISeriesPrimitive & DrawingPrimitive): void;\n serializeDrawings(): SerializedDrawing[];\n deserializeDrawings(data: SerializedDrawing[]): void;\n // ── Feature 9/10: Chart State Save/Restore ────────────────────────────────\n /** Export the current chart configuration (no bar data) as a serializable state object. */\n exportState(): ChartState;\n /** Restore a previously exported chart state, loading bar data via the provided loader. */\n importState(state: ChartState, dataLoader: (seriesId: string) => Promise<Bar[]>): Promise<void>;\n // ── Feature 11b: Periodicity ──────────────────────────────────────────────\n setPeriodicity(periodicity: Periodicity): void;\n getPeriodicity(): Periodicity;\n subscribePeriodicityChange(handler: (p: Periodicity) => void): void;\n unsubscribePeriodicityChange(handler: (p: Periodicity) => void): void;\n // ── Event Subscriptions ──────────────────────────────────────────────────\n subscribeDblClick(callback: DblClickCallback): void;\n unsubscribeDblClick(callback: DblClickCallback): void;\n subscribeDrawingEvent(callback: DrawingEventCallback): void;\n unsubscribeDrawingEvent(callback: DrawingEventCallback): void;\n subscribeIndicatorEvent(callback: IndicatorEventCallback): void;\n unsubscribeIndicatorEvent(callback: IndicatorEventCallback): void;\n subscribeResize(callback: ResizeCallback): void;\n unsubscribeResize(callback: ResizeCallback): void;\n subscribeSymbolChange(callback: SymbolChangeCallback): void;\n unsubscribeSymbolChange(callback: SymbolChangeCallback): void;\n subscribeChartTypeChange(callback: ChartTypeChangeCallback): void;\n unsubscribeChartTypeChange(callback: ChartTypeChangeCallback): void;\n subscribePreferencesChange(callback: PreferencesChangeCallback): void;\n unsubscribePreferencesChange(callback: PreferencesChangeCallback): void;\n subscribeLayoutChange(callback: LayoutChangeCallback): void;\n unsubscribeLayoutChange(callback: LayoutChangeCallback): void;\n // ── Feature 11c: Market Sessions ──────────────────────────────────────────\n setMarketSessions(sessions: MarketSession[]): void;\n getMarketSessions(): MarketSession[];\n setSessionFilter(filter: 'regular' | 'extended' | 'all'): void;\n getSessionFilter(): string;\n // ── Export ────────────────────────────────────────────────────────────────\n /** Export visible OHLCV data (and optionally indicator values) as a CSV string. */\n exportCSV(options?: import('./export').CSVExportOptions): string;\n /** Export the current chart view as an SVG string (PNG image embedded in SVG wrapper). */\n exportSVG(): string;\n /** Export the current chart view as a PDF Blob. */\n exportPDF(options?: import('./export').PDFExportOptions): Blob;\n // ── Alert Lines ──────────────────────────────────────────────────────────\n // ── Undo/Redo ────────────────────────────────────────────────────────\n /** Undo the last drawing/chart modification. */\n undo(): boolean;\n /** Redo the last undone modification. */\n redo(): boolean;\n /** Whether undo is available. */\n canUndo(): boolean;\n /** Whether redo is available. */\n canRedo(): boolean;\n // ── Range Selection & Measure ─────────────────────────────────────────\n /** Activate the range selection mode (drag to highlight a time range). */\n setRangeSelectionActive(active: boolean): void;\n /** Subscribe to range selection results. */\n onRangeSelected(callback: import('../interactions/range-selection').RangeSelectionCallback): void;\n /** Unsubscribe from range selection results. */\n offRangeSelected(callback: import('../interactions/range-selection').RangeSelectionCallback): void;\n /** Activate the measure tool (click two points to see stats). */\n setMeasureActive(active: boolean): void;\n /** Subscribe to measure results. */\n onMeasure(callback: import('../interactions/range-selection').MeasureCallback): void;\n /** Unsubscribe from measure results. */\n offMeasure(callback: import('../interactions/range-selection').MeasureCallback): void;\n // ── Alert Lines ──────────────────────────────────────────────────────────\n /** Add an alert line at the given price level. */\n addAlertLine(price: number, options?: Partial<import('../core/alert-line').AlertLineOptions>): import('../core/alert-line').AlertLine;\n /** Remove an alert line. */\n removeAlertLine(alert: import('../core/alert-line').AlertLine): void;\n /** Get all alert lines. */\n getAlertLines(): import('../core/alert-line').AlertLine[];\n // ── Text Labels ─────────────────────────────────────────────────────────\n /** Add a text label anchored to a bar index and price. Use DataLayer.findIndex(timestamp) to convert a timestamp to a bar index. */\n addTextLabel(barIndex: number, price: number, text: string, options?: Partial<import('../core/text-label').TextLabelOptions>): import('../core/text-label').TextLabel;\n /** Remove a text label. */\n removeTextLabel(label: import('../core/text-label').TextLabel): void;\n /** Get all text labels. */\n getTextLabels(): import('../core/text-label').TextLabel[];\n}\n\n// ─── Internal series entry ──────────────────────────────────────────────────\n\n/**\n * Tracks animated display values for the last bar of a series.\n * Display values chase the actual store values via exponential lerp.\n */\ninterface LastBarAnimState {\n /** The bar index we're tracking — reset animation if this changes. */\n lastIdx: number;\n /** Current display values (what gets rendered). */\n open: number;\n high: number;\n low: number;\n close: number;\n /** True while display values are converging toward actual values. */\n animating: boolean;\n}\n\n/** Lerp factor for last-bar OHLC animation. */\nconst LAST_BAR_LERP = 0.3;\n/** Snap threshold relative to price range. */\nconst LAST_BAR_SNAP = 0.0005;\n\ninterface SeriesEntry {\n api: SeriesApi<SeriesType>;\n renderer:\n | CandlestickRenderer\n | LineRenderer\n | AreaRenderer\n | BarOHLCRenderer\n | BaselineRenderer\n | HollowCandleRenderer\n | HistogramRenderer\n | StepLineRenderer\n | ColoredLineRenderer\n | ColoredMountainRenderer\n | HLCAreaRenderer\n | HighLowRenderer\n | ColumnRenderer\n | VolumeCandleRenderer\n | BaselineDeltaMountainRenderer\n | RenkoRenderer\n | KagiRenderer\n | LineBreakRenderer\n | PointFigureRenderer;\n type: SeriesType;\n paneId: string;\n /** Cached Heikin-Ashi transformed store (invalidated when data length changes). */\n _haCache?: { length: number; store: import('../core/types').ColumnStore };\n}\n\n// ─── niceStep utility ───────────────────────────────────────────────────────\n\nfunction niceStep(range: number, targetSteps: number): number {\n if (range <= 0 || targetSteps <= 0) return 1;\n const rawStep = range / targetSteps;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalised = rawStep / magnitude;\n let niceNormalised: number;\n if (normalised <= 1.5) niceNormalised = 1;\n else if (normalised <= 3.5) niceNormalised = 2;\n else if (normalised <= 7.5) niceNormalised = 5;\n else niceNormalised = 10;\n return niceNormalised * magnitude;\n}\n\n// ─── ChartApi ───────────────────────────────────────────────────────────────\n\nclass ChartApi implements IChartApi {\n private _options: ChartOptions;\n private _container: HTMLElement;\n private _wrapper: HTMLDivElement;\n private _paneContainer: HTMLDivElement;\n private _timeAxisCanvas: HTMLCanvasElement;\n private _timeAxisCtx: CanvasRenderingContext2D;\n private _tooltipEl: HTMLDivElement;\n\n private _timeScale: TimeScale;\n private _crosshair: Crosshair;\n private _mask: InvalidateMask;\n\n // Per-pane system\n private _paneMap: Map<string, Pane> = new Map();\n private _paneOrder: string[] = []; // ordered list of pane ids (main first)\n private _paneApis: Map<string, PaneApi> = new Map();\n private _dividers: PaneDivider[] = [];\n /** Cleanup functions for pointer listeners attached to indicator pane overlays. */\n private _panePointerCleanup: Map<string, () => void> = new Map();\n\n private _eventRouter: EventRouter;\n private _panZoomHandler: PanZoomHandler;\n private _crosshairHandler: CrosshairHandler | null = null;\n private _contextMenuHandler: ContextMenuHandler | null = null;\n\n private _series: SeriesEntry[] = [];\n\n private _rafId: number | null = null;\n private _resizeObserver: ResizeObserver | null = null;\n private _removed: boolean = false;\n\n private _crosshairMoveCallbacks: CrosshairMoveCallback[] = [];\n private _clickCallbacks: ClickCallback[] = [];\n private _dblClickCallbacks: DblClickCallback[] = [];\n private _visibleRangeChangeCallbacks: VisibleRangeChangeCallback[] = [];\n private _drawingEventCallbacks: DrawingEventCallback[] = [];\n private _indicatorEventCallbacks: IndicatorEventCallback[] = [];\n private _resizeCallbacks: ResizeCallback[] = [];\n private _symbolChangeCallbacks: SymbolChangeCallback[] = [];\n private _chartTypeChangeCallbacks: ChartTypeChangeCallback[] = [];\n private _preferencesChangeCallbacks: PreferencesChangeCallback[] = [];\n private _layoutChangeCallbacks: LayoutChangeCallback[] = [];\n private _lastVisibleRangeFrom: number | null = null;\n private _lastVisibleRangeTo: number | null = null;\n\n private _width: number;\n private _height: number;\n\n // ── Tooltip/Legend caching ──────────────────────────────────────────────\n private _lastTooltipBarIdx: number = -1;\n private _tooltipWidth: number = 140;\n private _tooltipHeight: number = 80;\n private _priceFormat!: (price: number) => string;\n private _timeFormat!: (ts: number, tick: 'year' | 'month' | 'day' | 'time', crosshair?: boolean) => string;\n\n // Pre-created tooltip child elements\n private _tooltipDateEl!: HTMLDivElement;\n private _tooltipOHEl!: HTMLDivElement;\n private _tooltipLCEl!: HTMLDivElement;\n private _tooltipVEl!: HTMLDivElement;\n\n // HUD management (per-pane heads-up display)\n private _huds: Map<string, HudManager> = new Map();\n\n // The \"primary\" pane id for the mask\n private readonly _mainPaneId = 'main';\n\n // Track next pane id\n private _nextPaneId = 0;\n\n // Indicator management\n private _indicators: IndicatorApi[] = [];\n private _nextIndicatorId = 0;\n\n // Comparison mode\n private _comparisonMode: boolean = false;\n private _basisPrices: Map<SeriesApi<SeriesType>, number> = new Map(); // series -> basis price (first visible bar's close)\n\n // Drawing tools\n private _drawings: (ISeriesPrimitive & DrawingPrimitive)[] = [];\n private _drawingApis: Map<string, DrawingApiImpl> = new Map();\n private _drawingHandler: DrawingHandler | null = null;\n private _nextDrawingId = 0;\n\n // Undo/redo\n private _undoRedo: UndoRedoManager = new UndoRedoManager(50);\n private _handleUndoRedoKey: ((e: KeyboardEvent) => void) | null = null;\n\n // Range selection & measure handlers\n private _rangeSelectionHandler: RangeSelectionHandler | null = null;\n private _measureHandler: MeasureHandler | null = null;\n\n // Alert lines\n private _alertLines: AlertLine[] = [];\n private _nextAlertLineId = 0;\n\n // Text labels\n private _textLabels: TextLabel[] = [];\n private _nextTextLabelId = 0;\n\n // Periodicity\n private _periodicity: Periodicity = { interval: 1, unit: 'day' };\n private _periodicityCallbacks: ((p: Periodicity) => void)[] = [];\n\n // Market sessions\n private _marketSessions: MarketSession[] = [];\n private _sessionFilter: string = 'all';\n\n // Animation state for smooth streaming updates\n private _lastBarAnims: Map<SeriesApi<SeriesType>, LastBarAnimState> = new Map();\n\n // WebGL rendering\n private _useWebGL: boolean = false;\n private _webglCandlestick: CandlestickWebGLRenderer | null = null;\n private _webglLine: LineWebGLRenderer | null = null;\n private _webglArea: AreaWebGLRenderer | null = null;\n\n private get _chartWidth(): number {\n const leftScaleW = this._options.leftPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const rightScaleW = this._options.rightPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n return this._width - leftScaleW - rightScaleW;\n }\n\n /** Get the main Pane instance. */\n private get _mainPane(): Pane {\n return this._paneMap.get(this._mainPaneId)!;\n }\n\n constructor(container: HTMLElement, options: ChartOptions) {\n this._options = options;\n this._container = container;\n this._width = options.width;\n this._height = options.height;\n this._initFormatters();\n\n // ── DOM setup ──────────────────────────────────────────────────────────\n this._wrapper = document.createElement('div');\n this._wrapper.style.position = 'relative';\n this._wrapper.style.overflow = 'hidden';\n this._wrapper.style.width = `${this._width}px`;\n this._wrapper.style.height = `${this._height}px`;\n this._wrapper.style.backgroundColor = options.layout.backgroundColor;\n\n // Pane container (flex column holds all pane rows + dividers)\n this._paneContainer = document.createElement('div');\n this._paneContainer.style.display = 'flex';\n this._paneContainer.style.flexDirection = 'column';\n this._paneContainer.style.width = '100%';\n\n // Determine WebGL availability\n this._useWebGL = options.renderer === 'webgl' && isWebGLAvailable();\n if (this._useWebGL) {\n this._webglCandlestick = new CandlestickWebGLRenderer();\n this._webglLine = new LineWebGLRenderer();\n this._webglArea = new AreaWebGLRenderer();\n }\n\n // Create main pane\n const mainPaneHeight = this._height - TIME_AXIS_HEIGHT;\n const mainPane = new Pane(this._mainPaneId, mainPaneHeight, this._useWebGL);\n if (options.rightPriceScale?.mode) mainPane.priceScale.setMode(options.rightPriceScale.mode);\n if (options.leftPriceScale?.mode) mainPane.leftPriceScale.setMode(options.leftPriceScale.mode);\n this._paneMap.set(this._mainPaneId, mainPane);\n this._paneOrder.push(this._mainPaneId);\n this._paneContainer.appendChild(mainPane.row);\n\n this._wrapper.appendChild(this._paneContainer);\n\n // Time axis canvas — below all panes\n this._timeAxisCanvas = document.createElement('canvas');\n this._timeAxisCanvas.style.position = 'absolute';\n this._timeAxisCanvas.style.left = '0';\n this._timeAxisCanvas.style.zIndex = '1';\n this._wrapper.appendChild(this._timeAxisCanvas);\n\n // HUD overlay for main pane\n this._createHudForPane(this._mainPaneId, mainPane);\n\n // Tooltip overlay (DOM-based)\n this._tooltipEl = document.createElement('div');\n this._tooltipEl.style.cssText =\n `position:absolute;z-index:20;pointer-events:none;display:none;` +\n `background:rgba(0,0,0,0.78);color:${options.layout.textColor};border-radius:4px;padding:6px 10px;` +\n `font-size:${options.layout.fontSize}px;font-family:${options.layout.fontFamily};` +\n `line-height:1.5;white-space:nowrap;`;\n // Pre-create tooltip child elements\n this._tooltipDateEl = document.createElement('div');\n this._tooltipDateEl.style.marginBottom = '2px';\n this._tooltipDateEl.style.color = '#999';\n this._tooltipOHEl = document.createElement('div');\n this._tooltipLCEl = document.createElement('div');\n this._tooltipVEl = document.createElement('div');\n this._tooltipEl.appendChild(this._tooltipDateEl);\n this._tooltipEl.appendChild(this._tooltipOHEl);\n this._tooltipEl.appendChild(this._tooltipLCEl);\n this._tooltipEl.appendChild(this._tooltipVEl);\n\n this._wrapper.appendChild(this._tooltipEl);\n\n container.appendChild(this._wrapper);\n\n // Get contexts\n this._timeAxisCtx = this._timeAxisCanvas.getContext('2d')!;\n\n // Layout panes and canvases\n this._layoutPanes();\n\n // ── Core model ─────────────────────────────────────────────────────────\n this._timeScale = new TimeScale(options.timeScale);\n const leftScaleW = options.leftPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const rightScaleW = options.rightPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n this._timeScale.setWidth(this._width - leftScaleW - rightScaleW);\n\n this._crosshair = new Crosshair();\n\n this._mask = new InvalidateMask();\n this._mask.addPane(this._mainPaneId);\n\n // ── Interactions ───────────────────────────────────────────────────────\n this._eventRouter = new EventRouter();\n this._panZoomHandler = new PanZoomHandler(this._timeScale, () =>\n this.requestRepaint(InvalidationLevel.Full),\n );\n this._eventRouter.addHandler(this._panZoomHandler);\n this._eventRouter.attach(mainPane.canvases.overlayCanvas);\n\n // ── Undo/Redo keyboard shortcuts ──────────────────────────────────────\n this._handleUndoRedoKey = (e: KeyboardEvent) => {\n const mod = e.metaKey || e.ctrlKey;\n if (!mod) return;\n if (e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n this.undo();\n } else if (e.key === 'y' || (e.key === 'z' && e.shiftKey) || (e.key === 'Z' && e.shiftKey)) {\n e.preventDefault();\n this.redo();\n }\n };\n mainPane.canvases.overlayCanvas.addEventListener('keydown', this._handleUndoRedoKey);\n\n // ── Context Menu ───────────────────────────────────────────────────────\n this._contextMenuHandler = new ContextMenuHandler({\n getDrawings: () => this._drawings\n .filter((d): d is BaseDrawing => d instanceof BaseDrawing)\n .map(d => ({ drawing: d, id: d.id })),\n getIndicatorAtPane: (paneId: string) => {\n const ind = this._indicators.find(i => i.paneId() === paneId);\n return ind ? { id: `indicator-${ind.id}`, label: ind.label() } : null;\n },\n getPaneAtY: (y: number) => {\n let cumY = 0;\n for (const paneId of this._paneOrder) {\n const pane = this._paneMap.get(paneId)!;\n if (y >= cumY && y < cumY + pane.height) return paneId;\n cumY += pane.height;\n }\n return null;\n },\n mainPaneId: this._mainPaneId,\n editDrawing: (id) => {\n const drawing = this._drawings.find(d => d instanceof BaseDrawing && d.id === id) as BaseDrawing | undefined;\n if (drawing) { drawing.selected = true; this.requestRepaint(InvalidationLevel.Full); }\n },\n removeDrawing: (id) => {\n const api = this._drawingApis.get(id);\n if (api) this.removeDrawing(api);\n },\n duplicateDrawing: (id) => {\n const drawing = this._drawings.find(d => d instanceof BaseDrawing && d.id === id) as BaseDrawing | undefined;\n if (!drawing) return;\n const s = drawing.serialize();\n // Offset both time (+1 bar) and price (+1% of price range) so duplicate is visible\n const priceRange = this._mainPane.priceScale.priceRange;\n const priceOffset = (priceRange.max - priceRange.min) * 0.02;\n const offsetPoints = s.points.map(p => ({ time: p.time + 1, price: p.price + priceOffset }));\n this._addDrawingByIndex(s.type, offsetPoints, s.options);\n },\n bringDrawingToFront: (id) => {\n const idx = this._drawings.findIndex(d => d instanceof BaseDrawing && d.id === id);\n if (idx !== -1 && idx < this._drawings.length - 1) {\n const [d] = this._drawings.splice(idx, 1);\n this._drawings.push(d);\n this.requestRepaint(InvalidationLevel.Full);\n }\n },\n sendDrawingToBack: (id) => {\n const idx = this._drawings.findIndex(d => d instanceof BaseDrawing && d.id === id);\n if (idx > 0) {\n const [d] = this._drawings.splice(idx, 1);\n this._drawings.unshift(d);\n this.requestRepaint(InvalidationLevel.Full);\n }\n },\n openIndicatorSettings: (id) => {\n // Find the indicator's pane HUD and programmatically trigger its gear button\n const ind = this._indicators.find(i => `indicator-${i.id}` === id);\n if (ind) {\n const hud = this._huds.get(ind.paneId());\n if (hud) {\n // Click the gear button for this indicator's HUD row\n hud.triggerSettings?.(id);\n }\n }\n },\n toggleIndicatorVisibility: (id) => {\n const ind = this._indicators.find(i => `indicator-${i.id}` === id);\n if (ind) {\n const newVis = !ind.isVisible();\n ind.applyOptions({ visible: newVis });\n for (const s of (ind as any).internalSeries) { s.applyOptions({ visible: newVis }); }\n this.requestRepaint(InvalidationLevel.Full);\n }\n },\n removeIndicator: (id) => {\n const ind = this._indicators.find(i => `indicator-${i.id}` === id);\n if (ind) this.removeIndicator(ind);\n },\n fitContent: () => { this._timeScale.fitContent(); this.requestRepaint(InvalidationLevel.Full); },\n scrollToRealTime: () => this.scrollToRealTime(),\n toggleCrosshair: () => {\n if (this._crosshairHandler) {\n this._eventRouter.removeHandler(this._crosshairHandler);\n this._crosshairHandler = null;\n this._crosshair.hide();\n } else if (this._series.length > 0) {\n this._crosshairHandler = new CrosshairHandler(\n this._crosshair, this._series[0].api.getDataLayer(),\n this._timeScale, this._mainPane.priceScale,\n () => this.requestRepaint(InvalidationLevel.Cursor),\n this._mainPaneId,\n );\n this._eventRouter.addHandler(this._crosshairHandler);\n }\n this.requestRepaint(InvalidationLevel.Full);\n },\n theme: {\n bg: this._options.layout.backgroundColor,\n text: this._options.layout.textColor,\n border: this._options.layout.backgroundColor === '#131722' ? '#2a2e39' : '#e0e3eb',\n },\n localToScreen: (x, y) => {\n const rect = this._wrapper.getBoundingClientRect();\n return { x: rect.left + x, y: rect.top + y };\n },\n });\n this._eventRouter.addHandler(this._contextMenuHandler);\n\n // ── Click detection via overlay canvas ─────────────────────────────────\n mainPane.canvases.overlayCanvas.addEventListener('click', this._handleClick);\n mainPane.canvases.overlayCanvas.addEventListener('dblclick', this._handleDblClick);\n\n // ── AutoSize ───────────────────────────────────────────────────────────\n if (options.autoSize) {\n this._resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n if (width > 0 && height > 0) {\n this.resize(Math.round(width), Math.round(height));\n }\n }\n });\n this._resizeObserver.observe(container);\n }\n }\n\n // ── Formatters ──────────────────────────────────────────────────────────\n\n private _initFormatters(): void {\n this._priceFormat = this._options.priceFormatter\n ?? createPriceFormatter({\n locale: this._options.locale,\n decimals: 2,\n currency: this._options.currency,\n });\n\n const customTickFormatter = this._options.timeScale.tickMarkFormatter;\n this._timeFormat = customTickFormatter\n ? (ts: number, tick: 'year' | 'month' | 'day' | 'time', _crosshair?: boolean) => customTickFormatter(ts, tick)\n : createTimeFormatter({\n timezone: this._options.timezone,\n locale: this._options.locale,\n });\n }\n\n private _formatPrice(price: number): string {\n return this._priceFormat(price);\n }\n\n // ── Series management ───────────────────────────────────────────────────\n\n addSeries(options: SeriesOptions): ISeriesApi<SeriesType> {\n const { type, ...rest } = options;\n return this._addSeries(type, rest as DeepPartial<SeriesOptionsMap[typeof type]>);\n }\n\n removeSeries(series: ISeriesApi<SeriesType>): void {\n const idx = this._series.findIndex((e) => e.api === series);\n if (idx !== -1) {\n const entry = this._series[idx];\n\n // Remove HUD row for this series\n const hudRowId = `series-${entry.type}-${idx}`;\n const hud = this._huds.get(entry.paneId);\n if (hud) {\n hud.removeRow(hudRowId);\n }\n\n this._series.splice(idx, 1);\n this._lastBarAnims.delete(entry.api);\n\n // If we removed the primary (first) series the crosshair handler holds a\n // reference to its DataLayer. Reset it so the handler is recreated with\n // the correct DataLayer the next time a series is added, or replaced with\n // one pointing at the new primary series if any remain.\n if (idx === 0 && this._crosshairHandler !== null) {\n this._eventRouter.removeHandler(this._crosshairHandler);\n this._crosshairHandler = null;\n\n if (this._series.length > 0) {\n this._crosshairHandler = new CrosshairHandler(\n this._crosshair,\n this._series[0].api.getDataLayer(),\n this._timeScale,\n this._mainPane.priceScale,\n () => this.requestRepaint(InvalidationLevel.Cursor),\n this._mainPaneId,\n );\n this._eventRouter.addHandler(this._crosshairHandler);\n }\n }\n\n this.requestRepaint(InvalidationLevel.Full);\n }\n }\n\n // ── Pane management ─────────────────────────────────────────────────────\n\n addPane(options?: PaneOptions): IPaneApi {\n const id = `pane-${this._nextPaneId++}`;\n const defaultHeight = options?.height ?? 150;\n const pane = new Pane(id, defaultHeight, this._useWebGL);\n this._paneMap.set(id, pane);\n this._paneOrder.push(id);\n\n // Create divider between the previous last pane and this new one\n const prevPaneId = this._paneOrder[this._paneOrder.length - 2];\n const prevPane = this._paneMap.get(prevPaneId)!;\n const divider = new PaneDivider(\n () => prevPane.height,\n (h) => { prevPane.height = h; },\n () => pane.height,\n (h) => { pane.height = h; },\n () => this._layoutPanes(),\n );\n this._dividers.push(divider);\n\n // Append divider and pane row to container\n this._paneContainer.appendChild(divider.el);\n this._paneContainer.appendChild(pane.row);\n\n this._mask.addPane(id);\n this._createHudForPane(id, pane);\n\n const paneApi = new PaneApi(id, pane, () =>\n this.requestRepaint(InvalidationLevel.Full),\n );\n this._paneApis.set(id, paneApi);\n\n // Attach pointer listeners so the crosshair works on indicator panes\n this._attachPanePointerListeners(id, pane);\n\n // Recalculate main pane height to accommodate new pane\n this._layoutPanes();\n this.requestRepaint(InvalidationLevel.Full);\n\n for (const cb of this._layoutChangeCallbacks) cb({ action: 'pane-added', paneId: id });\n\n return paneApi;\n }\n\n removePane(pane: IPaneApi): void {\n const paneId = pane.id;\n if (paneId === this._mainPaneId) return; // Can't remove main pane\n\n const orderIdx = this._paneOrder.indexOf(paneId);\n if (orderIdx === -1) return;\n\n // Remove the pane and its preceding divider\n const internalPane = this._paneMap.get(paneId)!;\n internalPane.row.remove();\n\n // The divider before this pane (divider index = orderIdx - 1 since main has no preceding divider)\n const dividerIdx = orderIdx - 1;\n if (dividerIdx >= 0 && dividerIdx < this._dividers.length) {\n const divider = this._dividers[dividerIdx];\n divider.el.remove();\n divider.destroy();\n this._dividers.splice(dividerIdx, 1);\n }\n\n this._paneMap.delete(paneId);\n this._paneOrder.splice(orderIdx, 1);\n this._paneApis.delete(paneId);\n this._mask.removePane(paneId);\n\n // Clean up pointer listeners for this pane\n const cleanup = this._panePointerCleanup.get(paneId);\n if (cleanup) {\n cleanup();\n this._panePointerCleanup.delete(paneId);\n }\n\n // If the crosshair is currently pointing at the removed pane, reset it\n if (this._crosshair.sourcePaneId === paneId) {\n this._crosshair.hide();\n if (this._crosshairHandler) {\n this._crosshairHandler.setSourcePaneId(this._mainPaneId);\n this._crosshairHandler.setPriceScale(this._mainPane.priceScale);\n }\n }\n\n // Destroy HUD for this pane\n const hud = this._huds.get(paneId);\n if (hud) {\n hud.destroy();\n this._huds.delete(paneId);\n }\n\n // Remove series assigned to this pane\n this._series = this._series.filter((s) => s.paneId !== paneId);\n\n this._layoutPanes();\n this.requestRepaint(InvalidationLevel.Full);\n\n for (const cb of this._layoutChangeCallbacks) cb({ action: 'pane-removed', paneId });\n }\n\n /**\n * Attach lightweight pointer listeners to an indicator pane's overlay canvas\n * so the crosshair works when hovering over non-main panes.\n */\n private _attachPanePointerListeners(paneId: string, pane: Pane): void {\n const overlay = pane.canvases.overlayCanvas;\n overlay.style.touchAction = 'none';\n\n const onPointerMove = (e: PointerEvent) => {\n if (!this._crosshairHandler || this._series.length === 0) return;\n const rect = overlay.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Update crosshair handler to use this pane's price scale and pane ID\n this._crosshairHandler.setSourcePaneId(paneId);\n this._crosshairHandler.setPriceScale(pane.priceScale);\n this._crosshairHandler.onPointerMove(x, y, e.pointerId);\n };\n\n const onPointerLeave = () => {\n if (!this._crosshairHandler) return;\n // Restore main pane context and hide crosshair\n this._crosshairHandler.setSourcePaneId(this._mainPaneId);\n this._crosshairHandler.setPriceScale(this._mainPane.priceScale);\n this._crosshairHandler.onPointerUp(0);\n };\n\n overlay.addEventListener('pointermove', onPointerMove);\n overlay.addEventListener('pointerleave', onPointerLeave);\n\n this._panePointerCleanup.set(paneId, () => {\n overlay.removeEventListener('pointermove', onPointerMove);\n overlay.removeEventListener('pointerleave', onPointerLeave);\n });\n }\n\n // ── Scale access ────────────────────────────────────────────────────────\n\n timeScale(): TimeScale {\n return this._timeScale;\n }\n\n priceScale(id?: string): PriceScale {\n if (id) {\n // Check if it's a pane id\n const pane = this._paneMap.get(id);\n if (pane) return pane.priceScale;\n // Check if it's 'left' for the main pane\n if (id === 'left') return this._mainPane.leftPriceScale;\n }\n return this._mainPane.priceScale;\n }\n\n // ── Options ─────────────────────────────────────────────────────────────\n\n applyOptions(options: DeepPartial<ChartOptions>): void {\n const prevSymbol = this._options.symbol;\n this._options = mergeOptions(this._options, options);\n this._initFormatters();\n\n // Emit symbol change if symbol was updated\n if (options.symbol !== undefined && options.symbol !== prevSymbol) {\n for (const cb of this._symbolChangeCallbacks) cb({ previous: prevSymbol ?? '', current: options.symbol ?? '' });\n }\n\n if (options.layout?.backgroundColor) {\n this._wrapper.style.backgroundColor = this._options.layout.backgroundColor;\n }\n\n if (options.timeScale) {\n this._timeScale.setOptions(this._options.timeScale);\n }\n\n // Sync price scale modes\n if (options.rightPriceScale?.mode) {\n for (const pane of this._paneMap.values()) {\n pane.priceScale.setMode(this._options.rightPriceScale.mode ?? 'linear');\n }\n }\n if (options.leftPriceScale?.mode) {\n for (const pane of this._paneMap.values()) {\n pane.leftPriceScale.setMode(this._options.leftPriceScale.mode ?? 'linear');\n }\n }\n\n // Re-layout canvases if scale visibility changed\n if (options.leftPriceScale !== undefined || options.rightPriceScale !== undefined ||\n options.width !== undefined || options.height !== undefined) {\n this.resize(this._options.width, this._options.height);\n } else {\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n for (const cb of this._preferencesChangeCallbacks) cb(options);\n }\n\n options(): ChartOptions {\n return { ...this._options };\n }\n\n // ── Lifecycle ───────────────────────────────────────────────────────────\n\n resize(width: number, height: number): void {\n this._width = width;\n this._height = height;\n\n this._wrapper.style.width = `${width}px`;\n this._wrapper.style.height = `${height}px`;\n\n const leftScaleWidthR = this._options.leftPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const rightScaleWidthR = this._options.rightPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n this._timeScale.setWidth(width - leftScaleWidthR - rightScaleWidthR);\n\n this._options.width = width;\n this._options.height = height;\n\n this._layoutPanes();\n this.requestRepaint(InvalidationLevel.Full);\n\n for (const cb of this._resizeCallbacks) cb({ width, height });\n }\n\n remove(): void {\n if (this._removed) return;\n this._removed = true;\n\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n\n this._resizeObserver?.disconnect();\n this._eventRouter.detach();\n this._panZoomHandler.destroy();\n this._mainPane.canvases.overlayCanvas.removeEventListener('click', this._handleClick);\n this._mainPane.canvases.overlayCanvas.removeEventListener('dblclick', this._handleDblClick);\n\n // Clean up all indicator pane pointer listeners\n for (const cleanup of this._panePointerCleanup.values()) cleanup();\n this._panePointerCleanup.clear();\n\n // Clean up all indicator pane pointer listeners\n for (const cleanup of this._panePointerCleanup.values()) cleanup();\n this._panePointerCleanup.clear();\n\n // Clean up HUDs\n for (const hud of this._huds.values()) hud.destroy();\n this._huds.clear();\n\n // Clean up dividers\n for (const d of this._dividers) d.destroy();\n this._dividers.length = 0;\n\n this._visibleRangeChangeCallbacks.length = 0;\n this._crosshairMoveCallbacks.length = 0;\n this._clickCallbacks.length = 0;\n this._dblClickCallbacks.length = 0;\n this._drawingEventCallbacks.length = 0;\n this._indicatorEventCallbacks.length = 0;\n this._resizeCallbacks.length = 0;\n this._symbolChangeCallbacks.length = 0;\n this._chartTypeChangeCallbacks.length = 0;\n this._preferencesChangeCallbacks.length = 0;\n this._layoutChangeCallbacks.length = 0;\n\n // Clean up undo/redo keyboard handler\n if (this._handleUndoRedoKey) {\n this._mainPane.canvases.overlayCanvas.removeEventListener('keydown', this._handleUndoRedoKey);\n }\n this._undoRedo.clear();\n\n // Clean up WebGL renderers\n this._webglCandlestick?.dispose();\n this._webglLine?.dispose();\n this._webglArea?.dispose();\n this._webglCandlestick = null;\n this._webglLine = null;\n this._webglArea = null;\n\n this._wrapper.remove();\n }\n\n // ── Events ──────────────────────────────────────────────────────────────\n\n subscribeCrosshairMove(callback: CrosshairMoveCallback): void {\n this._crosshairMoveCallbacks.push(callback);\n }\n\n unsubscribeCrosshairMove(callback: CrosshairMoveCallback): void {\n const idx = this._crosshairMoveCallbacks.indexOf(callback);\n if (idx !== -1) this._crosshairMoveCallbacks.splice(idx, 1);\n }\n\n subscribeClick(callback: ClickCallback): void {\n this._clickCallbacks.push(callback);\n }\n\n unsubscribeClick(callback: ClickCallback): void {\n const idx = this._clickCallbacks.indexOf(callback);\n if (idx !== -1) this._clickCallbacks.splice(idx, 1);\n }\n\n subscribeDblClick(callback: DblClickCallback): void {\n this._dblClickCallbacks.push(callback);\n }\n\n unsubscribeDblClick(callback: DblClickCallback): void {\n const idx = this._dblClickCallbacks.indexOf(callback);\n if (idx !== -1) this._dblClickCallbacks.splice(idx, 1);\n }\n\n subscribeDrawingEvent(callback: DrawingEventCallback): void {\n this._drawingEventCallbacks.push(callback);\n }\n\n unsubscribeDrawingEvent(callback: DrawingEventCallback): void {\n const idx = this._drawingEventCallbacks.indexOf(callback);\n if (idx !== -1) this._drawingEventCallbacks.splice(idx, 1);\n }\n\n subscribeIndicatorEvent(callback: IndicatorEventCallback): void {\n this._indicatorEventCallbacks.push(callback);\n }\n\n unsubscribeIndicatorEvent(callback: IndicatorEventCallback): void {\n const idx = this._indicatorEventCallbacks.indexOf(callback);\n if (idx !== -1) this._indicatorEventCallbacks.splice(idx, 1);\n }\n\n subscribeResize(callback: ResizeCallback): void {\n this._resizeCallbacks.push(callback);\n }\n\n unsubscribeResize(callback: ResizeCallback): void {\n const idx = this._resizeCallbacks.indexOf(callback);\n if (idx !== -1) this._resizeCallbacks.splice(idx, 1);\n }\n\n subscribeSymbolChange(callback: SymbolChangeCallback): void {\n this._symbolChangeCallbacks.push(callback);\n }\n\n unsubscribeSymbolChange(callback: SymbolChangeCallback): void {\n const idx = this._symbolChangeCallbacks.indexOf(callback);\n if (idx !== -1) this._symbolChangeCallbacks.splice(idx, 1);\n }\n\n subscribeChartTypeChange(callback: ChartTypeChangeCallback): void {\n this._chartTypeChangeCallbacks.push(callback);\n }\n\n unsubscribeChartTypeChange(callback: ChartTypeChangeCallback): void {\n const idx = this._chartTypeChangeCallbacks.indexOf(callback);\n if (idx !== -1) this._chartTypeChangeCallbacks.splice(idx, 1);\n }\n\n subscribePreferencesChange(callback: PreferencesChangeCallback): void {\n this._preferencesChangeCallbacks.push(callback);\n }\n\n unsubscribePreferencesChange(callback: PreferencesChangeCallback): void {\n const idx = this._preferencesChangeCallbacks.indexOf(callback);\n if (idx !== -1) this._preferencesChangeCallbacks.splice(idx, 1);\n }\n\n subscribeLayoutChange(callback: LayoutChangeCallback): void {\n this._layoutChangeCallbacks.push(callback);\n }\n\n unsubscribeLayoutChange(callback: LayoutChangeCallback): void {\n const idx = this._layoutChangeCallbacks.indexOf(callback);\n if (idx !== -1) this._layoutChangeCallbacks.splice(idx, 1);\n }\n\n // ── Feature 1: Range Switcher ─────────────────────────────────────────\n\n setVisibleRange(from: number, to: number): void {\n if (this._series.length === 0) return;\n const dl = this._series[0].api.getDataLayer();\n if (dl.store.length === 0) return;\n\n // Find bar indices corresponding to the timestamps using binary search\n const fromIdx = dl.findIndex(from);\n const toIdx = dl.findIndex(to);\n this.setVisibleLogicalRange(fromIdx, toIdx);\n }\n\n setVisibleLogicalRange(from: number, to: number): void {\n // Sync dataLength from primary series in case this is called before first paint\n if (this._series.length > 0) {\n const store = this._series[0].api.getDataLayer().store;\n this._timeScale.setDataLength(store.length);\n }\n\n const barsToShow = to - from + 1;\n if (barsToShow <= 0) return;\n\n const chartW = this._chartWidth;\n if (chartW <= 0) return;\n\n // Set barSpacing so exactly barsToShow bars fit in the chart width.\n // setOptions() internally clamps to [minBarSpacing, maxBarSpacing].\n const newBarSpacing = chartW / barsToShow;\n this._timeScale.setOptions({ barSpacing: newBarSpacing });\n\n // Compute rightOffset so that `to` sits at the right edge.\n // rightBorder = baseIndex + rightOffset = to -> rightOffset = to - baseIndex\n const baseIndex = this._timeScale.dataLength > 0\n ? this._timeScale.dataLength - 1\n : 0;\n const newRightOffset = to - baseIndex;\n\n this._timeScale.setRightOffset(newRightOffset);\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n // ── Feature 2: Go to Realtime ─────────────────────────────────────────\n\n scrollToRealTime(): void {\n this._timeScale.scrollToEnd();\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n // ── Feature 4: Fit Content & Screenshot ───────────────────────────────\n\n fitContent(): void {\n this._timeScale.fitContent();\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n takeScreenshot(): HTMLCanvasElement {\n // Force a synchronous paint so canvases are up to date\n this._paint();\n\n const pixelRatio = window.devicePixelRatio || 1;\n const totalW = Math.round(this._width * pixelRatio);\n const totalH = Math.round(this._height * pixelRatio);\n\n const offscreen = document.createElement('canvas');\n offscreen.width = totalW;\n offscreen.height = totalH;\n const ctx = offscreen.getContext('2d')!;\n\n const leftScaleW = this._options.leftPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const rightScaleW = this._options.rightPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const chartW = this._chartWidth;\n\n let yOffset = 0;\n\n for (const paneId of this._paneOrder) {\n const pane = this._paneMap.get(paneId)!;\n const paneH = Math.round(pane.height * pixelRatio);\n const cvs = pane.canvases;\n\n // Left price axis\n if (this._options.leftPriceScale.visible) {\n ctx.drawImage(cvs.leftPriceAxisCanvas, 0, yOffset);\n }\n\n // Chart canvas\n ctx.drawImage(cvs.chartCanvas, Math.round(leftScaleW * pixelRatio), yOffset);\n\n // Overlay canvas (same position, layered on top)\n ctx.drawImage(cvs.overlayCanvas, Math.round(leftScaleW * pixelRatio), yOffset);\n\n // Right price axis\n if (this._options.rightPriceScale.visible) {\n ctx.drawImage(cvs.rightPriceAxisCanvas, Math.round((leftScaleW + chartW) * pixelRatio), yOffset);\n }\n\n yOffset += paneH;\n\n // Account for divider between panes (4px logical = DIVIDER_HEIGHT)\n if (paneId !== this._paneOrder[this._paneOrder.length - 1]) {\n yOffset += Math.round(DIVIDER_HEIGHT * pixelRatio);\n }\n }\n\n // Draw time axis at the bottom\n ctx.drawImage(this._timeAxisCanvas, Math.round(leftScaleW * pixelRatio), yOffset);\n\n return offscreen;\n }\n\n // ── Export ───────────────────────────────────────────────────────────────\n\n exportCSV(options?: CSVExportOptions): string {\n const seriesInfos: SeriesInfo[] = this._series\n .filter((e) => e.api.isVisible())\n .map((e) => ({\n label: (e.api.options() as { label?: string }).label ?? '',\n store: e.api.getDataLayer().store,\n }));\n\n const indicatorInfos: IndicatorInfo[] = this._indicators\n .filter((ind) => ind.isVisible())\n .map((ind) => {\n const outputs = new Map<string, Float64Array>();\n for (const s of ind.internalSeries) {\n const store = (s as unknown as { getDataLayer(): { store: ColumnStore } }).getDataLayer().store;\n outputs.set(\n (s.options() as { label?: string }).label ?? ind.indicatorType(),\n store.close,\n );\n }\n return { label: ind.indicatorType(), outputs };\n });\n\n const range = this._timeScale.visibleRange();\n return exportCSVFn(seriesInfos, indicatorInfos, range, options);\n }\n\n exportSVG(): string {\n const canvas = this.takeScreenshot();\n return exportSVGFn(canvas);\n }\n\n exportPDF(options?: PDFExportOptions): Blob {\n const canvas = this.takeScreenshot();\n return exportPDFFn(canvas, options);\n }\n\n // ── Undo/Redo ─────────────────────────────────────────────────────────\n\n undo(): boolean {\n return this._undoRedo.undo();\n }\n\n redo(): boolean {\n return this._undoRedo.redo();\n }\n\n canUndo(): boolean {\n return this._undoRedo.canUndo();\n }\n\n canRedo(): boolean {\n return this._undoRedo.canRedo();\n }\n\n // ── Range Selection & Measure ─────────────────────────────────────────\n\n private _ensureRangeSelectionHandler(): RangeSelectionHandler {\n if (!this._rangeSelectionHandler) {\n this._rangeSelectionHandler = new RangeSelectionHandler(\n this._timeScale,\n this._mainPane.priceScale,\n () => this._series.length > 0 ? this._series[0].api.getDataLayer().store : null,\n () => this.requestRepaint(InvalidationLevel.Light),\n );\n this._eventRouter.addHandler(this._rangeSelectionHandler);\n }\n return this._rangeSelectionHandler;\n }\n\n private _ensureMeasureHandler(): MeasureHandler {\n if (!this._measureHandler) {\n this._measureHandler = new MeasureHandler(\n this._timeScale,\n this._mainPane.priceScale,\n () => this._series.length > 0 ? this._series[0].api.getDataLayer().store : null,\n () => this.requestRepaint(InvalidationLevel.Light),\n );\n this._eventRouter.addHandler(this._measureHandler);\n }\n return this._measureHandler;\n }\n\n setRangeSelectionActive(active: boolean): void {\n const handler = this._ensureRangeSelectionHandler();\n handler.active = active;\n // Deactivate measure when range selection is active\n if (active && this._measureHandler) this._measureHandler.active = false;\n }\n\n onRangeSelected(callback: RangeSelectionCallback): void {\n this._ensureRangeSelectionHandler().onRangeSelected(callback);\n }\n\n offRangeSelected(callback: RangeSelectionCallback): void {\n this._rangeSelectionHandler?.offRangeSelected(callback);\n }\n\n setMeasureActive(active: boolean): void {\n const handler = this._ensureMeasureHandler();\n handler.active = active;\n // Deactivate range selection when measure is active\n if (active && this._rangeSelectionHandler) this._rangeSelectionHandler.active = false;\n }\n\n onMeasure(callback: MeasureCallback): void {\n this._ensureMeasureHandler().onMeasure(callback);\n }\n\n offMeasure(callback: MeasureCallback): void {\n this._measureHandler?.offMeasure(callback);\n }\n\n // ── Alert Lines ─────────────────────────────────────────────────────────\n\n addAlertLine(price: number, options?: Partial<AlertLineOptions>): AlertLine {\n const id = `alert_${this._nextAlertLineId++}`;\n const alert = new AlertLine(\n id,\n { ...options, price } as AlertLineOptions,\n () => this.requestRepaint(InvalidationLevel.Light),\n );\n this._alertLines.push(alert);\n this.requestRepaint(InvalidationLevel.Light);\n return alert;\n }\n\n removeAlertLine(alert: AlertLine): void {\n const idx = this._alertLines.indexOf(alert);\n if (idx >= 0) {\n this._alertLines.splice(idx, 1);\n this.requestRepaint(InvalidationLevel.Light);\n }\n }\n\n getAlertLines(): AlertLine[] {\n return [...this._alertLines];\n }\n\n // ── Text Labels ─────────────────────────────────────────────────────────\n\n addTextLabel(barIndex: number, price: number, text: string, options?: Partial<TextLabelOptions>): TextLabel {\n const id = `textlabel_${this._nextTextLabelId++}`;\n const label = new TextLabel(\n id, barIndex, price,\n { text, ...options },\n () => this.requestRepaint(InvalidationLevel.Light),\n );\n this._textLabels.push(label);\n this.requestRepaint(InvalidationLevel.Light);\n return label;\n }\n\n removeTextLabel(label: TextLabel): void {\n const idx = this._textLabels.indexOf(label);\n if (idx >= 0) {\n this._textLabels.splice(idx, 1);\n this.requestRepaint(InvalidationLevel.Light);\n }\n }\n\n getTextLabels(): TextLabel[] {\n return [...this._textLabels];\n }\n\n // ── Feature 5: Indicator API ────────────────────────────────────────────\n\n addIndicator(type: IndicatorType, options: IndicatorOptions): IIndicatorApi {\n const id = `indicator-${this._nextIndicatorId++}`;\n\n // 1. Resolve params\n const defaults = DEFAULT_INDICATOR_PARAMS[type] ?? {};\n const params = { ...defaults, ...(options.params ?? {}) };\n\n // 2. Determine pane\n let paneId: string;\n let autoCreatedPaneId: string | null = null;\n if (options.paneId) {\n paneId = options.paneId;\n } else if (OVERLAY_INDICATORS.has(type)) {\n paneId = this._mainPaneId;\n } else {\n const newPane = this.addPane({ height: 150 });\n paneId = newPane.id;\n autoCreatedPaneId = paneId;\n }\n\n // 3. Read source series data\n const sourceApi = options.source as SeriesApi<SeriesType>;\n const store = sourceApi.getDataLayer().store;\n\n // 4. Compute indicator\n const result = this._computeIndicator(type, store, params);\n\n // 5-6. Create internal series\n const color = options.color ?? '#2962ff';\n const lineWidth = options.lineWidth ?? 2;\n const customColors = options.colors;\n const histUpColor = options.histogramUpColor ?? 'rgba(34, 171, 148, 0.4)';\n const histDownColor = options.histogramDownColor ?? 'rgba(247, 82, 95, 0.4)';\n\n const indicator = new IndicatorApi(id, type, options, paneId, () => {\n this.removeIndicator(indicator);\n });\n indicator.autoCreatedPaneId = autoCreatedPaneId;\n\n this._createIndicatorSeries(indicator, result, store, paneId, color, lineWidth, customColors, histUpColor, histDownColor);\n\n // 7. Subscribe to source's dataChanged for auto-recompute\n const dataChangedCallback = (): void => {\n const updatedStore = sourceApi.getDataLayer().store;\n const updatedResult = this._computeIndicator(type, updatedStore, params);\n\n // Remove old internal series\n for (const s of indicator.internalSeries) {\n this.removeSeries(s);\n }\n indicator.internalSeries = [];\n\n // Recreate with updated data\n this._createIndicatorSeries(indicator, updatedResult, updatedStore, paneId, color, lineWidth, customColors, histUpColor, histDownColor);\n };\n indicator._dataChangedCallback = dataChangedCallback;\n options.source.subscribeDataChanged(dataChangedCallback);\n\n this._indicators.push(indicator);\n\n // Register HUD row for this indicator\n this._registerIndicatorHudRow(indicator, options);\n\n for (const cb of this._indicatorEventCallbacks) cb({ type: 'added', indicatorId: id, indicatorType: type, paneId });\n\n return indicator;\n }\n\n removeIndicator(indicator: IIndicatorApi): void {\n const impl = indicator as IndicatorApi;\n const idx = this._indicators.indexOf(impl);\n if (idx === -1) return;\n\n // Remove HUD row for this indicator\n const hud = this._huds.get(impl.paneId());\n if (hud) {\n hud.removeRow(`indicator-${impl.id}`);\n }\n\n // 1. Remove all internal series\n for (const s of impl.internalSeries) {\n this.removeSeries(s);\n }\n impl.internalSeries = [];\n\n // 2. If auto-created pane and no other series/indicators use it, remove the pane\n if (impl.autoCreatedPaneId) {\n const autoPaneId = impl.autoCreatedPaneId;\n const otherSeriesInPane = this._series.some(s => s.paneId === autoPaneId);\n const otherIndicatorsInPane = this._indicators.some(\n (ind, i) => i !== idx && ind.paneId() === autoPaneId,\n );\n if (!otherSeriesInPane && !otherIndicatorsInPane) {\n const paneApi = this._paneApis.get(autoPaneId);\n if (paneApi) {\n this.removePane(paneApi);\n }\n }\n }\n\n // 3. Unsubscribe from source dataChanged\n if (impl._dataChangedCallback) {\n impl.options().source.unsubscribeDataChanged(impl._dataChangedCallback);\n impl._dataChangedCallback = null;\n }\n\n // 4. Remove from _indicators array\n const removedType = impl.indicatorType();\n const removedPaneId = impl.paneId();\n this._indicators.splice(idx, 1);\n\n for (const cb of this._indicatorEventCallbacks) cb({ type: 'removed', indicatorId: impl.id, indicatorType: removedType, paneId: removedPaneId });\n }\n\n private _computeIndicator(\n type: IndicatorType,\n store: ColumnStore,\n params: Record<string, number>,\n ): Record<string, Float64Array> {\n const len = store.length;\n const close = store.close;\n const high = store.high;\n const low = store.low;\n const volume = store.volume;\n\n switch (type) {\n case 'sma':\n return { value: computeSMA(close, len, params.period) };\n case 'ema':\n return { value: computeEMA(close, len, params.period) };\n case 'rsi':\n return { value: computeRSI(close, len, params.period) };\n case 'macd': {\n const r = computeMACD(close, len, params.fastPeriod, params.slowPeriod, params.signalPeriod);\n return { macd: r.macd, signal: r.signal, histogram: r.histogram };\n }\n case 'bollinger': {\n const r = computeBollinger(close, len, params.period, params.stdDev);\n return { upper: r.upper, middle: r.middle, lower: r.lower };\n }\n case 'vwap':\n return { value: computeVWAP(high, low, close, volume, len) };\n case 'stochastic': {\n const r = computeStochastic(high, low, close, len, params.kPeriod, params.dPeriod);\n return { k: r.k, d: r.d };\n }\n case 'atr':\n return { value: computeATR(high, low, close, len, params.period) };\n case 'adx': {\n const r = computeADX(high, low, close, len, params.period);\n return { adx: r.adx, plusDI: r.plusDI, minusDI: r.minusDI };\n }\n case 'obv':\n return { value: computeOBV(close, volume, len) };\n case 'williams-r':\n return { value: computeWilliamsR(high, low, close, len, params.period) };\n case 'ichimoku': {\n const r = computeIchimoku(high, low, close, len, params.tenkanPeriod, params.kijunPeriod, params.senkouPeriod);\n return { tenkan: r.tenkan, kijun: r.kijun, senkouA: r.senkouA, senkouB: r.senkouB, chikou: r.chikou };\n }\n case 'parabolic-sar':\n return { value: computeParabolicSAR(high, low, len, params.afStep, params.afMax) };\n case 'keltner': {\n const r = computeKeltner(close, high, low, len, params.emaPeriod, params.atrPeriod, params.multiplier);\n return { upper: r.upper, middle: r.middle, lower: r.lower };\n }\n case 'donchian': {\n const r = computeDonchian(high, low, len, params.period);\n return { upper: r.upper, middle: r.middle, lower: r.lower };\n }\n case 'cci':\n return { value: computeCCI(high, low, close, len, params.period) };\n case 'pivot-points': {\n const r = computePivotPoints(high, low, close, len);\n return { pp: r.pp, r1: r.r1, r2: r.r2, r3: r.r3, s1: r.s1, s2: r.s2, s3: r.s3 };\n }\n case 'aroon': {\n const r = computeAroon(high, low, len, params.period ?? 25);\n return { up: r.up, down: r.down };\n }\n case 'awesome-oscillator':\n return { histogram: computeAwesomeOscillator(high, low, len, params.fastPeriod ?? 5, params.slowPeriod ?? 34) };\n case 'chaikin-mf':\n return { value: computeChaikinMF(high, low, close, volume, len, params.period ?? 20) };\n case 'coppock':\n return { value: computeCoppock(close, len, params.wmaPeriod ?? 10, params.longROC ?? 14, params.shortROC ?? 11) };\n case 'elder-force':\n return { value: computeElderForce(close, volume, len, params.period ?? 13) };\n case 'trix': {\n const r = computeTRIX(close, len, params.period ?? 15, params.signalPeriod ?? 9);\n return { trix: r.trix, signal: r.signal };\n }\n case 'supertrend': {\n const r = computeSupertrend(high, low, close, len, params.period ?? 10, params.multiplier ?? 3);\n return { value: r.value };\n }\n case 'vwma':\n return { value: computeVWMA(close, volume, len, params.period ?? 20) };\n case 'choppiness':\n return { value: computeChoppiness(high, low, close, len, params.period ?? 14) };\n case 'mfi':\n return { value: computeMFI(high, low, close, volume, len, params.period ?? 14) };\n case 'roc':\n return { value: computeROC(close, len, params.period ?? 12) };\n case 'linear-regression':\n return { value: computeLinearRegression(close, len, params.period ?? 20) };\n default:\n throw new Error(`Unknown indicator type: ${type}`);\n }\n }\n\n private _createIndicatorSeries(\n indicator: IndicatorApi,\n result: Record<string, Float64Array>,\n store: ColumnStore,\n paneId: string,\n primaryColor: string,\n lineWidth: number,\n customColors?: Record<string, string>,\n histUpColor: string = 'rgba(34, 171, 148, 0.4)',\n histDownColor: string = 'rgba(247, 82, 95, 0.4)',\n ): void {\n const type = indicator.indicatorType();\n\n // Color map for multi-output indicators — custom overrides take precedence\n const defaultColorMap = this._getIndicatorColorMap(type, primaryColor);\n const colorMap = customColors ? { ...defaultColorMap, ...customColors } : defaultColorMap;\n\n // Draw histogram series first so line series render on top\n const sortedKeys = Object.keys(result).sort((a, b) =>\n (a === 'histogram' ? -1 : 0) - (b === 'histogram' ? -1 : 0),\n );\n for (const key of sortedKeys) {\n const values = result[key];\n const color = colorMap[key] ?? primaryColor;\n\n // Build Bar[] data from time + indicator values\n const bars: Bar[] = [];\n for (let i = 0; i < store.length; i++) {\n const v = values[i];\n if (isNaN(v)) continue;\n bars.push({\n time: store.time[i],\n open: v,\n high: v,\n low: v,\n close: v,\n volume: 0,\n });\n }\n\n let series: ISeriesApi<SeriesType>;\n if (key === 'histogram') {\n series = this._addSeries('histogram', {\n paneId,\n data: bars,\n upColor: histUpColor,\n downColor: histDownColor,\n }, true);\n } else {\n series = this._addSeries('line', {\n paneId,\n data: bars,\n color,\n lineWidth,\n }, true);\n }\n\n indicator.internalSeries.push(series);\n }\n }\n\n private _getIndicatorColorMap(\n type: IndicatorType,\n primaryColor: string,\n ): Record<string, string> {\n switch (type) {\n case 'macd':\n return { macd: '#2962ff', signal: '#ff6d00', histogram: '#22AB94' };\n case 'bollinger':\n return { upper: '#42a5f5', middle: primaryColor, lower: '#42a5f5' };\n case 'stochastic':\n return { k: primaryColor, d: '#ff6d00' };\n case 'adx':\n return { adx: primaryColor, plusDI: '#22AB94', minusDI: '#F7525F' };\n case 'ichimoku':\n return { tenkan: '#2962ff', kijun: '#F7525F', senkouA: '#22AB94', senkouB: '#ee6823', chikou: '#9c27b0' };\n case 'keltner':\n return { upper: '#42a5f5', middle: primaryColor, lower: '#42a5f5' };\n case 'donchian':\n return { upper: '#42a5f5', middle: primaryColor, lower: '#42a5f5' };\n case 'pivot-points':\n return { pp: primaryColor, r1: '#F7525F', r2: '#F7525F', r3: '#F7525F', s1: '#22AB94', s2: '#22AB94', s3: '#22AB94' };\n case 'aroon':\n return { up: '#22AB94', down: '#F7525F' };\n case 'trix':\n return { trix: primaryColor, signal: '#ff6d00' };\n default:\n return { value: primaryColor };\n }\n }\n\n // ── Feature 6: Comparison Mode ───────────────────────────────────────────\n\n setComparisonMode(enabled: boolean): void {\n this._comparisonMode = enabled;\n this._basisPrices.clear();\n for (const pane of this._paneMap.values()) {\n pane.priceScale.setComparisonMode(enabled);\n }\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n isComparisonMode(): boolean {\n return this._comparisonMode;\n }\n\n // ── Feature 8: Drawing Tools ──────────────────────────────────────────────\n\n addDrawing(type: string, points: AnchorPoint[], options: DrawingOptions = {}): IDrawingApi {\n // Public API: convert timestamp-based AnchorPoints to bar-index-based points.\n // Internally, drawings store time as a bar index, but callers provide Unix\n // timestamps matching the underlying series data.\n let resolvedPoints = points;\n if (this._series.length > 0) {\n const dl = this._series[0].api.getDataLayer();\n if (dl.store.length > 0) {\n resolvedPoints = points.map(p => ({\n ...p,\n time: dl.findIndex(p.time),\n }));\n }\n }\n return this._addDrawingByIndex(type, resolvedPoints, options);\n }\n\n /** @internal Add a drawing with points already expressed as bar indices. */\n _addDrawingByIndex(type: string, points: AnchorPoint[], options: DrawingOptions = {}): IDrawingApi {\n const id = `drawing_${this._nextDrawingId++}`;\n const drawing = createBuiltinDrawing(type, id, points, options);\n if (!drawing) throw new Error(`Unknown drawing type: ${type}`);\n if (drawing instanceof BaseDrawing) {\n drawing.setContext(this._getDrawingContext());\n }\n this._drawings.push(drawing);\n const api = new DrawingApiImpl(id, drawing, this);\n this._drawingApis.set(id, api);\n this.requestRepaint(InvalidationLevel.Full);\n\n for (const cb of this._drawingEventCallbacks) cb({ type: 'created', drawingId: id, drawingType: type });\n\n return api;\n }\n\n removeDrawing(drawingApi: IDrawingApi): void {\n const idx = this._drawings.findIndex(d => {\n if (d instanceof BaseDrawing) return d.id === drawingApi.id;\n return false;\n });\n if (idx !== -1) {\n const drawingType = drawingApi.drawingType();\n this._drawings.splice(idx, 1);\n this._drawingApis.delete(drawingApi.id);\n this.requestRepaint(InvalidationLevel.Full);\n\n for (const cb of this._drawingEventCallbacks) cb({ type: 'removed', drawingId: drawingApi.id, drawingType });\n }\n }\n\n getDrawings(): IDrawingApi[] {\n return Array.from(this._drawingApis.values());\n }\n\n setActiveDrawingTool(type: string | null): void {\n this._ensureDrawingHandler();\n this._drawingHandler!.setActiveToolType(type);\n }\n\n registerDrawingType(\n type: string,\n factory: (id: string, points: AnchorPoint[], options: DrawingOptions) => ISeriesPrimitive & DrawingPrimitive,\n ): void {\n DRAWING_REGISTRY.set(type, factory);\n }\n\n serializeDrawings(): SerializedDrawing[] {\n return this._drawings.map(d => d.serialize());\n }\n\n deserializeDrawings(data: SerializedDrawing[]): void {\n // Remove all existing\n this._drawings.length = 0;\n this._drawingApis.clear();\n for (const entry of data) {\n const drawing = createBuiltinDrawing(entry.type, entry.id, entry.points, entry.options);\n if (!drawing) continue;\n if (drawing instanceof BaseDrawing) {\n drawing.setContext(this._getDrawingContext());\n }\n this._drawings.push(drawing);\n const api = new DrawingApiImpl(entry.id, drawing, this);\n this._drawingApis.set(entry.id, api);\n }\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n exportState(): ChartState {\n // Collect series configs (no bar data)\n const seriesEntries = this._series.map((entry, idx) => ({\n id: `series-${idx}`,\n type: entry.type,\n options: entry.api.options() as unknown as Record<string, unknown>,\n }));\n\n // Collect indicator configs\n const indicatorEntries = this._indicators.map((ind) => {\n const opts = ind.options();\n return {\n type: ind.indicatorType(),\n sourceSeriesId: 'series-0', // primary series\n params: (opts.params ?? {}) as Record<string, number>,\n color: opts.color,\n };\n });\n\n // Collect pane heights\n const paneEntries = this._paneOrder.map((paneId) => {\n const pane = this._paneMap.get(paneId)!;\n return { id: paneId, height: pane.height };\n });\n\n // Collect visible range (time values)\n const visibleRange = this._timeScale.visibleRange();\n let visibleRangeTs: { from: number; to: number } | undefined;\n if (visibleRange) {\n const store = this._series[0]?.api.getDataLayer().store;\n if (store && store.length > 0) {\n const fromIdx = Math.max(0, Math.min(Math.floor(visibleRange.fromIdx), store.length - 1));\n const toIdx = Math.max(0, Math.min(Math.floor(visibleRange.toIdx), store.length - 1));\n visibleRangeTs = { from: store.time[fromIdx], to: store.time[toIdx] };\n }\n }\n\n return {\n version: CHART_STATE_VERSION,\n options: this._options as unknown as import('../core/types').DeepPartial<ChartOptions>,\n comparisonMode: this._comparisonMode,\n timeScale: {\n barSpacing: this._timeScale.barSpacing,\n rightOffset: this._timeScale.rightOffset,\n },\n series: seriesEntries,\n indicators: indicatorEntries,\n panes: paneEntries,\n drawings: this.serializeDrawings(),\n visibleRange: visibleRangeTs,\n };\n }\n\n async importState(state: ChartState, dataLoader: (seriesId: string) => Promise<Bar[]>): Promise<void> {\n if (!validateChartState(state)) {\n throw new Error('Invalid chart state: failed validation');\n }\n\n // Apply options\n this.applyOptions(state.options as DeepPartial<ChartOptions>);\n\n // Apply comparison mode\n if (state.comparisonMode !== undefined) {\n this.setComparisonMode(state.comparisonMode);\n }\n\n // Apply time scale\n this._timeScale.setOptions({\n barSpacing: state.timeScale.barSpacing,\n });\n this._timeScale.setRightOffset(state.timeScale.rightOffset);\n\n // Remove existing series\n for (const entry of [...this._series]) {\n this.removeSeries(entry.api);\n }\n\n // Remove existing indicators\n for (const ind of [...this._indicators]) {\n this.removeIndicator(ind);\n }\n\n // Re-create series (without data)\n const createdSeries: Map<string, ISeriesApi<SeriesType>> = new Map();\n for (const sEntry of state.series) {\n const api = this.addSeries({ type: sEntry.type, ...sEntry.options } as SeriesOptions);\n createdSeries.set(sEntry.id, api);\n }\n\n // Load data in parallel\n const loadPromises = state.series.map(async (sEntry) => {\n const api = createdSeries.get(sEntry.id);\n if (!api) return;\n const bars = await dataLoader(sEntry.id);\n api.setData(bars);\n });\n await Promise.all(loadPromises);\n\n // Re-create indicators\n for (const indEntry of state.indicators) {\n const sourceSeries = createdSeries.get(indEntry.sourceSeriesId);\n if (!sourceSeries) continue;\n this.addIndicator(indEntry.type, {\n source: sourceSeries,\n params: indEntry.params,\n color: indEntry.color,\n });\n }\n\n // Restore drawings\n if (state.drawings.length > 0) {\n this.deserializeDrawings(state.drawings);\n }\n\n // Restore viewport\n if (state.visibleRange) {\n this.setVisibleRange(state.visibleRange.from, state.visibleRange.to);\n }\n\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n // ── Feature 11b: Periodicity ──────────────────────────────────────────────\n\n setPeriodicity(periodicity: Periodicity): void {\n this._periodicity = periodicity;\n for (const cb of this._periodicityCallbacks) {\n cb(periodicity);\n }\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n getPeriodicity(): Periodicity {\n return this._periodicity;\n }\n\n subscribePeriodicityChange(handler: (p: Periodicity) => void): void {\n this._periodicityCallbacks.push(handler);\n }\n\n unsubscribePeriodicityChange(handler: (p: Periodicity) => void): void {\n const idx = this._periodicityCallbacks.indexOf(handler);\n if (idx !== -1) this._periodicityCallbacks.splice(idx, 1);\n }\n\n // ── Feature 11c: Market Sessions ──────────────────────────────────────────\n\n setMarketSessions(sessions: MarketSession[]): void {\n this._marketSessions = sessions;\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n getMarketSessions(): MarketSession[] {\n return this._marketSessions;\n }\n\n setSessionFilter(filter: 'regular' | 'extended' | 'all'): void {\n this._sessionFilter = filter;\n this.requestRepaint(InvalidationLevel.Full);\n }\n\n getSessionFilter(): string {\n return this._sessionFilter;\n }\n\n /** @internal */\n _getDrawingContext(): DrawingContext {\n const mainPane = this._mainPane;\n return {\n timeScale: this._timeScale,\n priceScale: mainPane.priceScale,\n chartWidth: this._chartWidth,\n chartHeight: mainPane.height,\n requestUpdate: () => this.requestRepaint(InvalidationLevel.Full),\n };\n }\n\n private _ensureDrawingHandler(): void {\n if (this._drawingHandler) return;\n const self = this;\n this._drawingHandler = new DrawingHandler({\n getDrawings: () => self._drawings,\n getDrawingContext: () => self._getDrawingContext(),\n onDrawingCreated(drawing) {\n if (drawing instanceof BaseDrawing) {\n drawing.setContext(self._getDrawingContext());\n }\n self._drawings.push(drawing);\n const id = (drawing as BaseDrawing).id;\n const api = new DrawingApiImpl(id, drawing, self);\n self._drawingApis.set(id, api);\n self.requestRepaint(InvalidationLevel.Full);\n },\n onDrawingUpdated(drawing) {\n self.requestRepaint(InvalidationLevel.Full);\n if (drawing && drawing instanceof BaseDrawing) {\n for (const cb of self._drawingEventCallbacks) cb({ type: 'modified', drawingId: drawing.id, drawingType: drawing.drawingType });\n }\n },\n xToTime(x: number): number {\n return self._timeScale.xToIndex(x);\n },\n yToPrice(y: number): number {\n return self._mainPane.priceScale.yToPrice(y);\n },\n });\n // Insert drawing handler BEFORE pan-zoom so it gets first crack at events\n this._eventRouter.addHandler(this._drawingHandler);\n }\n\n /**\n * Returns the basis price (first visible bar's close) for a given series entry,\n * computing and caching it on first call for each series per paint cycle.\n */\n private _getBasisPrice(entry: SeriesEntry, range: VisibleRange): number {\n if (this._basisPrices.has(entry.api)) {\n return this._basisPrices.get(entry.api)!;\n }\n const store = entry.api.getDataLayer().store;\n const fromIdx = Math.max(0, Math.min(range.fromIdx, store.length - 1));\n const basis = store.close[fromIdx] ?? 0;\n this._basisPrices.set(entry.api, basis);\n return basis;\n }\n\n // ── Feature 3: Visible Range Change Subscription ──────────────────────\n\n subscribeVisibleRangeChange(callback: VisibleRangeChangeCallback): void {\n this._visibleRangeChangeCallbacks.push(callback);\n }\n\n unsubscribeVisibleRangeChange(callback: VisibleRangeChangeCallback): void {\n const idx = this._visibleRangeChangeCallbacks.indexOf(callback);\n if (idx !== -1) this._visibleRangeChangeCallbacks.splice(idx, 1);\n }\n\n // ── Repaint scheduling ────────────────────────────────────────────────\n\n requestRepaint(level: number): void {\n this._mask.invalidateAll(level as 0 | 1 | 2 | 3);\n if (this._rafId === null && !this._removed) {\n this._rafId = requestAnimationFrame(() => {\n this._rafId = null;\n this._paint();\n });\n }\n }\n\n // ── Layout panes ─────────────────────────────────────────────────────\n\n private _layoutPanes(): void {\n const pixelRatio = window.devicePixelRatio || 1;\n const leftScaleW = this._options.leftPriceScale.visible ? PRICE_AXIS_WIDTH : 0;\n const rightScaleVisible = this._options.rightPriceScale.visible;\n const leftScaleVisible = this._options.leftPriceScale.visible;\n const chartW = this._chartWidth;\n\n // Calculate total available height for panes\n const totalDividerHeight = this._dividers.length * DIVIDER_HEIGHT;\n const totalAvailable = this._height - TIME_AXIS_HEIGHT - totalDividerHeight;\n\n // Sum of indicator pane heights (all except main)\n let indicatorPanesHeight = 0;\n for (const paneId of this._paneOrder) {\n if (paneId === this._mainPaneId) continue;\n indicatorPanesHeight += this._paneMap.get(paneId)!.height;\n }\n\n // Main pane gets the remainder\n const mainPaneHeight = Math.max(50, totalAvailable - indicatorPanesHeight);\n this._mainPane.height = mainPaneHeight;\n\n // Layout each pane\n for (const paneId of this._paneOrder) {\n const pane = this._paneMap.get(paneId)!;\n pane.layout(chartW, leftScaleW, PRICE_AXIS_WIDTH, rightScaleVisible, leftScaleVisible, pixelRatio);\n }\n\n // Position time axis below all panes\n const timeAxisTop = this._height - TIME_AXIS_HEIGHT;\n this._timeAxisCanvas.width = Math.round(chartW * pixelRatio);\n this._timeAxisCanvas.height = Math.round(TIME_AXIS_HEIGHT * pixelRatio);\n this._timeAxisCanvas.style.width = `${chartW}px`;\n this._timeAxisCanvas.style.height = `${TIME_AXIS_HEIGHT}px`;\n this._timeAxisCanvas.style.left = `${leftScaleW}px`;\n this._timeAxisCanvas.style.top = `${timeAxisTop}px`;\n }\n\n // ── Paint ─────────────────────────────────────────────────────────────\n\n private _paint(): void {\n if (this._removed) return;\n\n // Clear cached basis prices so they are recomputed for the new visible range each paint\n if (this._comparisonMode) {\n this._basisPrices.clear();\n }\n\n // Sync dataLength from primary series\n if (this._series.length > 0) {\n const primaryStore = this._series[0].api.getDataLayer().store;\n this._timeScale.setDataLength(primaryStore.length);\n }\n\n for (const paneId of this._paneOrder) {\n const pane = this._paneMap.get(paneId)!;\n const level = this._mask.level(paneId);\n const seriesForPane = this._series.filter(s => s.paneId === paneId);\n\n if (level >= InvalidationLevel.Light) {\n this._paintPane(pane, seriesForPane);\n this._paintPanePriceAxis(pane, seriesForPane);\n this._paintPaneLeftPriceAxis(pane, seriesForPane);\n }\n if (level >= InvalidationLevel.Cursor) {\n this._paintPaneOverlay(pane);\n // Redraw axes on cursor move too (for crosshair labels) -- axes are tiny, very cheap\n this._paintPanePriceAxis(pane, seriesForPane);\n this._paintPaneLeftPriceAxis(pane, seriesForPane);\n }\n }\n\n // Shared time axis\n this._paintTimeAxis();\n\n // Emit crosshair callbacks\n this._emitCrosshairCallbacks();\n\n this._updateHud();\n this._updateTooltip();\n\n // Emit visible range change callbacks (Feature 3)\n if (this._visibleRangeChangeCallbacks.length > 0) {\n this._emitVisibleRangeChange();\n }\n\n // Check alert line crossings against current price\n if (this._alertLines.length > 0 && this._series.length > 0) {\n const store = this._series[0].api.getDataLayer().store;\n if (store.length > 0) {\n const currentPrice = store.close[store.length - 1];\n for (const alert of this._alertLines) {\n alert.checkCrossing(currentPrice);\n }\n }\n }\n\n this._mask.reset();\n\n // Continue animation loop if any price scale or last bar is still animating\n if (this._isAnimating()) {\n this.requestRepaint(InvalidationLevel.Light);\n }\n }\n\n /**\n * Tick the last bar animation for a series. Returns the animation state\n * (with interpolated display values), or null if no animation is needed.\n */\n private _tickLastBarAnim(\n api: SeriesApi<SeriesType>,\n store: ColumnStore,\n lastIdx: number,\n ): LastBarAnimState | null {\n const anim = this._lastBarAnims.get(api);\n const actualOpen = store.open[lastIdx];\n const actualHigh = store.high[lastIdx];\n const actualLow = store.low[lastIdx];\n const actualClose = store.close[lastIdx];\n\n if (!anim || anim.lastIdx !== lastIdx) {\n // First time seeing this bar, or bar index changed — snap, no animation\n this._lastBarAnims.set(api, {\n lastIdx,\n open: actualOpen,\n high: actualHigh,\n low: actualLow,\n close: actualClose,\n animating: false,\n });\n return null;\n }\n\n // Check if actual values have changed from what we're displaying\n const range = Math.abs(actualHigh - actualLow) || 1;\n const eps = range * LAST_BAR_SNAP;\n const diffO = Math.abs(anim.open - actualOpen);\n const diffH = Math.abs(anim.high - actualHigh);\n const diffL = Math.abs(anim.low - actualLow);\n const diffC = Math.abs(anim.close - actualClose);\n\n if (diffO < eps && diffH < eps && diffL < eps && diffC < eps) {\n // Already converged\n anim.open = actualOpen;\n anim.high = actualHigh;\n anim.low = actualLow;\n anim.close = actualClose;\n anim.animating = false;\n return anim;\n }\n\n // Lerp toward actual values\n anim.open += (actualOpen - anim.open) * LAST_BAR_LERP;\n anim.high += (actualHigh - anim.high) * LAST_BAR_LERP;\n anim.low += (actualLow - anim.low) * LAST_BAR_LERP;\n anim.close += (actualClose - anim.close) * LAST_BAR_LERP;\n anim.animating = true;\n\n return anim;\n }\n\n /** Returns true if any animation (price scale or last bar) is still running. */\n private _isAnimating(): boolean {\n // Check price scales\n for (const paneId of this._paneOrder) {\n const pane = this._paneMap.get(paneId)!;\n if (pane.priceScale.isAnimating || pane.leftPriceScale.isAnimating) {\n return true;\n }\n }\n // Check last bar animations\n for (const anim of this._lastBarAnims.values()) {\n if (anim.animating) return true;\n }\n return false;\n }\n\n private _emitCrosshairCallbacks(): void {\n if (this._crosshair.visible) {\n const state: CrosshairState = {\n x: this._crosshair.x,\n y: this._crosshair.y,\n barIndex: this._crosshair.barIndex,\n price: this._crosshair.price,\n time: this._crosshair.time,\n snappedX: this._crosshair.snappedX,\n };\n for (const cb of this._crosshairMoveCallbacks) cb(state);\n } else {\n for (const cb of this._crosshairMoveCallbacks) cb(null);\n }\n }\n\n private _emitVisibleRangeChange(): void {\n if (this._series.length === 0) {\n if (this._lastVisibleRangeFrom !== null || this._lastVisibleRangeTo !== null) {\n this._lastVisibleRangeFrom = null;\n this._lastVisibleRangeTo = null;\n for (const cb of this._visibleRangeChangeCallbacks) cb(null);\n }\n return;\n }\n\n const store = this._series[0].api.getDataLayer().store;\n if (store.length === 0) {\n if (this._lastVisibleRangeFrom !== null || this._lastVisibleRangeTo !== null) {\n this._lastVisibleRangeFrom = null;\n this._lastVisibleRangeTo = null;\n for (const cb of this._visibleRangeChangeCallbacks) cb(null);\n }\n return;\n }\n\n const range = this._timeScale.visibleRange();\n const fromTime = store.time[Math.max(0, range.fromIdx)];\n const toTime = store.time[Math.min(store.length - 1, range.toIdx)];\n\n if (fromTime !== this._lastVisibleRangeFrom || toTime !== this._lastVisibleRangeTo) {\n this._lastVisibleRangeFrom = fromTime;\n this._lastVisibleRangeTo = toTime;\n const payload = { from: fromTime, to: toTime };\n for (const cb of this._visibleRangeChangeCallbacks) cb(payload);\n }\n }\n\n private _paintPane(pane: Pane, seriesForPane: SeriesEntry[]): void {\n const pixelRatio = window.devicePixelRatio || 1;\n const ctx = pane.canvases.chartCtx;\n const chartW = this._chartWidth;\n const chartH = pane.height;\n const isMain = pane.id === this._mainPaneId;\n\n // Clear chart canvas\n ctx.clearRect(0, 0, Math.round(chartW * pixelRatio), Math.round(chartH * pixelRatio));\n\n // Clear WebGL canvas if present\n const gl = pane.canvases.webglCtx ?? null;\n if (gl) {\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n }\n\n if (seriesForPane.length === 0 && !isMain) return;\n\n // For the main pane (or any pane with series), find the primary series for data length & visible range\n const primaryEntry = this._series.length > 0 ? this._series[0] : null;\n const primaryStore = primaryEntry ? primaryEntry.api.getDataLayer().store : null;\n\n if (primaryStore) {\n this._timeScale.setDataLength(primaryStore.length);\n }\n\n const range = this._timeScale.visibleRange();\n\n if (!primaryStore || range.fromIdx > range.toIdx || primaryStore.length === 0) {\n if (seriesForPane.length === 0) return;\n }\n\n // Auto-scale price from visible data (only series assigned to this pane)\n this._updatePaneDataRange(pane, seriesForPane, range);\n\n // Advance price scale animations (smooth Y-axis transitions)\n pane.priceScale.tick();\n pane.leftPriceScale.tick();\n\n if (isMain) {\n // Draw watermark BEFORE grid/series so it appears behind everything\n this._drawWatermark(ctx, chartW, chartH, pixelRatio);\n }\n\n if (isMain && primaryStore) {\n // Draw grid (within chart area only)\n this._drawGrid(ctx, chartW, chartH, range, primaryStore, pane.priceScale, pixelRatio);\n }\n\n // Clip series rendering to chart area\n ctx.save();\n ctx.beginPath();\n ctx.rect(0, 0, Math.round(chartW * pixelRatio), Math.round(chartH * pixelRatio));\n ctx.clip();\n\n // Draw each series\n const target = this._createRenderTarget(pane.canvases.chartCanvas, ctx, chartW, chartH, pixelRatio);\n const indexToX = (i: number) => this._timeScale.indexToX(i);\n\n // Primary priceToY for this pane (used for markers, price lines, last close line).\n // In comparison mode it is keyed to the first visible series in this pane.\n const primaryEntryForPane = seriesForPane.find(e => e.api.isVisible()) ?? null;\n const primaryPriceToY: (p: number) => number = this._comparisonMode && primaryEntryForPane\n ? (() => {\n const basis = this._getBasisPrice(primaryEntryForPane, range);\n return (price: number) => {\n const pct = basis === 0 ? 0 : ((price - basis) / basis) * 100;\n return pane.priceScale.priceToY(pct);\n };\n })()\n : (p: number) => pane.priceScale.priceToY(p);\n\n // Volume overlay (main pane only) — drawn before series so it appears behind\n if (isMain && this._options.volume.visible) {\n this._drawVolumeOverlay(ctx, chartW, chartH, range, pixelRatio);\n }\n\n for (const entry of seriesForPane) {\n if (!entry.api.isVisible()) continue;\n\n const rawStore = entry.api.getDataLayer().store;\n const store = this._getEffectiveStore(entry, rawStore);\n let priceToY: (p: number) => number;\n if (this._comparisonMode) {\n const basis = this._getBasisPrice(entry, range);\n priceToY = (price: number) => {\n const pct = basis === 0 ? 0 : ((price - basis) / basis) * 100;\n return pane.priceScale.priceToY(pct);\n };\n } else {\n priceToY = (p: number) => pane.priceScale.priceToY(p);\n }\n this._drawSeries(entry, target, store, range, indexToX, priceToY);\n }\n\n // Markers (main pane only)\n if (isMain) {\n for (const entry of seriesForPane) {\n if (!entry.api.isVisible()) continue;\n const markers = entry.api.getMarkers();\n if (markers.length > 0) {\n const dataLayer = entry.api.getDataLayer();\n this._drawMarkers(ctx, markers, dataLayer, range, indexToX, primaryPriceToY, pixelRatio);\n }\n }\n }\n\n // Price lines (main pane only)\n if (isMain) {\n for (const entry of seriesForPane) {\n if (!entry.api.isVisible()) continue;\n const priceLines = entry.api.getPriceLines();\n if (priceLines.length > 0) {\n this._drawPriceLines(ctx, priceLines, chartW, primaryPriceToY, pixelRatio);\n }\n }\n }\n\n // Alert lines (main pane only)\n if (isMain && this._alertLines.length > 0) {\n this._drawAlertLines(ctx, chartW, primaryPriceToY, pixelRatio);\n }\n\n // Text labels (main pane only) — reuse existing target and indexToX from above\n if (isMain && this._textLabels.length > 0) {\n for (const label of this._textLabels) {\n const view = label.createPaneView(indexToX, primaryPriceToY);\n const renderer = view.renderer();\n renderer?.draw(target);\n }\n }\n\n // Last close price line (main pane only)\n if (isMain && this._options.lastPriceLine.visible && primaryStore && primaryStore.length > 0) {\n const lastClose = primaryStore.close[primaryStore.length - 1];\n const lastOpen = primaryStore.open[primaryStore.length - 1];\n const isUp = lastClose >= lastOpen;\n const lineColor = isUp ? '#22AB94' : '#F7525F';\n const lastY = Math.round(primaryPriceToY(lastClose) * pixelRatio);\n\n ctx.save();\n ctx.strokeStyle = lineColor;\n ctx.lineWidth = pixelRatio;\n ctx.setLineDash([4 * pixelRatio, 4 * pixelRatio]);\n ctx.beginPath();\n ctx.moveTo(0, lastY);\n ctx.lineTo(Math.round(chartW * pixelRatio), lastY);\n ctx.stroke();\n ctx.restore();\n }\n\n ctx.restore();\n\n // Draw separator lines on chart canvas edges\n ctx.save();\n ctx.strokeStyle = this._options.grid.horzLinesColor;\n ctx.lineWidth = Math.max(1, Math.round(pixelRatio));\n // Right edge separator (chart area | price axis)\n ctx.beginPath();\n ctx.moveTo(Math.round(chartW * pixelRatio) - 1, 0);\n ctx.lineTo(Math.round(chartW * pixelRatio) - 1, Math.round(chartH * pixelRatio));\n ctx.stroke();\n // Bottom edge separator (chart area / time axis)\n ctx.beginPath();\n ctx.moveTo(0, Math.round(chartH * pixelRatio) - 1);\n ctx.lineTo(Math.round(chartW * pixelRatio), Math.round(chartH * pixelRatio) - 1);\n ctx.stroke();\n ctx.restore();\n }\n\n /** Set of series types that have WebGL renderer implementations. */\n private static readonly _WEBGL_SUPPORTED_TYPES = new Set<SeriesType>([\n 'candlestick', 'heikin-ashi', 'line', 'area',\n ]);\n\n private _drawSeries(\n entry: SeriesEntry,\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (p: number) => number,\n ): void {\n const barWidth = this._timeScale.barSpacing * 0.8;\n\n // ── Last bar animation: interpolate OHLC for smooth streaming ────────\n const lastIdx = store.length - 1;\n let saved: { o: number; h: number; l: number; c: number } | null = null;\n\n if (lastIdx >= 0 && lastIdx >= range.fromIdx && lastIdx <= range.toIdx) {\n const anim = this._tickLastBarAnim(entry.api, store, lastIdx);\n if (anim && anim.animating) {\n // Temporarily write interpolated values into the store for rendering\n saved = {\n o: store.open[lastIdx],\n h: store.high[lastIdx],\n l: store.low[lastIdx],\n c: store.close[lastIdx],\n };\n store.open[lastIdx] = anim.open;\n store.high[lastIdx] = anim.high;\n store.low[lastIdx] = anim.low;\n store.close[lastIdx] = anim.close;\n }\n }\n\n // ── WebGL fast path for supported types ──────────────────────────────\n const pane = this._paneMap.get(entry.paneId);\n const gl = pane?.canvases.webglCtx ?? null;\n\n if (gl && this._useWebGL && ChartApi._WEBGL_SUPPORTED_TYPES.has(entry.type)) {\n const pixelRatio = target.pixelRatio;\n const w = target.width;\n const h = target.height;\n\n switch (entry.type) {\n case 'candlestick':\n case 'heikin-ashi':\n this._webglCandlestick!.applyOptions((entry.renderer as CandlestickRenderer).options());\n this._webglCandlestick!.draw(gl, w, h, pixelRatio, store, range, indexToX, priceToY, barWidth);\n break;\n case 'line':\n this._webglLine!.applyOptions((entry.renderer as LineRenderer).options());\n this._webglLine!.draw(gl, w, h, pixelRatio, store, range, indexToX, priceToY);\n break;\n case 'area':\n this._webglArea!.applyOptions((entry.renderer as AreaRenderer).options());\n this._webglArea!.draw(gl, w, h, pixelRatio, store, range, indexToX, priceToY);\n break;\n }\n\n // Restore store if needed\n if (saved !== null) {\n store.open[lastIdx] = saved.o;\n store.high[lastIdx] = saved.h;\n store.low[lastIdx] = saved.l;\n store.close[lastIdx] = saved.c;\n }\n return;\n }\n\n // ── Canvas 2D path ──────────────────────────────────────────────────\n switch (entry.type) {\n case 'candlestick':\n case 'heikin-ashi':\n (entry.renderer as CandlestickRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'line':\n (entry.renderer as LineRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'area':\n (entry.renderer as AreaRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'bar':\n (entry.renderer as BarOHLCRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'baseline':\n (entry.renderer as BaselineRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'hollow-candle':\n (entry.renderer as HollowCandleRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'histogram':\n (entry.renderer as HistogramRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'step-line':\n (entry.renderer as StepLineRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'colored-line':\n (entry.renderer as ColoredLineRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'colored-mountain':\n (entry.renderer as ColoredMountainRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'hlc-area':\n (entry.renderer as HLCAreaRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'high-low':\n (entry.renderer as HighLowRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'column':\n (entry.renderer as ColumnRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'volume-candle':\n (entry.renderer as VolumeCandleRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'baseline-delta-mountain':\n (entry.renderer as BaselineDeltaMountainRenderer).draw(target, store, range, indexToX, priceToY);\n break;\n case 'renko':\n (entry.renderer as RenkoRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'kagi':\n (entry.renderer as KagiRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'line-break':\n (entry.renderer as LineBreakRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n case 'point-figure':\n (entry.renderer as PointFigureRenderer).draw(target, store, range, indexToX, priceToY, barWidth);\n break;\n }\n\n // Restore original store values after rendering\n if (saved !== null) {\n store.open[lastIdx] = saved.o;\n store.high[lastIdx] = saved.h;\n store.low[lastIdx] = saved.l;\n store.close[lastIdx] = saved.c;\n }\n }\n\n private _paintPaneOverlay(pane: Pane): void {\n const pixelRatio = window.devicePixelRatio || 1;\n const ctx = pane.canvases.overlayCtx;\n const chartW = this._chartWidth;\n const chartH = pane.height;\n const isMain = pane.id === this._mainPaneId;\n\n // Overlay canvas is sized to chart area only\n ctx.clearRect(0, 0, Math.round(chartW * pixelRatio), Math.round(chartH * pixelRatio));\n\n // Render drawings on overlay canvas (main pane only for now)\n if (isMain && this._drawings.length > 0) {\n const target = {\n canvas: pane.canvases.overlayCanvas,\n context: ctx,\n width: Math.round(chartW * pixelRatio),\n height: Math.round(chartH * pixelRatio),\n pixelRatio,\n };\n for (const drawing of this._drawings) {\n const views = drawing.paneViews?.();\n if (!views) continue;\n for (const view of views) {\n const renderer = view.renderer();\n renderer?.drawBackground?.(target);\n }\n }\n for (const drawing of this._drawings) {\n const views = drawing.paneViews?.();\n if (!views) continue;\n for (const view of views) {\n const renderer = view.renderer();\n renderer?.draw(target);\n }\n }\n }\n\n // Range selection overlay (main pane only)\n if (isMain && this._rangeSelectionHandler?.selecting) {\n const rsh = this._rangeSelectionHandler;\n const sx = Math.round(Math.min(rsh.startX, rsh.endX) * pixelRatio);\n const ex = Math.round(Math.max(rsh.startX, rsh.endX) * pixelRatio);\n const selW = ex - sx;\n ctx.save();\n ctx.fillStyle = 'rgba(33, 150, 243, 0.15)';\n ctx.fillRect(sx, 0, selW, Math.round(chartH * pixelRatio));\n ctx.strokeStyle = 'rgba(33, 150, 243, 0.6)';\n ctx.lineWidth = pixelRatio;\n ctx.setLineDash([]);\n ctx.strokeRect(sx, 0, selW, Math.round(chartH * pixelRatio));\n ctx.restore();\n }\n\n // Measure tool overlay (main pane only)\n if (isMain && this._measureHandler?.firstPoint) {\n const mh = this._measureHandler;\n const p1 = mh.firstPoint!;\n const p2 = mh.secondPoint ?? (mh.hovering ? { x: mh.hoverX, y: mh.hoverY } : null);\n if (p2) {\n const x1 = Math.round(p1.x * pixelRatio);\n const y1 = Math.round(p1.y * pixelRatio);\n const x2 = Math.round(p2.x * pixelRatio);\n const y2 = Math.round(p2.y * pixelRatio);\n ctx.save();\n ctx.strokeStyle = '#FF9800';\n ctx.lineWidth = pixelRatio;\n ctx.setLineDash([6 * pixelRatio, 4 * pixelRatio]);\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n ctx.setLineDash([]);\n // Draw endpoint dots\n ctx.fillStyle = '#FF9800';\n const dotR = 3 * pixelRatio;\n ctx.beginPath();\n ctx.arc(x1, y1, dotR, 0, Math.PI * 2);\n ctx.fill();\n ctx.beginPath();\n ctx.arc(x2, y2, dotR, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n }\n }\n\n if (!this._crosshair.visible) return;\n\n const opts = this._options.crosshair;\n\n // Vertical crosshair line draws on ALL panes (shared X)\n const vx = Math.round(this._crosshair.snappedX * pixelRatio);\n ctx.save();\n ctx.strokeStyle = opts.vertLineColor;\n ctx.lineWidth = opts.vertLineWidth * pixelRatio;\n ctx.setLineDash(opts.vertLineDash.map((d) => d * pixelRatio));\n ctx.beginPath();\n ctx.moveTo(vx, 0);\n ctx.lineTo(vx, Math.round(chartH * pixelRatio));\n ctx.stroke();\n ctx.restore();\n\n // Horizontal crosshair line on the pane where the pointer is\n if (pane.id === this._crosshair.sourcePaneId) {\n const hy = Math.round(this._crosshair.y * pixelRatio);\n ctx.save();\n ctx.strokeStyle = opts.horzLineColor;\n ctx.lineWidth = opts.horzLineWidth * pixelRatio;\n ctx.setLineDash(opts.horzLineDash.map((d) => d * pixelRatio));\n ctx.beginPath();\n ctx.moveTo(0, hy);\n ctx.lineTo(Math.round(chartW * pixelRatio), hy);\n ctx.stroke();\n ctx.restore();\n }\n }\n\n // ── Grid ──────────────────────────────────────────────────────────────\n\n private _drawGrid(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n range: VisibleRange,\n store: ColumnStore,\n priceScale: PriceScale,\n pixelRatio: number,\n ): void {\n const gridOpts = this._options.grid;\n\n ctx.save();\n ctx.lineWidth = Math.max(1, Math.round(pixelRatio));\n\n // Horizontal price grid lines\n if (gridOpts.horzLinesVisible) {\n ctx.strokeStyle = gridOpts.horzLinesColor;\n const priceRange = priceScale.priceRange;\n const pRange = priceRange.max - priceRange.min;\n const targetHorzSteps = Math.max(2, Math.floor(h / 60));\n const step = niceStep(pRange, targetHorzSteps);\n\n const firstPrice = Math.ceil(priceRange.min / step) * step;\n for (let price = firstPrice; price <= priceRange.max; price += step) {\n const y = Math.round(priceScale.priceToY(price) * pixelRatio);\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(Math.round(w * pixelRatio), y);\n ctx.stroke();\n }\n }\n\n // Vertical time grid lines\n if (gridOpts.vertLinesVisible && store.length > 0) {\n ctx.strokeStyle = gridOpts.vertLinesColor;\n const barsInRange = range.toIdx - range.fromIdx + 1;\n const targetVertSteps = Math.max(2, Math.floor(w / 100));\n const barStep = Math.max(1, Math.round(barsInRange / targetVertSteps));\n\n for (let i = range.fromIdx; i <= range.toIdx; i += barStep) {\n const x = Math.round(this._timeScale.indexToX(i) * pixelRatio);\n ctx.beginPath();\n ctx.moveTo(x, 0);\n ctx.lineTo(x, Math.round(h * pixelRatio));\n ctx.stroke();\n }\n }\n\n ctx.restore();\n }\n\n // ── Price axis per-pane ───────────────────────────────────────────────\n\n private _paintPanePriceAxis(pane: Pane, seriesForPane: SeriesEntry[]): void {\n const pixelRatio = window.devicePixelRatio || 1;\n const ctx = pane.canvases.rightPriceAxisCtx;\n const chartH = pane.height;\n const axisW = PRICE_AXIS_WIDTH;\n const isMain = pane.id === this._mainPaneId;\n\n ctx.clearRect(0, 0, Math.round(axisW * pixelRatio), Math.round(chartH * pixelRatio));\n\n const layout = this._options.layout;\n const priceRange = pane.priceScale.priceRange;\n const pRange = priceRange.max - priceRange.min;\n const targetSteps = Math.max(2, Math.floor(chartH / 60));\n const step = niceStep(pRange, targetSteps);\n\n // Label formatter — percentage format in comparison mode\n const formatAxisLabel = this._comparisonMode\n ? (value: number) => {\n const sign = value > 0 ? '+' : '';\n return `${sign}${value.toFixed(1)}%`;\n }\n : (value: number) => this._formatPrice(value);\n\n ctx.save();\n ctx.font = `${Math.round(layout.fontSize * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n\n const axisRight = Math.round(axisW * pixelRatio);\n const padding = Math.round(6 * pixelRatio);\n const labelHeight = Math.round(layout.fontSize * 1.6 * pixelRatio);\n\n const firstPrice = Math.ceil(priceRange.min / step) * step;\n for (let price = firstPrice; price <= priceRange.max; price += step) {\n const y = Math.round(pane.priceScale.priceToY(price) * pixelRatio);\n if (y < labelHeight / 2 || y > Math.round(chartH * pixelRatio) - labelHeight / 2) continue;\n\n const text = formatAxisLabel(price);\n\n // Draw background rect\n ctx.fillStyle = this._options.layout.backgroundColor;\n ctx.fillRect(0, y - labelHeight / 2, axisRight, labelHeight);\n\n // Draw text\n ctx.fillStyle = layout.textColor;\n ctx.fillText(text, axisRight - padding, y);\n }\n\n // Draw left separator line\n ctx.strokeStyle = this._options.grid.horzLinesColor;\n ctx.lineWidth = Math.max(1, Math.round(pixelRatio));\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(0, Math.round(chartH * pixelRatio));\n ctx.stroke();\n\n // Current price label (last close) — main pane only\n if (isMain && this._options.lastPriceLine.visible && this._series.length > 0) {\n const primaryEntry = this._series[0];\n const store = primaryEntry.api.getDataLayer().store;\n if (store.length > 0) {\n const lastClose = store.close[store.length - 1];\n const lastOpen = store.open[store.length - 1];\n const isUp = lastClose >= lastOpen;\n const bgColor = isUp ? '#22AB94' : '#F7525F';\n // In comparison mode, map last close to percent space for Y position\n let labelY: number;\n let priceText: string;\n if (this._comparisonMode) {\n const range = this._timeScale.visibleRange();\n const basis = this._getBasisPrice(primaryEntry, range);\n const pct = basis === 0 ? 0 : ((lastClose - basis) / basis) * 100;\n labelY = Math.round(pane.priceScale.priceToY(pct) * pixelRatio);\n priceText = formatAxisLabel(pct);\n } else {\n labelY = Math.round(pane.priceScale.priceToY(lastClose) * pixelRatio);\n priceText = this._formatPrice(lastClose);\n }\n const lh = Math.round(layout.fontSize * 1.8 * pixelRatio);\n\n // Background\n ctx.fillStyle = bgColor;\n ctx.fillRect(0, labelY - lh / 2, axisRight, lh);\n\n // Text\n ctx.fillStyle = '#ffffff';\n ctx.font = `bold ${Math.round(layout.fontSize * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n ctx.fillText(priceText, axisRight - padding, labelY);\n }\n }\n\n // Price line labels on axis (main pane only)\n if (isMain) {\n for (const entry of seriesForPane) {\n if (!entry.api.isVisible()) continue;\n for (const pl of entry.api.getPriceLines()) {\n if (!pl.options.axisLabelVisible) continue;\n const plY = Math.round(pane.priceScale.priceToY(pl.options.price) * pixelRatio);\n if (plY < labelHeight / 2 || plY > Math.round(chartH * pixelRatio) - labelHeight / 2) continue;\n const plText = formatAxisLabel(pl.options.price);\n const plLh = Math.round(layout.fontSize * 1.8 * pixelRatio);\n\n ctx.fillStyle = pl.options.axisLabelColor ?? pl.options.color;\n ctx.fillRect(0, plY - plLh / 2, axisRight, plLh);\n\n ctx.fillStyle = pl.options.axisLabelTextColor ?? '#ffffff';\n ctx.font = `bold ${Math.round(layout.fontSize * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n ctx.fillText(plText, axisRight - padding, plY);\n }\n }\n }\n\n // Crosshair price label on the pane the pointer is over\n if (pane.id === this._crosshair.sourcePaneId && this._crosshair.visible) {\n const hy = Math.round(this._crosshair.y * pixelRatio);\n // In comparison mode, crosshair.price is still a raw price; convert to pct for display\n let priceText: string;\n if (this._comparisonMode && this._series.length > 0) {\n const primaryEntry = this._series[0];\n const range = this._timeScale.visibleRange();\n const basis = this._getBasisPrice(primaryEntry, range);\n const pct = basis === 0 ? 0 : ((this._crosshair.price - basis) / basis) * 100;\n priceText = formatAxisLabel(pct);\n } else {\n priceText = this._formatPrice(this._crosshair.price);\n }\n const lh = Math.round(layout.fontSize * 1.8 * pixelRatio);\n\n ctx.fillStyle = this._options.crosshair.horzLineColor;\n ctx.fillRect(0, hy - lh / 2, axisRight, lh);\n\n ctx.fillStyle = '#ffffff';\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n ctx.fillText(priceText, axisRight - padding, hy);\n }\n\n ctx.restore();\n }\n\n // ── Tick type helper ─────────────────────────────────────────────────\n\n private _getTickType(store: ColumnStore): 'year' | 'month' | 'day' | 'time' {\n if (store.length < 2) return 'day';\n const interval = store.time[1] - store.time[0];\n if (interval < 86400) return 'time';\n if (interval < 86400 * 28) return 'day';\n if (interval < 86400 * 365) return 'month';\n return 'year';\n }\n\n // ── Time axis (on its own canvas) ─────────────────────────────────────\n\n private _paintTimeAxis(): void {\n const pixelRatio = window.devicePixelRatio || 1;\n const ctx = this._timeAxisCtx;\n const chartW = this._chartWidth;\n\n ctx.clearRect(0, 0, Math.round(chartW * pixelRatio), Math.round(TIME_AXIS_HEIGHT * pixelRatio));\n\n if (this._series.length === 0) return;\n\n const primaryEntry = this._series[0];\n const primaryStore = primaryEntry.api.getDataLayer().store;\n if (primaryStore.length === 0) return;\n\n this._timeScale.setDataLength(primaryStore.length);\n const range = this._timeScale.visibleRange();\n if (range.fromIdx > range.toIdx) return;\n\n const layout = this._options.layout;\n const barsInRange = range.toIdx - range.fromIdx + 1;\n const targetSteps = Math.max(2, Math.floor(chartW / 100));\n const barStep = Math.max(1, Math.round(barsInRange / targetSteps));\n\n ctx.save();\n ctx.font = `${Math.round(layout.fontSize * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'top';\n ctx.fillStyle = layout.textColor;\n\n const textY = Math.round(8 * pixelRatio);\n\n const tickType = this._getTickType(primaryStore);\n\n for (let i = range.fromIdx; i <= range.toIdx; i += barStep) {\n if (i >= primaryStore.length) break;\n const x = Math.round(this._timeScale.indexToX(i) * pixelRatio);\n if (x < 0 || x > Math.round(chartW * pixelRatio)) continue;\n\n const timestamp = primaryStore.time[i];\n const label = this._timeFormat(timestamp, tickType);\n\n ctx.fillText(label, x, textY);\n }\n\n // Draw top separator line\n ctx.strokeStyle = this._options.grid.horzLinesColor;\n ctx.lineWidth = Math.max(1, Math.round(pixelRatio));\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(Math.round(chartW * pixelRatio), 0);\n ctx.stroke();\n\n // Crosshair time label\n if (this._crosshair.visible && this._series.length > 0) {\n const store = this._series[0].api.getDataLayer().store;\n if (store.length > 0 && this._crosshair.barIndex >= 0 && this._crosshair.barIndex < store.length) {\n const vx = Math.round(this._crosshair.snappedX * pixelRatio);\n const timestamp = store.time[this._crosshair.barIndex];\n\n const crosshairTickType = this._getTickType(store);\n const timeLabel = this._timeFormat(timestamp, crosshairTickType, true);\n\n const lh = Math.round(layout.fontSize * 1.8 * pixelRatio);\n const tw = Math.round(50 * pixelRatio);\n\n ctx.fillStyle = this._options.crosshair.vertLineColor;\n ctx.fillRect(vx - tw / 2, 0, tw, lh);\n\n ctx.fillStyle = '#ffffff';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'top';\n ctx.fillText(timeLabel, vx, Math.round(2 * pixelRatio));\n }\n }\n\n ctx.restore();\n }\n\n // ── Auto-scale price range (per-pane) ─────────────────────────────────\n\n private _updatePaneDataRange(pane: Pane, seriesForPane: SeriesEntry[], range: VisibleRange): void {\n let rightMin = Infinity;\n let rightMax = -Infinity;\n let leftMin = Infinity;\n let leftMax = -Infinity;\n\n for (const entry of seriesForPane) {\n if (!entry.api.isVisible()) continue;\n const dataLayer = entry.api.getDataLayer();\n const rawStore = dataLayer.store;\n const store = this._getEffectiveStore(entry, rawStore);\n const to = Math.min(range.toIdx, store.length - 1);\n\n const isLeft = entry.api.options().priceScaleId === 'left';\n\n if (this._comparisonMode) {\n // In comparison mode we must scan in percent space (no segment tree shortcut)\n const basis = this._getBasisPrice(entry, range);\n for (let i = range.fromIdx; i <= to; i++) {\n const loPct = basis === 0 ? 0 : ((store.low[i] - basis) / basis) * 100;\n const hiPct = basis === 0 ? 0 : ((store.high[i] - basis) / basis) * 100;\n if (isLeft) {\n if (loPct < leftMin) leftMin = loPct;\n if (hiPct > leftMax) leftMax = hiPct;\n } else {\n if (loPct < rightMin) rightMin = loPct;\n if (hiPct > rightMax) rightMax = hiPct;\n }\n }\n } else {\n // Use segment tree for O(log n) min/max when the store is the raw (non-transformed) one.\n // Heikin-Ashi and other transforms produce a different store, so fall back to linear scan.\n if (store === rawStore && dataLayer.segmentTree.length === store.length) {\n const { min, max } = dataLayer.queryMinMax(range.fromIdx, to);\n if (isLeft) {\n if (min < leftMin) leftMin = min;\n if (max > leftMax) leftMax = max;\n } else {\n if (min < rightMin) rightMin = min;\n if (max > rightMax) rightMax = max;\n }\n } else {\n // Linear scan fallback for transformed stores\n for (let i = range.fromIdx; i <= to; i++) {\n const lo = store.low[i];\n const hi = store.high[i];\n if (isLeft) {\n if (lo < leftMin) leftMin = lo;\n if (hi > leftMax) leftMax = hi;\n } else {\n if (lo < rightMin) rightMin = lo;\n if (hi > rightMax) rightMax = hi;\n }\n }\n }\n }\n }\n\n if (rightMin < Infinity && rightMax > -Infinity) {\n pane.priceScale.autoScale(rightMin, rightMax);\n }\n if (leftMin < Infinity && leftMax > -Infinity) {\n pane.leftPriceScale.autoScale(leftMin, leftMax);\n }\n }\n\n // ── Watermark ─────────────────────────────────────────────────────────\n\n private _drawWatermark(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n pixelRatio: number,\n ): void {\n const wm = this._options.watermark;\n if (!wm.visible || !wm.text) return;\n\n ctx.save();\n ctx.font = `bold ${Math.round(wm.fontSize * pixelRatio)}px ${this._options.layout.fontFamily}`;\n ctx.fillStyle = wm.color;\n\n let x: number;\n if (wm.horzAlign === 'left') {\n ctx.textAlign = 'left';\n x = Math.round(20 * pixelRatio);\n } else if (wm.horzAlign === 'right') {\n ctx.textAlign = 'right';\n x = Math.round((w - 20) * pixelRatio);\n } else {\n ctx.textAlign = 'center';\n x = Math.round((w / 2) * pixelRatio);\n }\n\n let y: number;\n if (wm.vertAlign === 'top') {\n ctx.textBaseline = 'top';\n y = Math.round(20 * pixelRatio);\n } else if (wm.vertAlign === 'bottom') {\n ctx.textBaseline = 'bottom';\n y = Math.round((h - 20) * pixelRatio);\n } else {\n ctx.textBaseline = 'middle';\n y = Math.round((h / 2) * pixelRatio);\n }\n\n ctx.fillText(wm.text, x, y);\n ctx.restore();\n }\n\n // ── Volume overlay ───────────────────────────────────────────────────\n\n private _drawVolumeOverlay(\n ctx: CanvasRenderingContext2D,\n chartW: number,\n chartH: number,\n range: VisibleRange,\n pixelRatio: number,\n ): void {\n const volOpts = this._options.volume;\n\n // Gather volume data from all visible series (use primary for OHLC coloring)\n const primaryStore = this._series[0].api.getDataLayer().store;\n if (!primaryStore.volume) return;\n const to = Math.min(range.toIdx, primaryStore.length - 1);\n if (to < range.fromIdx) return;\n\n // Find max volume in visible range\n let maxVol = 0;\n for (let i = range.fromIdx; i <= to; i++) {\n const v = primaryStore.volume[i];\n if (v > maxVol) maxVol = v;\n }\n if (maxVol === 0) return;\n\n // Volume occupies the area from scaleMarginTop*chartH to chartH\n const volTop = Math.round(volOpts.scaleMarginTop * chartH * pixelRatio);\n const volBottom = Math.round(chartH * pixelRatio);\n const volHeight = volBottom - volTop;\n\n const barWidth = this._timeScale.barSpacing * 0.8;\n const halfBar = Math.max(1, Math.round((barWidth * pixelRatio) / 2));\n\n ctx.save();\n for (let i = range.fromIdx; i <= to; i++) {\n const vol = primaryStore.volume[i];\n if (vol === 0) continue;\n\n const isUp = primaryStore.close[i] >= primaryStore.open[i];\n ctx.fillStyle = isUp ? volOpts.upColor : volOpts.downColor;\n\n const cx = Math.round(this._timeScale.indexToX(i) * pixelRatio);\n const barH = Math.max(1, Math.round((vol / maxVol) * volHeight));\n const topY = volBottom - barH;\n\n ctx.fillRect(cx - halfBar, topY, halfBar * 2, barH);\n }\n ctx.restore();\n }\n\n // ── Series markers ───────────────────────────────────────────────────\n\n private _drawMarkers(\n ctx: CanvasRenderingContext2D,\n markers: readonly SeriesMarker[],\n dataLayer: DataLayer,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (p: number) => number,\n pixelRatio: number,\n ): void {\n const store = dataLayer.store;\n if (store.length === 0) return;\n\n ctx.save();\n const layout = this._options.layout;\n\n for (const marker of markers) {\n // Binary search for bar index matching marker time\n const idx = dataLayer.findIndex(marker.time);\n if (idx < range.fromIdx || idx > range.toIdx) continue;\n if (idx >= store.length) continue;\n\n const x = Math.round(indexToX(idx) * pixelRatio);\n const size = (marker.size ?? 1) * 8 * pixelRatio;\n const offset = size + 4 * pixelRatio;\n\n let y: number;\n if (marker.position === 'aboveBar') {\n y = Math.round(priceToY(store.high[idx]) * pixelRatio) - offset;\n } else if (marker.position === 'belowBar') {\n y = Math.round(priceToY(store.low[idx]) * pixelRatio) + offset;\n } else {\n y = Math.round(priceToY(store.close[idx]) * pixelRatio);\n }\n\n ctx.fillStyle = marker.color;\n\n switch (marker.shape) {\n case 'circle':\n ctx.beginPath();\n ctx.arc(x, y, size, 0, 2 * Math.PI);\n ctx.fill();\n break;\n case 'square':\n ctx.fillRect(x - size, y - size, size * 2, size * 2);\n break;\n case 'arrowUp': {\n ctx.beginPath();\n ctx.moveTo(x, y - size);\n ctx.lineTo(x - size, y + size);\n ctx.lineTo(x + size, y + size);\n ctx.closePath();\n ctx.fill();\n break;\n }\n case 'arrowDown': {\n ctx.beginPath();\n ctx.moveTo(x, y + size);\n ctx.lineTo(x - size, y - size);\n ctx.lineTo(x + size, y - size);\n ctx.closePath();\n ctx.fill();\n break;\n }\n }\n\n // Draw text label if provided\n if (marker.text) {\n ctx.fillStyle = marker.color;\n ctx.font = `${Math.round(10 * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = marker.position === 'belowBar' ? 'top' : 'bottom';\n const textY = marker.position === 'belowBar'\n ? y + size + 2 * pixelRatio\n : y - size - 2 * pixelRatio;\n ctx.fillText(marker.text, x, textY);\n }\n }\n\n ctx.restore();\n }\n\n // ── Price lines ──────────────────────────────────────────────────────\n\n private _drawPriceLines(\n ctx: CanvasRenderingContext2D,\n priceLines: readonly import('../core/price-line').PriceLine[],\n chartW: number,\n priceToY: (p: number) => number,\n pixelRatio: number,\n ): void {\n ctx.save();\n for (const pl of priceLines) {\n const y = Math.round(priceToY(pl.options.price) * pixelRatio);\n\n ctx.strokeStyle = pl.options.color;\n ctx.lineWidth = pl.options.lineWidth * pixelRatio;\n\n switch (pl.options.lineStyle) {\n case 'dashed':\n ctx.setLineDash([6 * pixelRatio, 4 * pixelRatio]);\n break;\n case 'dotted':\n ctx.setLineDash([2 * pixelRatio, 2 * pixelRatio]);\n break;\n default:\n ctx.setLineDash([]);\n break;\n }\n\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(Math.round(chartW * pixelRatio), y);\n ctx.stroke();\n\n // Draw title text if provided\n if (pl.options.title) {\n ctx.fillStyle = pl.options.color;\n ctx.font = `${Math.round(10 * pixelRatio)}px ${this._options.layout.fontFamily}`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'bottom';\n ctx.fillText(pl.options.title, Math.round(4 * pixelRatio), y - Math.round(2 * pixelRatio));\n }\n }\n ctx.setLineDash([]);\n ctx.restore();\n }\n\n private _drawAlertLines(\n ctx: CanvasRenderingContext2D,\n chartW: number,\n priceToY: (p: number) => number,\n pixelRatio: number,\n ): void {\n ctx.save();\n const bellChar = '\\u{1F514}'; // 🔔\n const fontFamily = this._options.layout.fontFamily;\n\n for (const alert of this._alertLines) {\n const opts = alert.options;\n const y = Math.round(priceToY(opts.price) * pixelRatio);\n const isArmed = opts.armed;\n\n // Line color: full opacity when armed, dim when disarmed\n ctx.globalAlpha = isArmed ? 1 : 0.4;\n ctx.strokeStyle = opts.color;\n ctx.lineWidth = opts.lineWidth * pixelRatio;\n\n switch (opts.lineStyle) {\n case 'dashed':\n ctx.setLineDash([6 * pixelRatio, 4 * pixelRatio]);\n break;\n case 'dotted':\n ctx.setLineDash([2 * pixelRatio, 2 * pixelRatio]);\n break;\n default:\n ctx.setLineDash([]);\n break;\n }\n\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(Math.round(chartW * pixelRatio), y);\n ctx.stroke();\n\n // Bell icon on the right side\n const iconSize = Math.round(10 * pixelRatio);\n const iconX = Math.round(chartW * pixelRatio) - Math.round(16 * pixelRatio);\n ctx.font = `${iconSize}px ${fontFamily}`;\n ctx.fillStyle = opts.color;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'middle';\n ctx.fillText(bellChar, iconX, y);\n\n // Title text on the left\n if (opts.title) {\n ctx.font = `${Math.round(10 * pixelRatio)}px ${fontFamily}`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'bottom';\n ctx.fillText(opts.title, Math.round(4 * pixelRatio), y - Math.round(2 * pixelRatio));\n }\n }\n\n ctx.globalAlpha = 1;\n ctx.setLineDash([]);\n ctx.restore();\n }\n\n // ── Tooltip ──────────────────────────────────────────────────────────\n\n private _updateTooltip(): void {\n if (!this._options.tooltip.enabled || this._series.length === 0) {\n this._tooltipEl.style.display = 'none';\n return;\n }\n\n if (!this._crosshair.visible) {\n this._tooltipEl.style.display = 'none';\n return;\n }\n\n const primaryEntry = this._series[0];\n const rawStore = primaryEntry.api.getDataLayer().store;\n const store = this._getEffectiveStore(primaryEntry, rawStore);\n const idx = this._crosshair.barIndex;\n if (idx < 0 || idx >= store.length) {\n this._tooltipEl.style.display = 'none';\n return;\n }\n\n // Only rebuild content when barIndex changes\n if (idx !== this._lastTooltipBarIdx) {\n this._lastTooltipBarIdx = idx;\n\n const o = store.open[idx];\n const h = store.high[idx];\n const l = store.low[idx];\n const c = store.close[idx];\n const v = rawStore.volume ? rawStore.volume[idx] : 0;\n const timestamp = store.time[idx];\n const tooltipTickType = this._getTickType(store);\n const dateStr = this._timeFormat(timestamp, tooltipTickType, true);\n\n const isUp = c >= o;\n const color = isUp ? '#22AB94' : '#F7525F';\n\n this._tooltipDateEl.textContent = dateStr;\n this._tooltipOHEl.textContent = `O ${this._formatPrice(o)} H ${this._formatPrice(h)}`;\n this._tooltipOHEl.style.color = color;\n this._tooltipLCEl.textContent = `L ${this._formatPrice(l)} C ${this._formatPrice(c)}`;\n this._tooltipLCEl.style.color = color;\n this._tooltipVEl.textContent = `V ${formatVolume(v, this._options.locale)}`;\n this._tooltipVEl.style.color = '#999';\n\n // Re-measure cached dimensions only when content changes\n this._tooltipWidth = this._tooltipEl.offsetWidth || 140;\n this._tooltipHeight = this._tooltipEl.offsetHeight || 80;\n }\n\n // Position tooltip near cursor, ensuring it doesn't overflow\n const chartW = this._chartWidth;\n const chartH = this._mainPane.height;\n const cursorX = this._crosshair.snappedX;\n const cursorY = this._crosshair.y;\n const tooltipW = this._tooltipWidth;\n const tooltipH = this._tooltipHeight;\n\n let tx = cursorX + 16;\n let ty = cursorY - tooltipH - 8;\n\n // Keep within chart bounds\n if (tx + tooltipW > chartW) tx = cursorX - tooltipW - 16;\n if (tx < 0) tx = 4;\n if (ty < 0) ty = cursorY + 16;\n if (ty + tooltipH > chartH) ty = chartH - tooltipH - 4;\n\n this._tooltipEl.style.left = `${Math.round(tx)}px`;\n this._tooltipEl.style.top = `${Math.round(ty)}px`;\n this._tooltipEl.style.display = 'block';\n }\n\n // ── HUD ───────────────────────────────────────────────────────────────\n\n private _createHudForPane(paneId: string, pane: Pane): void {\n const hud = new HudManager(pane.row, {\n bg: this._options.layout.backgroundColor,\n text: this._options.layout.textColor,\n border: this._options.grid.horzLinesColor,\n fontFamily: this._options.layout.fontFamily,\n });\n this._huds.set(paneId, hud);\n\n // Wire cross-pane sync: collapsing the main pane HUD collapses all others\n if (paneId === this._mainPaneId) {\n hud.onGlobalCollapseToggle = () => {\n const collapsed = hud.isGlobalCollapsed;\n for (const [id, otherHud] of this._huds) {\n if (id !== this._mainPaneId) {\n otherHud.setGlobalCollapsed(collapsed);\n }\n }\n };\n }\n }\n\n private _getCrosshairBarIndex(): number {\n if (this._series.length === 0) return -1;\n const store = this._series[0].api.getDataLayer().store;\n if (store.length === 0) return -1;\n\n if (this._crosshair.visible && this._crosshair.barIndex >= 0 && this._crosshair.barIndex < store.length) {\n return this._crosshair.barIndex;\n }\n return store.length - 1;\n }\n\n private _updateHud(): void {\n const barIndex = this._getCrosshairBarIndex();\n for (const hud of this._huds.values()) {\n hud.updateValues(barIndex);\n }\n }\n\n private _getSeriesColor(type: SeriesType, options: Record<string, unknown>): string {\n switch (type) {\n case 'candlestick':\n case 'bar':\n case 'hollow-candle':\n return (options.upColor as string) ?? '#22AB94';\n case 'line':\n return (options.color as string) ?? '#2196F3';\n case 'area':\n return (options.lineColor as string) ?? '#2196F3';\n case 'baseline':\n return (options.topLineColor as string) ?? '#22AB94';\n case 'histogram':\n return (options.upColor as string) ?? '#22AB94';\n default:\n return '#2196F3';\n }\n }\n\n private _getSeriesValues(api: SeriesApi<SeriesType>, barIndex: number): string {\n const rawStore = api.getDataLayer().store;\n if (barIndex < 0 || barIndex >= rawStore.length) return '';\n\n const type = api.seriesType();\n const isOHLC = type === 'candlestick' || type === 'bar' || type === 'hollow-candle' || type === 'heikin-ashi';\n\n if (isOHLC) {\n // For heikin-ashi, use the transformed store via the series entry cache\n const entry = this._series.find(e => e.api === (api as SeriesApi<SeriesType>));\n const store = entry ? this._getEffectiveStore(entry, rawStore) : rawStore;\n const o = store.open[barIndex];\n const h = store.high[barIndex];\n const l = store.low[barIndex];\n const c = store.close[barIndex];\n const v = rawStore.volume ? rawStore.volume[barIndex] : 0;\n return `O ${this._formatPrice(o)} H ${this._formatPrice(h)} L ${this._formatPrice(l)} C ${this._formatPrice(c)} V ${formatVolume(v, this._options.locale)}`;\n }\n\n const c = rawStore.close[barIndex];\n return this._formatPrice(c);\n }\n\n private _getIndicatorValues(indicator: IndicatorApi, barIndex: number): string {\n const parts: string[] = [];\n for (const s of indicator.internalSeries) {\n const impl = s as SeriesApi<SeriesType>;\n const store = impl.getDataLayer().store;\n if (barIndex >= 0 && barIndex < store.length) {\n const val = store.close[barIndex];\n if (!isNaN(val)) {\n parts.push(this._formatPrice(val));\n }\n }\n }\n return parts.join(' ');\n }\n\n private _getSeriesSettingsFields(type: SeriesType, options: Record<string, unknown>): SettingsField[] {\n const fields: SettingsField[] = [];\n switch (type) {\n case 'candlestick':\n fields.push({ key: 'upColor', label: 'Up Color', type: 'color', value: (options.upColor as string) ?? '#22AB94' });\n fields.push({ key: 'downColor', label: 'Down Color', type: 'color', value: (options.downColor as string) ?? '#F7525F' });\n break;\n case 'line':\n fields.push({ key: 'color', label: 'Color', type: 'color', value: (options.color as string) ?? '#2196F3' });\n fields.push({ key: 'lineWidth', label: 'Width', type: 'number', value: (options.lineWidth as number) ?? 2, min: 1, max: 5, step: 1 });\n break;\n case 'area':\n fields.push({ key: 'lineColor', label: 'Line Color', type: 'color', value: (options.lineColor as string) ?? '#2196F3' });\n fields.push({ key: 'topColor', label: 'Top Color', type: 'color', value: (options.topColor as string) ?? 'rgba(33,150,243,0.4)' });\n fields.push({ key: 'bottomColor', label: 'Bottom Color', type: 'color', value: (options.bottomColor as string) ?? 'rgba(33,150,243,0)' });\n break;\n case 'bar':\n case 'hollow-candle':\n fields.push({ key: 'upColor', label: 'Up Color', type: 'color', value: (options.upColor as string) ?? '#22AB94' });\n fields.push({ key: 'downColor', label: 'Down Color', type: 'color', value: (options.downColor as string) ?? '#F7525F' });\n break;\n case 'histogram':\n fields.push({ key: 'upColor', label: 'Up Color', type: 'color', value: (options.upColor as string) ?? '#22AB94' });\n fields.push({ key: 'downColor', label: 'Down Color', type: 'color', value: (options.downColor as string) ?? '#F7525F' });\n break;\n case 'baseline':\n fields.push({ key: 'topLineColor', label: 'Top Color', type: 'color', value: (options.topLineColor as string) ?? '#22AB94' });\n fields.push({ key: 'bottomLineColor', label: 'Bottom Color', type: 'color', value: (options.bottomLineColor as string) ?? '#F7525F' });\n fields.push({ key: 'basePrice', label: 'Base Price', type: 'number', value: (options.basePrice as number) ?? 0, step: 0.01 });\n break;\n }\n return fields;\n }\n\n private _getIndicatorSettingsFields(indicator: IndicatorApi): SettingsField[] {\n const fields: SettingsField[] = [];\n const opts = indicator.options();\n\n // Color field\n fields.push({ key: 'color', label: 'Color', type: 'color', value: opts.color ?? '#2962ff' });\n\n // Params\n const params = opts.params ?? {};\n for (const [key, val] of Object.entries(params)) {\n fields.push({ key, label: key, type: 'number', value: val as number, min: 1, step: 1 });\n }\n\n return fields;\n }\n\n private _registerSeriesHudRow(\n api: SeriesApi<SeriesType>,\n type: SeriesType,\n resolvedOptions: Record<string, unknown>,\n paneId: string,\n seriesIndex: number,\n ): void {\n const hud = this._huds.get(paneId);\n if (!hud) return;\n\n const hudRowId = `series-${type}-${seriesIndex}`;\n hud.addRow({\n id: hudRowId,\n label: (resolvedOptions.label as string) || this._options.symbol || 'Symbol',\n color: this._getSeriesColor(type, resolvedOptions),\n getValues: (barIndex: number) => this._getSeriesValues(api, barIndex),\n onToggleVisible: () => {\n const newVis = !api.isVisible();\n api.applyOptions({ visible: newVis } as never);\n return newVis;\n },\n onRemove: () => { this.removeSeries(api); },\n getSettingsFields: () => this._getSeriesSettingsFields(type, api.options() as unknown as Record<string, unknown>),\n onSettingsApply: (values) => { api.applyOptions(values as never); },\n });\n }\n\n private _registerIndicatorHudRow(indicator: IndicatorApi, options: IndicatorOptions): void {\n const hud = this._huds.get(indicator.paneId());\n if (!hud) return;\n\n hud.addRow({\n id: `indicator-${indicator.id}`,\n label: indicator.label(),\n color: options.color ?? '#2962ff',\n getValues: (barIndex: number) => this._getIndicatorValues(indicator, barIndex),\n onToggleVisible: () => {\n const newVis = !indicator.isVisible();\n indicator.applyOptions({ visible: newVis });\n // Toggle visibility of all internal series\n for (const s of indicator.internalSeries) {\n s.applyOptions({ visible: newVis } as never);\n }\n return newVis;\n },\n onRemove: () => { this.removeIndicator(indicator); },\n getSettingsFields: () => this._getIndicatorSettingsFields(indicator),\n onSettingsApply: (values) => {\n // Separate color from params\n const { color, ...paramValues } = values;\n if (color !== undefined) {\n indicator.applyOptions({ color: color as string });\n }\n if (Object.keys(paramValues).length > 0) {\n // Recompute with new params\n const numParams: Record<string, number> = {};\n for (const [k, v] of Object.entries(paramValues)) {\n numParams[k] = v as number;\n }\n indicator.applyOptions({ params: numParams });\n }\n },\n });\n }\n\n // ── Left Price axis per-pane ────────────────────────────────────────────\n\n private _paintPaneLeftPriceAxis(pane: Pane, seriesForPane: SeriesEntry[]): void {\n if (!this._options.leftPriceScale.visible) return;\n\n const pixelRatio = window.devicePixelRatio || 1;\n const ctx = pane.canvases.leftPriceAxisCtx;\n const chartH = pane.height;\n const axisW = PRICE_AXIS_WIDTH;\n const isMain = pane.id === this._mainPaneId;\n\n ctx.clearRect(0, 0, Math.round(axisW * pixelRatio), Math.round(chartH * pixelRatio));\n\n // Left scale auto-scales independently in _updatePaneDataRange() based on series with priceScaleId: 'left'.\n // Fall back to right scale range if no series are assigned to the left scale.\n const leftRange = pane.leftPriceScale.priceRange;\n if (leftRange.min === leftRange.max) {\n pane.leftPriceScale.autoScale(pane.priceScale.priceRange.min, pane.priceScale.priceRange.max);\n }\n\n const layout = this._options.layout;\n const priceRange = pane.leftPriceScale.priceRange;\n const pRange = priceRange.max - priceRange.min;\n const targetSteps = Math.max(2, Math.floor(chartH / 60));\n const step = niceStep(pRange, targetSteps);\n\n ctx.save();\n ctx.font = `${Math.round(layout.fontSize * pixelRatio)}px ${layout.fontFamily}`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n\n const padding = Math.round(6 * pixelRatio);\n const labelHeight = Math.round(layout.fontSize * 1.6 * pixelRatio);\n\n const firstPrice = Math.ceil(priceRange.min / step) * step;\n for (let price = firstPrice; price <= priceRange.max; price += step) {\n const y = Math.round(pane.leftPriceScale.priceToY(price) * pixelRatio);\n if (y < labelHeight / 2 || y > Math.round(chartH * pixelRatio) - labelHeight / 2) continue;\n\n const text = this._formatPrice(price);\n\n ctx.fillStyle = layout.backgroundColor;\n ctx.fillRect(0, y - labelHeight / 2, Math.round(axisW * pixelRatio), labelHeight);\n\n ctx.fillStyle = layout.textColor;\n ctx.fillText(text, padding, y);\n }\n\n // Draw right separator line\n ctx.strokeStyle = this._options.grid.horzLinesColor;\n ctx.lineWidth = Math.max(1, Math.round(pixelRatio));\n ctx.beginPath();\n ctx.moveTo(Math.round(axisW * pixelRatio) - 1, 0);\n ctx.lineTo(Math.round(axisW * pixelRatio) - 1, Math.round(chartH * pixelRatio));\n ctx.stroke();\n\n // Crosshair price label on left axis for the pane the pointer is over\n if (pane.id === this._crosshair.sourcePaneId && this._crosshair.visible) {\n const hy = Math.round(this._crosshair.y * pixelRatio);\n const priceText = this._formatPrice(this._crosshair.price);\n const lh = Math.round(layout.fontSize * 1.8 * pixelRatio);\n\n ctx.fillStyle = this._options.crosshair.horzLineColor;\n ctx.fillRect(0, hy - lh / 2, Math.round(axisW * pixelRatio), lh);\n\n ctx.fillStyle = '#ffffff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(priceText, padding, hy);\n }\n\n // Suppress unused variable warning\n void seriesForPane;\n\n ctx.restore();\n }\n\n // ── Helpers ───────────────────────────────────────────────────────────\n\n private _createRenderTarget(\n canvas: HTMLCanvasElement,\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n pixelRatio: number,\n ): IRenderTarget {\n return {\n canvas,\n context: ctx,\n width,\n height,\n pixelRatio,\n };\n }\n\n private _addSeries<T extends SeriesType>(\n type: T,\n options: DeepPartial<SeriesOptionsMap[T]>,\n _internal: boolean = false,\n ): ISeriesApi<T> {\n const dataLayer = new DataLayer();\n const resolvedOptions = (options ?? {}) as SeriesOptionsMap[T];\n\n // Determine which pane this series belongs to\n const paneId = (resolvedOptions as { paneId?: string }).paneId ?? this._mainPaneId;\n const pane = this._paneMap.get(paneId);\n if (!pane) {\n throw new Error(`Pane \"${paneId}\" not found. Create it first with addPane().`);\n }\n\n const renderer = this._createRenderer(type, resolvedOptions as unknown as Record<string, unknown>);\n const api = new SeriesApi<T>(type, dataLayer, pane.priceScale, resolvedOptions, () =>\n this.requestRepaint(InvalidationLevel.Full),\n );\n\n this._series.push({ api: api as SeriesApi<SeriesType>, renderer, type, paneId });\n\n // Register HUD row for user-visible (non-internal) series\n if (!_internal) {\n this._registerSeriesHudRow(\n api as SeriesApi<SeriesType>,\n type,\n resolvedOptions as unknown as Record<string, unknown>,\n paneId,\n this._series.length - 1,\n );\n }\n\n // Set up crosshair handler on first series added\n if (this._series.length === 1 && this._crosshairHandler === null) {\n this._crosshairHandler = new CrosshairHandler(\n this._crosshair,\n dataLayer,\n this._timeScale,\n this._mainPane.priceScale,\n () => this.requestRepaint(InvalidationLevel.Cursor),\n this._mainPaneId,\n );\n this._eventRouter.addHandler(this._crosshairHandler);\n }\n\n this.requestRepaint(InvalidationLevel.Full);\n\n if (!_internal) {\n for (const cb of this._chartTypeChangeCallbacks) cb({ seriesType: type });\n }\n\n return api;\n }\n\n private _getEffectiveStore(entry: SeriesEntry, rawStore: ColumnStore): ColumnStore {\n if (entry.type !== 'heikin-ashi') return rawStore;\n const cache = entry._haCache;\n if (cache && cache.length === rawStore.length) return cache.store;\n const haStore = computeHeikinAshi(rawStore);\n entry._haCache = { length: rawStore.length, store: haStore };\n return haStore;\n }\n\n private _createRenderer(\n type: SeriesType,\n options: Record<string, unknown>,\n ): SeriesEntry['renderer'] {\n // Extract renderer-relevant options (exclude BaseSeriesOptions fields)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { data: _d, priceScaleId: _p, visible: _v, paneId: _pi, label: _l, ...rendererOpts } = options;\n\n switch (type) {\n case 'candlestick':\n case 'heikin-ashi': {\n const r = new CandlestickRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'line': {\n const r = new LineRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'area': {\n const r = new AreaRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'bar': {\n const r = new BarOHLCRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'baseline': {\n const r = new BaselineRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'hollow-candle': {\n const r = new HollowCandleRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'histogram': {\n const r = new HistogramRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'step-line': {\n const r = new StepLineRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'colored-line': {\n const r = new ColoredLineRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'colored-mountain': {\n const r = new ColoredMountainRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'hlc-area': {\n const r = new HLCAreaRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'high-low': {\n const r = new HighLowRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'column': {\n const r = new ColumnRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'volume-candle': {\n const r = new VolumeCandleRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'baseline-delta-mountain': {\n const r = new BaselineDeltaMountainRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'renko': {\n const r = new RenkoRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'kagi': {\n const r = new KagiRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'line-break': {\n const r = new LineBreakRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n case 'point-figure': {\n const r = new PointFigureRenderer();\n if (Object.keys(rendererOpts).length > 0) r.applyOptions(rendererOpts as never);\n return r;\n }\n default:\n throw new Error(`Unknown series type: ${type}`);\n }\n }\n\n private _getClickState(e: MouseEvent): { x: number; y: number; time: number; price: number } {\n const rect = this._mainPane.canvases.overlayCanvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const price = this._mainPane.priceScale.yToPrice(y);\n\n let time = 0;\n if (this._series.length > 0) {\n const store = this._series[0].api.getDataLayer().store;\n if (store.length > 0) {\n const idx = Math.max(0, Math.min(store.length - 1, this._timeScale.xToIndex(x)));\n time = store.time[idx];\n }\n }\n return { x, y, time, price };\n }\n\n private _handleClick = (e: MouseEvent): void => {\n if (this._clickCallbacks.length === 0) return;\n const state = this._getClickState(e);\n for (const cb of this._clickCallbacks) cb(state);\n };\n\n private _handleDblClick = (e: MouseEvent): void => {\n if (this._dblClickCallbacks.length === 0) return;\n const state = this._getClickState(e);\n for (const cb of this._dblClickCallbacks) cb(state);\n };\n}\n\n// ─── DrawingApiImpl ─────────────────────────────────────────────────────────\n\nclass DrawingApiImpl implements IDrawingApi {\n readonly id: string;\n private _drawing: ISeriesPrimitive & DrawingPrimitive;\n private _chart: ChartApi;\n\n constructor(id: string, drawing: ISeriesPrimitive & DrawingPrimitive, chart: ChartApi) {\n this.id = id;\n this._drawing = drawing;\n this._chart = chart;\n }\n\n drawingType(): string {\n return this._drawing.drawingType;\n }\n\n points(): AnchorPoint[] {\n return this._drawing.points.map(p => ({ ...p }));\n }\n\n applyOptions(opts: Partial<DrawingOptions>): void {\n Object.assign(this._drawing.options, opts);\n this._chart.requestRepaint(InvalidationLevel.Full);\n }\n\n options(): DrawingOptions {\n return { ...this._drawing.options };\n }\n\n remove(): void {\n this._chart.removeDrawing(this);\n }\n}\n\n// ─── Factory function ───────────────────────────────────────────────────────\n\nexport function createChart(\n container: HTMLElement,\n options?: DeepPartial<ChartOptions>,\n): IChartApi {\n let resolved: ChartOptions;\n if (options) {\n // If a theme is specified, merge theme defaults first, then user options on top\n const theme = options.theme;\n if (theme === 'light') {\n resolved = mergeOptions(mergeOptions(DEFAULT_CHART_OPTIONS, LIGHT_THEME), options);\n } else if (theme === 'dark') {\n resolved = mergeOptions(mergeOptions(DEFAULT_CHART_OPTIONS, DARK_THEME), options);\n } else if (theme === 'colorful') {\n resolved = mergeOptions(mergeOptions(DEFAULT_CHART_OPTIONS, COLORFUL_THEME), options);\n } else {\n resolved = mergeOptions(DEFAULT_CHART_OPTIONS, options);\n }\n } else {\n resolved = { ...DEFAULT_CHART_OPTIONS };\n }\n return new ChartApi(container, resolved);\n}\n"],"mappings":"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"}
|
package/dist/index107.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e){switch(e.unit){case"second":return e.interval;case"minute":return 60*e.interval;case"hour":return 3600*e.interval;case"day":return 86400*e.interval;case"week":return 604800*e.interval;case"month":return 2592e3*e.interval}}var n={second:"s",minute:"m",hour:"h",day:"D",week:"W",month:"M"};function r(e){return`${e.interval}${n[e.unit]}`}export{r as periodicityToLabel,e as periodicityToSeconds};
|
|
2
|
+
//# sourceMappingURL=index107.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index107.js","names":[],"sources":["../src/core/periodicity.ts"],"sourcesContent":["export interface Periodicity {\n interval: number;\n unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month';\n}\n\nexport function periodicityToSeconds(p: Periodicity): number {\n switch (p.unit) {\n case 'second': return p.interval;\n case 'minute': return p.interval * 60;\n case 'hour': return p.interval * 3600;\n case 'day': return p.interval * 86400;\n case 'week': return p.interval * 604800;\n case 'month': return p.interval * 2592000;\n }\n}\n\nconst UNIT_LABELS: Record<string, string> = {\n second: 's', minute: 'm', hour: 'h', day: 'D', week: 'W', month: 'M',\n};\n\nexport function periodicityToLabel(p: Periodicity): string {\n return `${p.interval}${UNIT_LABELS[p.unit]}`;\n}\n"],"mappings":"AAKA,SAAgB,EAAqB,GACnC,OAAQ,EAAE,MACR,IAAK,SAAU,OAAO,EAAE,SACxB,IAAK,SAAU,OAAoB,GAAb,EAAE,SACxB,IAAK,OAAQ,OAAoB,KAAb,EAAE,SACtB,IAAK,MAAO,OAAoB,MAAb,EAAE,SACrB,IAAK,OAAQ,OAAoB,OAAb,EAAE,SACtB,IAAK,QAAS,OAAoB,OAAb,EAAE,UAI3B,IAAM,EAAsC,CAC1C,OAAQ,IAAK,OAAQ,IAAK,KAAM,IAAK,IAAK,IAAK,KAAM,IAAK,MAAO,KAGnE,SAAgB,EAAmB,GACjC,MAAO,GAAG,EAAE,WAAW,EAAY,EAAE"}
|
package/dist/index108.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getTimezoneOffsetMinutes as t}from"./index103.js";var r=[{id:"premarket",label:"PRE",startMinute:240,endMinute:570,bgColor:"rgba(255,235,59,0.05)"},{id:"regular",label:"",startMinute:570,endMinute:960,bgColor:"transparent"},{id:"postmarket",label:"POST",startMinute:960,endMinute:1200,bgColor:"rgba(255,235,59,0.05)"}];function n(t,r){return t>=r.startMinute&&t<r.endMinute}function e(t,r){for(const e of r)if(n(t,e))return e;return null}function o(r,n=-300){const e="string"==typeof n?t(r,n):n;return((Math.floor(r/60)+e)%1440+1440)%1440}export{r as US_EQUITY_SESSIONS,e as getSessionForTime,n as isInSession,o as timestampToMinuteOfDay};
|
|
2
|
+
//# sourceMappingURL=index108.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index108.js","names":[],"sources":["../src/core/market-session.ts"],"sourcesContent":["import { getTimezoneOffsetMinutes } from '../timezone/timezone';\n\nexport interface MarketSession {\n id: string;\n label: string;\n startMinute: number; // minutes from midnight in exchange timezone\n endMinute: number;\n bgColor: string;\n}\n\nexport const US_EQUITY_SESSIONS: MarketSession[] = [\n { id: 'premarket', label: 'PRE', startMinute: 240, endMinute: 570, bgColor: 'rgba(255,235,59,0.05)' },\n { id: 'regular', label: '', startMinute: 570, endMinute: 960, bgColor: 'transparent' },\n { id: 'postmarket', label: 'POST', startMinute: 960, endMinute: 1200, bgColor: 'rgba(255,235,59,0.05)' },\n];\n\nexport function isInSession(minuteOfDay: number, session: MarketSession): boolean {\n return minuteOfDay >= session.startMinute && minuteOfDay < session.endMinute;\n}\n\nexport function getSessionForTime(minuteOfDay: number, sessions: MarketSession[]): MarketSession | null {\n for (const s of sessions) {\n if (isInSession(minuteOfDay, s)) return s;\n }\n return null;\n}\n\nexport function timestampToMinuteOfDay(timestamp: number, utcOffsetOrTimezone: number | string = -300): number {\n const offset = typeof utcOffsetOrTimezone === 'string'\n ? getTimezoneOffsetMinutes(timestamp, utcOffsetOrTimezone)\n : utcOffsetOrTimezone;\n const totalMinutes = Math.floor(timestamp / 60) + offset;\n return ((totalMinutes % 1440) + 1440) % 1440;\n}\n"],"mappings":"yDAUA,IAAa,EAAsC,CACjD,CAAE,GAAI,YAAa,MAAO,MAAO,YAAa,IAAK,UAAW,IAAK,QAAS,yBAC5E,CAAE,GAAI,UAAW,MAAO,GAAI,YAAa,IAAK,UAAW,IAAK,QAAS,eACvE,CAAE,GAAI,aAAc,MAAO,OAAQ,YAAa,IAAK,UAAW,KAAM,QAAS,0BAGjF,SAAgB,EAAY,EAAqB,GAC/C,OAAO,GAAe,EAAQ,aAAe,EAAc,EAAQ,UAGrE,SAAgB,EAAkB,EAAqB,GACrD,IAAK,MAAM,KAAK,EACd,GAAI,EAAY,EAAa,GAAI,OAAO,EAE1C,OAAO,KAGT,SAAgB,EAAuB,EAAmB,GAAuC,KAC/F,MAAM,EAAwC,iBAAxB,EAClB,EAAyB,EAAW,GACpC,EAEJ,QADqB,KAAK,MAAM,EAAY,IAAM,GAC1B,KAAQ,MAAQ"}
|
package/dist/index109.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var t=class{constructor(t){this._ws=null,this._subscriptions=/* @__PURE__ */new Map,this._reconnectAttempts=0,this._reconnectTimer=null,this._connected=!1,this._intentionalClose=!1,this._options={url:t.url,reconnect:t.reconnect??!0,maxReconnectAttempts:t.maxReconnectAttempts??10,reconnectDelay:t.reconnectDelay??1e3,maxReconnectDelay:t.maxReconnectDelay??3e4,parseMessage:t.parseMessage??n}}get connected(){return this._connected}get reconnectAttempts(){return this._reconnectAttempts}connect(){this._clearReconnectTimer(),this._reconnectAttempts=0,this._intentionalClose=!1,this._createConnection()}disconnect(){this._intentionalClose=!0,this._clearReconnectTimer(),this._ws&&(this._ws.close(),this._ws=null),this._connected=!1}subscribeBars(t,e,s){const n=`${t}:${e}`;this._subscriptions.set(n,s)}unsubscribeBars(t,e){const s=`${t}:${e}`;this._subscriptions.delete(s)}_createConnection(){this._ws&&(this._intentionalClose=!0,this._ws.close(),this._ws=null,this._intentionalClose=!1);const t=new WebSocket(this._options.url);t.onopen=()=>{this._connected=!0,this._reconnectAttempts=0},t.onmessage=t=>{let e;try{e=JSON.parse(t.data)}catch{return}const s=this._options.parseMessage(e);if(!s)return;const n=`${s.symbol}:${s.resolution}`,i=this._subscriptions.get(n);i&&i(s.bar)},t.onclose=()=>{this._connected=!1,this._ws=null,!this._intentionalClose&&this._options.reconnect&&this._scheduleReconnect()},t.onerror=()=>{},this._ws=t}_scheduleReconnect(){this._clearReconnectTimer();const{maxReconnectAttempts:t,reconnectDelay:e,maxReconnectDelay:s}=this._options;if(t>0&&this._reconnectAttempts>=t)return;const n=Math.min(e*Math.pow(2,this._reconnectAttempts),s);this._reconnectAttempts++,this._reconnectTimer=setTimeout(()=>{this._reconnectTimer=null,this._createConnection()},n)}_clearReconnectTimer(){null!==this._reconnectTimer&&(clearTimeout(this._reconnectTimer),this._reconnectTimer=null)}},e=class{constructor(t){this._timers=/* @__PURE__ */new Map,this._subscriptions=/* @__PURE__ */new Map,this._fetching=/* @__PURE__ */new Set,this._options=t,this._interval=t.interval??5e3}connect(){}disconnect(){for(const t of this._timers.values())clearInterval(t);this._timers.clear(),this._subscriptions.clear()}subscribeBars(t,e,s){const n=`${t}:${e}`;this._subscriptions.set(n,s);const i=this._timers.get(n);i&&clearInterval(i);const c=setInterval(async()=>{if(!this._fetching.has(n)){this._fetching.add(n);try{const s=await this._options.fetchBar(t,e),i=this._subscriptions.get(n);s&&i&&i(s)}finally{this._fetching.delete(n)}}},this._interval);this._timers.set(n,c)}unsubscribeBars(t,e){const s=`${t}:${e}`,n=this._timers.get(s);n&&(clearInterval(n),this._timers.delete(s)),this._subscriptions.delete(s)}},s=class{constructor(){this._buffer=/* @__PURE__ */new Map,this._flushCallbacks=/* @__PURE__ */new Map,this._rafId=null}register(t,e){this._flushCallbacks.set(t,e)}unregister(t){this._flushCallbacks.delete(t),this._buffer.delete(t),0===this._flushCallbacks.size&&this._stopLoop()}push(t,e){this._buffer.set(t,e),null===this._rafId&&this._flushCallbacks.size>0&&this._startLoop()}_startLoop(){const t=()=>{if(0===this._buffer.size)return void(this._rafId=null);const e=this._buffer;this._buffer=/* @__PURE__ */new Map;for(const[t,s]of e){const e=this._flushCallbacks.get(t);e&&e(s)}this._rafId=requestAnimationFrame(t)};this._rafId=requestAnimationFrame(t)}_stopLoop(){null!==this._rafId&&(cancelAnimationFrame(this._rafId),this._rafId=null),this._buffer.clear()}};function n(t){if("object"!=typeof t||null===t)return null;const e=t;if("string"!=typeof e.symbol||"string"!=typeof e.resolution)return null;const s=e.bar??e;if("number"!=typeof s.time)return null;const n=s;return{symbol:e.symbol,resolution:e.resolution,bar:{time:n.time,open:n.open??0,high:n.high??0,low:n.low??0,close:n.close??0,volume:n.volume??0}}}export{e as PollingAdapter,s as TickBuffer,t as WebSocketAdapter};
|
|
2
|
+
//# sourceMappingURL=index109.js.map
|