@coderyo/renderer-lite 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pane-orchestrator.ts","../src/chart-grid.ts","../src/indicator-panes.ts","../src/pane-resize.ts","../src/time-scale-bus.ts","../src/bar-smooth-animator.ts"],"sourcesContent":["import {\n CandlestickSeries,\n ColorType,\n createChart,\n HistogramSeries,\n LineSeries,\n type CandlestickData,\n type HistogramData,\n type WhitespaceData,\n type IChartApi,\n type ISeriesApi,\n type IPriceLine,\n type MouseEventParams,\n type Time,\n type UTCTimestamp,\n} from 'lightweight-charts';\nimport type { Bar } from '@coderyo/data';\nimport { lodDecimateBars } from '@coderyo/series';\nimport { gridOptions } from './chart-grid.js';\nimport type { IndicatorConfig } from '@coderyo/indicators';\n\nimport {\n IndicatorPaneStack,\n bollOverlayLines,\n emaOverlayLine,\n maOverlayLine,\n volMaOverlayLine,\n} from './indicator-panes.js';\nimport { attachPaneResizer } from './pane-resize.js';\nimport { TimeScaleBus, type ChartVisibleRange } from './time-scale-bus.js';\n\nexport type { ChartVisibleRange };\nimport { BarSmoothAnimator } from './bar-smooth-animator.js';\n\nexport type ScaleMode = 'linear' | 'log';\n\nexport interface CrosshairPayload {\n time: number;\n price: number | null;\n ohlcv: { o: number; h: number; l: number; c: number; v?: number } | null;\n}\n\nexport interface PinePlotLine {\n title: string;\n color?: string;\n values: (number | null)[];\n}\n\nexport interface PaneOrchestratorOptions {\n container: HTMLElement;\n indicatorRoot?: HTMLElement;\n theme?: 'dark' | 'light';\n scaleMode?: ScaleMode;\n maxRenderPoints?: number;\n /** Show chart grid lines (default false). */\n showGrid?: boolean;\n /** null = no MA overlays and no MACD/RSI/KDJ panes. */\n indicatorConfig?: IndicatorConfig | null;\n /** Pine-lite plot lines on main chart (when pineEnabled). */\n pinePlots?: PinePlotLine[] | null;\n /** Animate last candle + price line toward new OHLC (~150ms). */\n smoothPriceUpdate?: boolean;\n smoothPriceDurationMs?: number;\n}\n\nfunction toUtcSeconds(tMs: number): UTCTimestamp {\n return Math.floor(tMs / 1000) as UTCTimestamp;\n}\n\nfunction barToCandle(b: Bar): CandlestickData {\n return { time: toUtcSeconds(b.t), open: b.o, high: b.h, low: b.l, close: b.c };\n}\n\nfunction barToVolume(b: Bar): HistogramData<UTCTimestamp> {\n return { time: toUtcSeconds(b.t), value: b.v ?? 0 };\n}\n\nexport class PaneOrchestrator {\n readonly bus = new TimeScaleBus();\n private readonly mainChart: IChartApi;\n private readonly volumeChart: IChartApi;\n private readonly mainSeries: ISeriesApi<'Candlestick'>;\n private readonly volumeSeries: ISeriesApi<'Histogram'>;\n private readonly maSeries: ISeriesApi<'Line'>;\n private readonly emaSeries: ISeriesApi<'Line'>;\n private readonly bollUpper: ISeriesApi<'Line'>;\n private readonly bollMiddle: ISeriesApi<'Line'>;\n private readonly bollLower: ISeriesApi<'Line'>;\n private readonly volMaSeries: ISeriesApi<'Line'>;\n private readonly indicatorRoot?: HTMLElement;\n private indicators: IndicatorPaneStack | null;\n private pinePlotSeries: ISeriesApi<'Line'>[] = [];\n private pinePlots: PinePlotLine[] | null = null;\n private overlayCanvas: HTMLCanvasElement | null = null;\n private dark = true;\n private showGrid = false;\n private readonly maxRenderPoints: number;\n private barByTime = new Map<number, Bar>();\n private barTimesOrdered: number[] = [];\n private didInitialFit = false;\n private skipNextInitialFit = false;\n private indicatorConfig: IndicatorConfig | null = null;\n private priceLine: IPriceLine | null = null;\n private barAnimator: BarSmoothAnimator | null = null;\n private smoothPriceDurationMs = 150;\n\n constructor(opts: PaneOrchestratorOptions) {\n this.maxRenderPoints = opts.maxRenderPoints ?? 4000;\n this.dark = opts.theme !== 'light';\n this.showGrid = opts.showGrid ?? false;\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n\n const mainEl = document.createElement('div');\n mainEl.style.cssText = 'flex:7;min-height:120px;width:100%;position:relative;';\n const volEl = document.createElement('div');\n volEl.style.cssText = 'flex:2;min-height:64px;width:100%;position:relative;';\n\n opts.container.style.cssText =\n 'display:flex;flex-direction:column;height:100%;width:100%;min-height:240px;overflow:hidden;';\n opts.container.append(mainEl, volEl);\n attachPaneResizer(mainEl, volEl, { storageKey: 'tradview:pane:main-volume' });\n\n this.mainChart = createChart(mainEl, { layout, grid, autoSize: true });\n this.volumeChart = createChart(volEl, {\n layout,\n grid,\n autoSize: true,\n rightPriceScale: { scaleMargins: { top: 0.8, bottom: 0 } },\n });\n\n if (opts.scaleMode === 'log') {\n this.mainChart.priceScale('right').applyOptions({ mode: 1 });\n }\n\n this.mainSeries = this.mainChart.addSeries(CandlestickSeries, {\n upColor: '#26a69a',\n downColor: '#ef5350',\n borderVisible: false,\n wickUpColor: '#26a69a',\n wickDownColor: '#ef5350',\n });\n this.maSeries = this.mainChart.addSeries(LineSeries, {\n color: '#f0b429',\n lineWidth: 1,\n title: 'MA',\n });\n this.emaSeries = this.mainChart.addSeries(LineSeries, {\n color: '#7ee787',\n lineWidth: 1,\n title: 'EMA',\n visible: false,\n });\n this.bollUpper = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e',\n lineWidth: 1,\n title: 'BOLL↑',\n visible: false,\n });\n this.bollMiddle = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e88',\n lineWidth: 1,\n lineStyle: 2,\n title: 'BOLL',\n visible: false,\n });\n this.bollLower = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e',\n lineWidth: 1,\n title: 'BOLL↓',\n visible: false,\n });\n this.volumeSeries = this.volumeChart.addSeries(HistogramSeries, {\n color: '#26a69a55',\n priceFormat: { type: 'volume' },\n });\n this.volMaSeries = this.volumeChart.addSeries(LineSeries, {\n color: '#58a6ff',\n lineWidth: 1,\n title: 'VolMA5',\n });\n\n this.bus.register(this.mainChart);\n this.bus.register(this.volumeChart);\n\n this.indicatorRoot = opts.indicatorRoot;\n this.indicatorConfig = opts.indicatorConfig ?? null;\n this.pinePlots = opts.pinePlots ?? null;\n this.indicators = this.createIndicatorStack();\n\n this.initOverlay(mainEl);\n this.setSmoothPriceUpdate(opts.smoothPriceUpdate ?? false, opts.smoothPriceDurationMs);\n }\n\n setSmoothPriceUpdate(enabled: boolean, durationMs = 150): void {\n this.smoothPriceDurationMs = durationMs;\n if (enabled) {\n if (!this.barAnimator) {\n this.barAnimator = new BarSmoothAnimator(durationMs, (bar) => this.applyLastBarToSeries(bar));\n } else {\n this.barAnimator.setDuration(durationMs);\n }\n return;\n }\n this.barAnimator?.cancel();\n this.barAnimator = null;\n if (this.priceLine) {\n this.mainSeries.removePriceLine(this.priceLine);\n this.priceLine = null;\n }\n }\n\n /** Update the last candle (and price line); optional smooth interpolation. */\n updateLastBar(target: Bar, opts?: { smooth?: boolean; durationMs?: number }): void {\n const prev = this.barByTime.get(target.t);\n const smooth = opts?.smooth ?? !!this.barAnimator;\n const duration = opts?.durationMs ?? this.smoothPriceDurationMs;\n if (smooth && this.barAnimator) {\n this.barAnimator.setDuration(duration);\n this.barAnimator.animateTo(target, prev ?? target);\n return;\n }\n this.barAnimator?.cancel();\n this.applyLastBarToSeries(target);\n }\n\n private applyLastBarToSeries(bar: Bar): void {\n this.barByTime.set(bar.t, bar);\n this.mainSeries.update(barToCandle(bar));\n this.volumeSeries.update(barToVolume(bar));\n this.ensurePriceLine(bar.c);\n if (this.indicatorConfig) {\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.applyMainOverlays(bars);\n this.indicators?.setBars(bars);\n }\n }\n\n private ensurePriceLine(price: number): void {\n if (!this.priceLine) {\n this.priceLine = this.mainSeries.createPriceLine({\n price,\n color: '#58a6ff',\n lineWidth: 1,\n lineStyle: 2,\n axisLabelVisible: true,\n title: '',\n });\n } else {\n this.priceLine.applyOptions({ price });\n }\n }\n\n setTheme(theme: 'dark' | 'light'): void {\n this.dark = theme === 'dark';\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.mainChart.applyOptions({ layout, grid });\n this.volumeChart.applyOptions({ layout, grid });\n this.indicators?.setTheme(theme);\n }\n\n setIndicatorConfig(config: IndicatorConfig | null): void {\n this.indicatorConfig = config;\n if (!config) {\n this.indicators = null;\n this.maSeries.setData([]);\n this.emaSeries.setData([]);\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n this.volMaSeries.setData([]);\n this.emaSeries.applyOptions({ visible: false });\n this.bollUpper.applyOptions({ visible: false });\n this.bollMiddle.applyOptions({ visible: false });\n this.bollLower.applyOptions({ visible: false });\n return;\n }\n if (!this.indicators) this.indicators = this.createIndicatorStack();\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.indicators?.setConfig(config);\n if (bars.length > 0) {\n this.applyMainOverlays(bars);\n this.indicators?.setBars(bars);\n }\n }\n\n setPinePlots(plots: PinePlotLine[] | null): void {\n this.pinePlots = plots;\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.syncPinePlotSeries(bars);\n }\n\n private applyMainOverlays(bars: Bar[]): void {\n const cfg = this.indicatorConfig;\n if (!cfg) return;\n this.maSeries.applyOptions({ title: `MA${cfg.maPeriod}` });\n this.maSeries.setData(maOverlayLine(bars, cfg.maPeriod, cfg.source));\n this.volMaSeries.setData(volMaOverlayLine(bars, cfg.volMaPeriod));\n\n if (cfg.showEma) {\n this.emaSeries.applyOptions({ visible: true, title: `EMA${cfg.emaPeriod}` });\n this.emaSeries.setData(emaOverlayLine(bars, cfg.emaPeriod, cfg.source));\n } else {\n this.emaSeries.applyOptions({ visible: false });\n this.emaSeries.setData([]);\n }\n\n if (cfg.showBoll) {\n const bands = bollOverlayLines(bars, cfg.bollPeriod, cfg.bollMult, cfg.source);\n this.bollUpper.applyOptions({ visible: true });\n this.bollMiddle.applyOptions({ visible: true });\n this.bollLower.applyOptions({ visible: true });\n this.bollUpper.setData(bands.upper);\n this.bollMiddle.setData(bands.middle);\n this.bollLower.setData(bands.lower);\n } else {\n this.bollUpper.applyOptions({ visible: false });\n this.bollMiddle.applyOptions({ visible: false });\n this.bollLower.applyOptions({ visible: false });\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n }\n this.syncPinePlotSeries(bars);\n }\n\n private syncPinePlotSeries(bars: Bar[]): void {\n for (const s of this.pinePlotSeries) this.mainChart.removeSeries(s);\n this.pinePlotSeries = [];\n if (!this.pinePlots?.length || bars.length === 0) return;\n\n const palette = ['#58a6ff', '#d2a8ff', '#ff7b72', '#ffa657'];\n for (let i = 0; i < this.pinePlots.length; i++) {\n const plot = this.pinePlots[i]!;\n const series = this.mainChart.addSeries(LineSeries, {\n color: plot.color ?? palette[i % palette.length]!,\n lineWidth: 1,\n title: plot.title,\n });\n const out: { time: UTCTimestamp; value: number }[] = [];\n for (let j = 0; j < bars.length; j++) {\n const v = plot.values[j];\n if (v == null) continue;\n out.push({ time: toUtcSeconds(bars[j]!.t), value: v });\n }\n series.setData(out);\n this.pinePlotSeries.push(series);\n }\n }\n\n setShowGrid(show: boolean): void {\n this.showGrid = show;\n const grid = gridOptions(show, this.dark);\n this.mainChart.applyOptions({ grid });\n this.volumeChart.applyOptions({ grid });\n this.indicators?.setShowGrid(show);\n }\n\n setBars(bars: Bar[], gaps?: number[]): void {\n const renderBars = lodDecimateBars(bars, this.maxRenderPoints);\n this.barByTime = new Map(renderBars.map((b) => [b.t, b]));\n this.barTimesOrdered = renderBars.map((b) => b.t);\n\n const gapSet = new Set(gaps ?? []);\n const seenTimes = new Set<number>();\n type CandlePoint = CandlestickData | WhitespaceData<UTCTimestamp>;\n const candles: CandlePoint[] = [];\n const vols: HistogramData<UTCTimestamp>[] = [];\n\n for (let i = 0; i < renderBars.length; i++) {\n const b = renderBars[i]!;\n const time = toUtcSeconds(b.t);\n if (seenTimes.has(time)) continue;\n seenTimes.add(time);\n if (gapSet.has(b.t)) {\n candles.push({ time });\n }\n candles.push(barToCandle(b));\n vols.push(barToVolume(b));\n }\n\n this.mainSeries.setData(candles);\n this.volumeSeries.setData(vols);\n if (this.indicatorConfig) {\n this.applyMainOverlays(renderBars);\n this.indicators?.setBars(renderBars);\n } else {\n this.maSeries.setData([]);\n this.emaSeries.setData([]);\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n this.volMaSeries.setData([]);\n this.syncPinePlotSeries(renderBars);\n }\n\n if (renderBars.length > 0) {\n this.syncChartSize();\n if (!this.didInitialFit && !this.skipNextInitialFit) {\n this.mainChart.timeScale().fitContent();\n this.volumeChart.timeScale().fitContent();\n this.indicators?.fitContent();\n this.didInitialFit = true;\n }\n this.skipNextInitialFit = false;\n }\n }\n\n subscribeCrosshair(listener: (payload: CrosshairPayload | null) => void): () => void {\n const handler = (param: MouseEventParams<Time>) => {\n if (param.time == null || !param.point) {\n listener(null);\n return;\n }\n const tMs = typeof param.time === 'number' ? param.time * 1000 : null;\n if (tMs == null) {\n listener(null);\n return;\n }\n const price = this.mainSeries.coordinateToPrice(param.point.y) ?? null;\n const bar = this.barByTime.get(tMs) ?? this.findNearestBar(tMs);\n listener({\n time: tMs,\n price,\n ohlcv: bar\n ? { o: bar.o, h: bar.h, l: bar.l, c: bar.c, v: bar.v }\n : null,\n });\n };\n this.mainChart.subscribeCrosshairMove(handler);\n return () => this.mainChart.unsubscribeCrosshairMove(handler);\n }\n\n private findNearestBar(tMs: number): Bar | null {\n let best: Bar | null = null;\n let bestDt = Infinity;\n for (const b of this.barByTime.values()) {\n const dt = Math.abs(b.t - tMs);\n if (dt < bestDt) {\n bestDt = dt;\n best = b;\n }\n }\n return bestDt < 120_000 ? best : null;\n }\n\n private createIndicatorStack(): IndicatorPaneStack | null {\n if (!this.indicatorRoot || !this.indicatorConfig) return null;\n return new IndicatorPaneStack(this.indicatorRoot, this.bus, {\n theme: this.dark ? 'dark' : 'light',\n showGrid: this.showGrid,\n config: this.indicatorConfig,\n });\n }\n\n resetViewState(): void {\n this.didInitialFit = false;\n this.skipNextInitialFit = false;\n this.bus.visibleFromMs = 0;\n this.bus.visibleToMs = 0;\n }\n\n /** Skip the next automatic fitContent after setBars (used by reloadHistory). */\n preserveViewportOnNextSetBars(): void {\n this.skipNextInitialFit = true;\n this.didInitialFit = true;\n }\n\n getVisibleRange(): ChartVisibleRange | null {\n return this.bus.getVisibleRange();\n }\n\n getBarSpace(): number {\n return this.bus.getBarSpacing();\n }\n\n setBarSpace(px: number): void {\n this.bus.setBarSpacing(px);\n }\n\n setVisibleRange(range: ChartVisibleRange): void {\n this.bus.setVisibleTimeRange(range);\n this.didInitialFit = true;\n }\n\n scrollToTimestamp(tsMs: number, animationMs?: number): void {\n const time = toUtcSeconds(tsMs);\n const idx = this.mainChart.timeScale().timeToIndex(time, true);\n if (idx == null) {\n const nearest = this.findNearestBar(tsMs);\n if (nearest == null) return;\n const i = this.barTimesOrdered.indexOf(nearest.t);\n if (i < 0) return;\n this.bus.scrollToLogicalPosition(i, (animationMs ?? 0) > 0);\n return;\n }\n this.bus.scrollToLogicalPosition(idx as number, (animationMs ?? 0) > 0);\n }\n\n /** Clear series while symbol/interval data reloads (avoids overlapping candles). */\n clearBars(): void {\n this.barAnimator?.cancel();\n this.barByTime = new Map();\n this.barTimesOrdered = [];\n this.mainSeries.setData([]);\n this.maSeries.setData([]);\n this.volumeSeries.setData([]);\n this.volMaSeries.setData([]);\n this.indicators?.clearBars();\n }\n\n fitContent(): void {\n this.mainChart.timeScale().fitContent();\n this.volumeChart.timeScale().fitContent();\n this.indicators?.fitContent();\n this.didInitialFit = true;\n }\n\n scrollToRealtime(): void {\n this.mainChart.timeScale().scrollToRealTime();\n this.volumeChart.timeScale().scrollToRealTime();\n this.indicators?.scrollToRealtime();\n }\n\n setLogScale(enabled: boolean): void {\n this.mainChart.priceScale('right').applyOptions({ mode: enabled ? 1 : 0 });\n }\n\n resize(): void {\n this.syncChartSize();\n this.syncOverlaySize();\n this.indicators?.resize();\n }\n\n getOverlayCanvas(): HTMLCanvasElement | null {\n return this.overlayCanvas;\n }\n\n timeToX(tMs: number): number | null {\n const coord = this.mainChart.timeScale().timeToCoordinate(toUtcSeconds(tMs));\n if (coord == null) return null;\n return coord * devicePixelRatio;\n }\n\n priceToY(price: number): number | null {\n const coord = this.mainSeries.priceToCoordinate(price);\n if (coord == null) return null;\n return coord * devicePixelRatio;\n }\n\n xToTime(x: number): number | null {\n const t = this.mainChart.timeScale().coordinateToTime(x / devicePixelRatio);\n if (t == null) return null;\n return Number(t) * 1000;\n }\n\n yToPrice(y: number): number | null {\n const p = this.mainSeries.coordinateToPrice(y / devicePixelRatio);\n return p ?? null;\n }\n\n destroy(): void {\n this.barAnimator?.cancel();\n if (this.priceLine) {\n this.mainSeries.removePriceLine(this.priceLine);\n this.priceLine = null;\n }\n this.mainChart.remove();\n this.volumeChart.remove();\n this.indicators?.destroy();\n this.overlayCanvas?.remove();\n }\n\n private initOverlay(parent: HTMLElement) {\n const canvas = document.createElement('canvas');\n canvas.style.cssText =\n 'position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10;';\n parent.style.position = 'relative';\n parent.appendChild(canvas);\n this.overlayCanvas = canvas;\n this.syncOverlaySize();\n this.bus.subscribeTransform(() => {\n this.syncOverlaySize();\n });\n }\n\n /** Let drawing overlay receive clicks; cursor mode keeps pan/zoom on LWC. */\n setOverlayPointerEvents(mode: 'auto' | 'none'): void {\n if (this.overlayCanvas) this.overlayCanvas.style.pointerEvents = mode;\n }\n\n private syncOverlaySize() {\n if (!this.overlayCanvas?.parentElement) return;\n const parent = this.overlayCanvas.parentElement;\n if (parent.lastElementChild !== this.overlayCanvas) {\n parent.appendChild(this.overlayCanvas);\n }\n const rect = parent.getBoundingClientRect();\n this.overlayCanvas.width = rect.width * devicePixelRatio;\n this.overlayCanvas.height = rect.height * devicePixelRatio;\n }\n\n private syncChartSize(): void {\n const mainEl = this.mainChart.chartElement().parentElement;\n const volEl = this.volumeChart.chartElement().parentElement;\n if (mainEl) {\n const w = mainEl.clientWidth;\n const h = mainEl.clientHeight;\n if (w > 0 && h > 0) this.mainChart.resize(w, h);\n }\n if (volEl) {\n const w = volEl.clientWidth;\n const h = volEl.clientHeight;\n if (w > 0 && h > 0) this.volumeChart.resize(w, h);\n }\n }\n\n private layoutForTheme(dark: boolean) {\n return {\n background: { type: ColorType.Solid, color: dark ? '#0d1117' : '#ffffff' },\n textColor: dark ? '#e6edf3' : '#24292f',\n };\n }\n}","/** LWC grid line options — default off per product spec. */\nexport function gridOptions(showGrid: boolean, dark: boolean) {\n const color = dark ? '#21262d' : '#d0d7de';\n return {\n vertLines: { visible: showGrid, color },\n horzLines: { visible: showGrid, color },\n };\n}","import {\n ColorType,\n createChart,\n HistogramSeries,\n LineSeries,\n type HistogramData,\n type IChartApi,\n type ISeriesApi,\n type LineData,\n type UTCTimestamp,\n} from 'lightweight-charts';\nimport type { Bar } from '@coderyo/data';\nimport {\n type IndicatorConfig,\n DEFAULT_INDICATOR_CONFIG,\n boll,\n kdj,\n macd,\n rsi,\n sma,\n ema,\n} from '@coderyo/indicators';\nimport { gridOptions } from './chart-grid.js';\nimport type { TimeScaleBus } from './time-scale-bus.js';\n\nexport interface IndicatorPaneStackOptions {\n theme?: 'dark' | 'light';\n showGrid?: boolean;\n config?: IndicatorConfig;\n}\n\nfunction barsForSource(bars: Bar[], source: IndicatorConfig['source']): Bar[] {\n if (source === 'close') return bars;\n return bars.map((b) => ({ ...b, c: (b.h + b.l + b.c) / 3 }));\n}\n\nfunction toUtcSeconds(tMs: number): UTCTimestamp {\n return Math.floor(tMs / 1000) as UTCTimestamp;\n}\n\nfunction lineData(bars: Bar[], values: (number | null)[]): LineData<UTCTimestamp>[] {\n const out: LineData<UTCTimestamp>[] = [];\n for (let i = 0; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n out.push({ time: toUtcSeconds(bars[i]!.t), value: v });\n }\n return out;\n}\n\nfunction histData(bars: Bar[], values: (number | null)[]): HistogramData<UTCTimestamp>[] {\n const out: HistogramData<UTCTimestamp>[] = [];\n for (let i = 0; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n out.push({\n time: toUtcSeconds(bars[i]!.t),\n value: v,\n color: v >= 0 ? '#26a69a88' : '#ef535088',\n });\n }\n return out;\n}\n\nexport class IndicatorPaneStack {\n private readonly macdChart: IChartApi;\n private readonly rsiChart: IChartApi;\n private readonly kdjChart: IChartApi;\n private readonly macdLine: ISeriesApi<'Line'>;\n private readonly macdSignal: ISeriesApi<'Line'>;\n private readonly macdHist: ISeriesApi<'Histogram'>;\n private readonly rsiLine: ISeriesApi<'Line'>;\n private readonly kdjK: ISeriesApi<'Line'>;\n private readonly kdjD: ISeriesApi<'Line'>;\n private readonly kdjJ: ISeriesApi<'Line'>;\n private dark = true;\n private showGrid = false;\n private config: IndicatorConfig = DEFAULT_INDICATOR_CONFIG;\n private readonly macdWrap: HTMLElement;\n private readonly rsiWrap: HTMLElement;\n private readonly kdjWrap: HTMLElement;\n\n constructor(\n private readonly root: HTMLElement,\n bus: TimeScaleBus,\n opts: IndicatorPaneStackOptions | 'dark' | 'light' = 'dark',\n ) {\n const o = typeof opts === 'string' ? { theme: opts, showGrid: false } : opts;\n this.dark = o.theme !== 'light';\n this.showGrid = o.showGrid ?? false;\n this.config = o.config ?? DEFAULT_INDICATOR_CONFIG;\n this.root.style.display = 'flex';\n this.root.style.flexDirection = 'column';\n this.root.style.flex = '2';\n this.root.style.minHeight = '0';\n this.root.style.overflow = 'hidden';\n\n const macdPane = this.createPaneWrap('MACD');\n const rsiPane = this.createPaneWrap('RSI');\n const kdjPane = this.createPaneWrap('KDJ');\n this.macdWrap = macdPane.wrap;\n this.rsiWrap = rsiPane.wrap;\n this.kdjWrap = kdjPane.wrap;\n this.root.append(macdPane.wrap, rsiPane.wrap, kdjPane.wrap);\n this.applyPaneVisibility();\n\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.macdChart = createChart(macdPane.el, { layout, grid, autoSize: true });\n this.rsiChart = createChart(rsiPane.el, { layout, grid, autoSize: true });\n this.kdjChart = createChart(kdjPane.el, { layout, grid, autoSize: true });\n\n for (const c of [this.macdChart, this.rsiChart, this.kdjChart]) bus.register(c);\n\n this.macdLine = this.macdChart.addSeries(LineSeries, { color: '#2962ff', lineWidth: 1 });\n this.macdSignal = this.macdChart.addSeries(LineSeries, { color: '#ff9800', lineWidth: 1 });\n this.macdHist = this.macdChart.addSeries(HistogramSeries, {\n priceFormat: { type: 'price', precision: 4, minMove: 0.0001 },\n });\n this.rsiLine = this.rsiChart.addSeries(LineSeries, { color: '#ab47bc', lineWidth: 1 });\n this.kdjK = this.kdjChart.addSeries(LineSeries, { color: '#42a5f5', lineWidth: 1 });\n this.kdjD = this.kdjChart.addSeries(LineSeries, { color: '#ffa726', lineWidth: 1 });\n this.kdjJ = this.kdjChart.addSeries(LineSeries, { color: '#ef5350', lineWidth: 1 });\n }\n\n setConfig(config: IndicatorConfig): void {\n this.config = config;\n this.applyPaneVisibility();\n }\n\n private applyPaneVisibility(): void {\n this.macdWrap.style.display = this.config.showMacd ? '' : 'none';\n this.rsiWrap.style.display = this.config.showRsi ? '' : 'none';\n this.kdjWrap.style.display = this.config.showKdj ? '' : 'none';\n }\n\n clearBars(): void {\n this.macdLine.setData([]);\n this.macdSignal.setData([]);\n this.macdHist.setData([]);\n this.rsiLine.setData([]);\n this.kdjK.setData([]);\n this.kdjD.setData([]);\n this.kdjJ.setData([]);\n }\n\n setBars(bars: Bar[]): void {\n if (bars.length === 0) return;\n const src = barsForSource(bars, this.config.source);\n const m = macd(src, this.config.macdFast, this.config.macdSlow, this.config.macdSignal);\n this.macdLine.setData(lineData(bars, m.macd));\n this.macdSignal.setData(lineData(bars, m.signal));\n this.macdHist.setData(histData(bars, m.histogram));\n\n this.rsiLine.setData(lineData(bars, rsi(src, this.config.rsiPeriod)));\n\n const k = kdj(src, this.config.kdjPeriod, this.config.kdjKSmooth, this.config.kdjDSmooth);\n this.kdjK.setData(lineData(bars, k.k));\n this.kdjD.setData(lineData(bars, k.d));\n this.kdjJ.setData(lineData(bars, k.j));\n\n this.macdChart.timeScale().fitContent();\n this.rsiChart.timeScale().fitContent();\n this.kdjChart.timeScale().fitContent();\n this.resize();\n }\n\n setTheme(theme: 'dark' | 'light'): void {\n this.dark = theme === 'dark';\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.macdChart.applyOptions({ layout, grid });\n this.rsiChart.applyOptions({ layout, grid });\n this.kdjChart.applyOptions({ layout, grid });\n }\n\n setShowGrid(show: boolean): void {\n this.showGrid = show;\n const grid = gridOptions(show, this.dark);\n this.macdChart.applyOptions({ grid });\n this.rsiChart.applyOptions({ grid });\n this.kdjChart.applyOptions({ grid });\n }\n\n fitContent(): void {\n this.macdChart.timeScale().fitContent();\n this.rsiChart.timeScale().fitContent();\n this.kdjChart.timeScale().fitContent();\n }\n\n scrollToRealtime(): void {\n this.macdChart.timeScale().scrollToRealTime();\n this.rsiChart.timeScale().scrollToRealTime();\n this.kdjChart.timeScale().scrollToRealTime();\n }\n\n resize(): void {\n for (const { chart, el } of [\n { chart: this.macdChart, el: this.macdChart.chartElement().parentElement },\n { chart: this.rsiChart, el: this.rsiChart.chartElement().parentElement },\n { chart: this.kdjChart, el: this.kdjChart.chartElement().parentElement },\n ]) {\n if (!el) continue;\n const w = el.clientWidth;\n const h = el.clientHeight;\n if (w > 0 && h > 0) chart.resize(w, h);\n }\n }\n\n destroy(): void {\n this.macdChart.remove();\n this.rsiChart.remove();\n this.kdjChart.remove();\n this.root.replaceChildren();\n }\n\n private createPaneWrap(label: string): { wrap: HTMLElement; el: HTMLElement } {\n const wrap = document.createElement('div');\n wrap.style.cssText =\n 'flex:1;min-height:72px;width:100%;position:relative;border-top:1px solid #30363d;';\n const tag = document.createElement('span');\n tag.textContent = label;\n tag.style.cssText =\n 'position:absolute;left:6px;top:4px;z-index:2;font-size:10px;color:#8b949e;pointer-events:none;';\n const el = document.createElement('div');\n el.style.cssText = 'width:100%;height:100%;';\n wrap.append(tag, el);\n return { wrap, el };\n }\n\n private layoutForTheme(dark: boolean) {\n return {\n background: { type: ColorType.Solid, color: dark ? '#0d1117' : '#ffffff' },\n textColor: dark ? '#e6edf3' : '#24292f',\n };\n }\n}\n\nexport function maOverlayLine(\n bars: Bar[],\n period = 20,\n source: IndicatorConfig['source'] = 'close',\n): LineData<UTCTimestamp>[] {\n const src = barsForSource(bars, source);\n return lineData(bars, sma(src, period));\n}\n\nexport function volMaOverlayLine(bars: Bar[], period = 5): LineData<UTCTimestamp>[] {\n const volBars = bars.map((b) => ({ ...b, c: b.v ?? 0 }));\n return lineData(bars, sma(volBars, period, 'close'));\n}\n\nexport function emaOverlayLine(\n bars: Bar[],\n period: number,\n source: IndicatorConfig['source'] = 'close',\n): LineData<UTCTimestamp>[] {\n const src = barsForSource(bars, source);\n return lineData(bars, ema(src, period));\n}\n\nexport function bollOverlayLines(\n bars: Bar[],\n period: number,\n mult: number,\n source: IndicatorConfig['source'] = 'close',\n): {\n upper: LineData<UTCTimestamp>[];\n middle: LineData<UTCTimestamp>[];\n lower: LineData<UTCTimestamp>[];\n} {\n const src = barsForSource(bars, source);\n const bands = boll(src, period, mult);\n return {\n upper: lineData(bars, bands.upper),\n middle: lineData(bars, bands.middle),\n lower: lineData(bars, bands.lower),\n };\n}","export function attachPaneResizer(\n topPane: HTMLElement,\n bottomPane: HTMLElement,\n opts: { minTopPx?: number; minBottomPx?: number; storageKey?: string } = {},\n): () => void {\n const minTop = opts.minTopPx ?? 120;\n const minBottom = opts.minBottomPx ?? 60;\n const parent = topPane.parentElement;\n if (!parent) return () => {};\n\n const handle = document.createElement('div');\n handle.style.cssText =\n 'height:4px;cursor:row-resize;background:#30363d;flex-shrink:0;touch-action:none;';\n bottomPane.insertAdjacentElement('beforebegin', handle);\n\n const saved = opts.storageKey ? localStorage.getItem(opts.storageKey) : null;\n if (saved) {\n const ratio = Number(saved);\n if (Number.isFinite(ratio) && ratio > 0 && ratio < 1) {\n topPane.style.flex = `${ratio * 10}`;\n bottomPane.style.flex = `${(1 - ratio) * 10}`;\n }\n }\n\n let dragging = false;\n\n const onMove = (clientY: number) => {\n const rect = parent.getBoundingClientRect();\n const y = clientY - rect.top;\n const ratio = Math.min(0.85, Math.max(0.15, y / rect.height));\n const topPx = ratio * rect.height;\n const bottomPx = rect.height - topPx - handle.offsetHeight;\n if (topPx < minTop || bottomPx < minBottom) return;\n topPane.style.flex = `${ratio * 10}`;\n bottomPane.style.flex = `${(1 - ratio) * 10}`;\n if (opts.storageKey) localStorage.setItem(opts.storageKey, String(ratio));\n };\n\n const stop = () => {\n dragging = false;\n document.body.style.cursor = '';\n };\n\n handle.addEventListener('pointerdown', (e) => {\n dragging = true;\n handle.setPointerCapture(e.pointerId);\n document.body.style.cursor = 'row-resize';\n });\n handle.addEventListener('pointermove', (e) => {\n if (dragging) onMove(e.clientY);\n });\n handle.addEventListener('pointerup', stop);\n handle.addEventListener('pointercancel', stop);\n\n return () => handle.remove();\n}","import type { IChartApi, LogicalRange, UTCTimestamp } from 'lightweight-charts';\n\nexport interface ChartVisibleRange {\n fromMs: number;\n toMs: number;\n}\n\nexport interface TransformState {\n visibleFromMs: number;\n visibleToMs: number;\n width: number;\n height: number;\n}\n\ntype TransformListener = (state: TransformState) => void;\n\n/** Sync visible logical range across multiple LWC panes (§10.4.1). */\nexport class TimeScaleBus {\n private charts: IChartApi[] = [];\n private listeners = new Set<TransformListener>();\n private syncing = false;\n visibleFromMs = 0;\n visibleToMs = 0;\n\n register(chart: IChartApi): void {\n if (this.charts.includes(chart)) return;\n this.charts.push(chart);\n chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {\n if (this.syncing || !range) return;\n const tr = chart.timeScale().getVisibleRange();\n if (tr && typeof tr.from === 'number' && typeof tr.to === 'number') {\n this.visibleFromMs = tr.from * 1000;\n this.visibleToMs = tr.to * 1000;\n }\n this.syncFrom(chart, range);\n });\n }\n\n subscribeTransform(listener: TransformListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n setBarsTimeRange(fromMs: number, toMs: number): void {\n this.visibleFromMs = fromMs;\n this.visibleToMs = toMs;\n this.emit();\n }\n\n getVisibleRange(): ChartVisibleRange | null {\n if (this.visibleToMs <= this.visibleFromMs) return null;\n return { fromMs: this.visibleFromMs, toMs: this.visibleToMs };\n }\n\n getBarSpacing(): number {\n const chart = this.charts[0];\n return chart ? chart.timeScale().options().barSpacing : 6;\n }\n\n setBarSpacing(spacing: number): void {\n if (!Number.isFinite(spacing) || spacing <= 0) return;\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().applyOptions({ barSpacing: spacing });\n }\n this.syncing = false;\n this.emit();\n }\n\n setVisibleTimeRange(range: ChartVisibleRange): void {\n const from = Math.floor(range.fromMs / 1000) as UTCTimestamp;\n const to = Math.floor(range.toMs / 1000) as UTCTimestamp;\n if (to <= from) return;\n this.visibleFromMs = range.fromMs;\n this.visibleToMs = range.toMs;\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().setVisibleRange({ from, to });\n }\n this.syncing = false;\n this.emit();\n }\n\n scrollToLogicalPosition(position: number, animated = false): void {\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().scrollToPosition(position, animated);\n }\n this.syncing = false;\n this.emit();\n }\n\n private syncFrom(source: IChartApi, range: LogicalRange) {\n this.syncing = true;\n for (const chart of this.charts) {\n if (chart !== source) {\n chart.timeScale().setVisibleLogicalRange(range);\n }\n }\n this.syncing = false;\n this.emit();\n }\n\n private emit(): void {\n const state: TransformState = {\n visibleFromMs: this.visibleFromMs,\n visibleToMs: this.visibleToMs,\n width: 0,\n height: 0,\n };\n for (const l of this.listeners) l(state);\n }\n}","import type { Bar } from '@coderyo/data';\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nfunction easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\n}\n\n/** Interpolate last candle OHLC toward target over `durationMs` (interrupts on new target). */\nexport class BarSmoothAnimator {\n private raf = 0;\n private start = 0;\n private from: Bar | null = null;\n private to: Bar | null = null;\n\n constructor(\n private durationMs: number,\n private readonly onFrame: (bar: Bar) => void,\n ) {}\n\n setDuration(ms: number): void {\n this.durationMs = ms;\n }\n\n animateTo(target: Bar, from?: Bar): void {\n if (this.raf) cancelAnimationFrame(this.raf);\n const base = from ?? this.to ?? target;\n this.from = { ...base, t: target.t };\n this.to = { ...target };\n this.start = performance.now();\n\n const step = (now: number) => {\n const raw = Math.min(1, (now - this.start) / this.durationMs);\n const p = easeOutCubic(raw);\n const f = this.from!;\n const t = this.to!;\n const frame: Bar = {\n t: t.t,\n o: lerp(f.o, t.o, p),\n h: lerp(f.h, t.h, p),\n l: lerp(f.l, t.l, p),\n c: lerp(f.c, t.c, p),\n v: t.v,\n };\n this.onFrame(frame);\n if (raw < 1) {\n this.raf = requestAnimationFrame(step);\n } else {\n this.raf = 0;\n this.onFrame(t);\n }\n };\n this.raf = requestAnimationFrame(step);\n }\n\n cancel(): void {\n if (this.raf) cancelAnimationFrame(this.raf);\n this.raf = 0;\n }\n}"],"mappings":"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","names":["ColorType","createChart","HistogramSeries","LineSeries","toUtcSeconds","createChart","LineSeries","HistogramSeries","ColorType"]}
1
+ {"version":3,"sources":["../src/pane-orchestrator.ts","../src/chart-grid.ts","../src/indicator-panes.ts","../src/pane-resize.ts","../src/time-scale-bus.ts","../src/time-scale-bus-registry.ts","../src/viewport-fit.ts","../src/bar-smooth-animator.ts"],"sourcesContent":["import {\n CandlestickSeries,\n ColorType,\n createChart,\n HistogramSeries,\n LineSeries,\n type CandlestickData,\n type HistogramData,\n type WhitespaceData,\n type IChartApi,\n type ISeriesApi,\n type IPriceLine,\n type MouseEventParams,\n type Time,\n type UTCTimestamp,\n} from 'lightweight-charts';\nimport { intervalMs, type Bar, type Interval } from '@coderyo/data';\nimport { lodDecimateBars } from '@coderyo/series';\nimport { gridOptions } from './chart-grid.js';\nimport {\n DEFAULT_INDICATOR_CONFIG,\n hasVisibleIndicatorPanes,\n type IndicatorConfig,\n} from '@coderyo/indicators';\n\nimport {\n IndicatorPaneStack,\n bollOverlayLines,\n emaOverlayLine,\n maOverlayLine,\n volMaOverlayLine,\n} from './indicator-panes.js';\nimport { attachPaneResizer } from './pane-resize.js';\nimport { type ChartVisibleRange } from './time-scale-bus.js';\nimport {\n type PaneSyncGroupPatch,\n type PaneSyncKey,\n TimeScaleBusRegistry,\n} from './time-scale-bus-registry.js';\nimport { resolveBarSpacingForInterval } from './viewport-fit.js';\n\nexport type { ChartVisibleRange };\nimport { BarSmoothAnimator } from './bar-smooth-animator.js';\n\nexport type ScaleMode = 'linear' | 'log';\n\nexport interface CrosshairPayload {\n time: number;\n price: number | null;\n ohlcv: { o: number; h: number; l: number; c: number; v?: number } | null;\n}\n\nexport interface PinePlotLine {\n title: string;\n color?: string;\n values: (number | null)[];\n}\n\nexport type ChartPaneId = 'main' | 'volume' | 'indicator';\n\nexport function isLayeredPaneMount(opts: Pick<PaneOrchestratorOptions, 'volumeMount'>): boolean {\n return !!opts.volumeMount;\n}\n\nexport function shouldResizeChartPane(\n focus: Set<ChartPaneId> | null,\n pane: ChartPaneId,\n): boolean {\n if (!focus) return true;\n return focus.has(pane);\n}\n\nexport interface PaneOrchestratorOptions {\n /** Main candlestick mount (required). */\n container: HTMLElement;\n /**\n * P2: separate volume layer host; when set, no flex column in container.\n * Mount order: create empty `chartMain` + `chartVolume` nodes first, pass to compositor widgets,\n * then `createChart(chartMain, { volumeMount: chartVolume })` so LWC mounts after layer frames apply.\n */\n volumeMount?: HTMLElement;\n indicatorRoot?: HTMLElement;\n theme?: 'dark' | 'light';\n scaleMode?: ScaleMode;\n maxRenderPoints?: number;\n /** Show chart grid lines (default false). */\n showGrid?: boolean;\n /** null = no MA overlays and no MACD/RSI/KDJ panes. */\n indicatorConfig?: IndicatorConfig | null;\n /** Pine-lite plot lines on main chart (when pineEnabled). */\n pinePlots?: PinePlotLine[] | null;\n /** Animate last candle + price line toward new OHLC (~150ms). */\n smoothPriceUpdate?: boolean;\n smoothPriceDurationMs?: number;\n onIndicatorConfigChange?: (config: IndicatorConfig) => void;\n /** When true (default), set bar spacing on interval reload — does not change visible bar count. */\n autoBarSpacingOnInterval?: boolean;\n barSpacingByInterval?: Partial<Record<Interval, number>>;\n /**\n * When false, do not listen for `tradview:pane-resize` (ChartController owns that path).\n * @default true for standalone orchestrator use; ChartController passes false.\n */\n listenPaneResizeEvents?: boolean;\n}\n\nfunction toUtcSeconds(tMs: number): UTCTimestamp {\n return Math.floor(tMs / 1000) as UTCTimestamp;\n}\n\nfunction barToCandle(b: Bar): CandlestickData {\n return { time: toUtcSeconds(b.t), open: b.o, high: b.h, low: b.l, close: b.c };\n}\n\nfunction barToVolume(b: Bar): HistogramData<UTCTimestamp> {\n return { time: toUtcSeconds(b.t), value: b.v ?? 0 };\n}\n\nexport class PaneOrchestrator {\n readonly busRegistry = new TimeScaleBusRegistry();\n /** Active sync group bus (last-focused pane); used by ChartController viewport APIs. */\n get bus() {\n return this.busRegistry.activeBus;\n }\n private readonly layeredPanes: boolean;\n private readonly mainEl: HTMLElement;\n private readonly volWrap: HTMLElement;\n private detachMainVolResizer: () => void = () => {};\n private resizeFocusPanes: Set<ChartPaneId> | null = null;\n private readonly listenPaneResizeEvents: boolean;\n private readonly mainChart: IChartApi;\n private readonly volumeChart: IChartApi;\n private readonly mainSeries: ISeriesApi<'Candlestick'>;\n private readonly volumeSeries: ISeriesApi<'Histogram'>;\n private readonly maSeries: ISeriesApi<'Line'>;\n private readonly emaSeries: ISeriesApi<'Line'>;\n private readonly bollUpper: ISeriesApi<'Line'>;\n private readonly bollMiddle: ISeriesApi<'Line'>;\n private readonly bollLower: ISeriesApi<'Line'>;\n private readonly volMaSeries: ISeriesApi<'Line'>;\n private readonly indicatorRoot?: HTMLElement;\n private indicators: IndicatorPaneStack | null;\n private pinePlotSeries: ISeriesApi<'Line'>[] = [];\n private pinePlots: PinePlotLine[] | null = null;\n private overlayCanvas: HTMLCanvasElement | null = null;\n private dark = true;\n private showGrid = false;\n private readonly maxRenderPoints: number;\n private barByTime = new Map<number, Bar>();\n private barTimesOrdered: number[] = [];\n private didInitialFit = false;\n private skipNextInitialFit = false;\n /** setBars ran before the pane had layout size; refit on first real resize. */\n private pendingViewportFit = false;\n private pendingViewportBars: Bar[] | null = null;\n private indicatorConfig: IndicatorConfig | null = null;\n private onIndicatorConfigChange?: (config: IndicatorConfig) => void;\n private currentInterval: Interval = '1h';\n private autoBarSpacingOnInterval = true;\n private barSpacingByInterval?: Partial<Record<Interval, number>>;\n private priceLine: IPriceLine | null = null;\n private barAnimator: BarSmoothAnimator | null = null;\n private smoothPriceDurationMs = 150;\n\n constructor(opts: PaneOrchestratorOptions) {\n this.maxRenderPoints = opts.maxRenderPoints ?? 4000;\n this.listenPaneResizeEvents = opts.listenPaneResizeEvents !== false;\n this.dark = opts.theme !== 'light';\n this.showGrid = opts.showGrid ?? false;\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n\n this.layeredPanes = !!opts.volumeMount;\n const volEl = document.createElement('div');\n volEl.style.cssText = 'width:100%;height:100%;min-height:0;position:relative;';\n\n if (this.layeredPanes) {\n this.mainEl = opts.container;\n this.mainEl.style.cssText =\n 'width:100%;height:100%;min-height:80px;position:relative;overflow:hidden;';\n this.volWrap = opts.volumeMount!;\n this.volWrap.dataset.paneId = 'volume';\n this.volWrap.className = 'tv-volume-pane tv-volume-pane--layered';\n this.volWrap.replaceChildren();\n this.volWrap.style.cssText =\n 'width:100%;height:100%;min-height:48px;position:relative;overflow:hidden;box-sizing:border-box;';\n const volTag = document.createElement('span');\n volTag.textContent = 'Volume';\n volTag.style.cssText =\n 'position:absolute;left:6px;top:4px;z-index:2;font-size:10px;color:#8b949e;pointer-events:none;';\n const volClose = document.createElement('button');\n volClose.type = 'button';\n volClose.textContent = '×';\n volClose.title = '關閉成交量';\n volClose.setAttribute('aria-label', 'Close volume');\n volClose.style.cssText =\n 'position:absolute;right:6px;top:4px;z-index:3;width:22px;height:22px;padding:0;border:1px solid #30363d;border-radius:4px;background:#21262d;color:#8b949e;cursor:pointer;font-size:14px;line-height:1;';\n volClose.onclick = () => this.closeVolumePane();\n this.volWrap.append(volTag, volClose, volEl);\n } else {\n this.mainEl = document.createElement('div');\n this.mainEl.style.cssText = 'flex:7;min-height:120px;width:100%;position:relative;';\n volEl.style.cssText = 'flex:1;min-height:0;width:100%;height:100%;position:relative;';\n\n this.volWrap = document.createElement('div');\n this.volWrap.dataset.paneId = 'volume';\n this.volWrap.className = 'tv-volume-pane';\n this.volWrap.style.cssText =\n 'flex:2;min-height:48px;width:100%;position:relative;display:flex;flex-direction:column;border-top:1px solid #30363d;';\n const volTag = document.createElement('span');\n volTag.textContent = 'Volume';\n volTag.style.cssText =\n 'position:absolute;left:6px;top:4px;z-index:2;font-size:10px;color:#8b949e;pointer-events:none;';\n const volClose = document.createElement('button');\n volClose.type = 'button';\n volClose.textContent = '×';\n volClose.title = '關閉成交量';\n volClose.setAttribute('aria-label', 'Close volume');\n volClose.style.cssText =\n 'position:absolute;right:6px;top:4px;z-index:3;width:22px;height:22px;padding:0;border:1px solid #30363d;border-radius:4px;background:#21262d;color:#8b949e;cursor:pointer;font-size:14px;line-height:1;';\n volClose.onclick = () => this.closeVolumePane();\n this.volWrap.append(volTag, volClose, volEl);\n\n opts.container.style.cssText =\n 'display:flex;flex-direction:column;height:100%;width:100%;min-height:200px;overflow:hidden;';\n opts.container.append(this.mainEl, this.volWrap);\n this.rebuildMainVolumeResizer();\n }\n\n this.mainChart = createChart(this.mainEl, { layout, grid, autoSize: true });\n this.volumeChart = createChart(volEl, {\n layout,\n grid,\n autoSize: true,\n rightPriceScale: { scaleMargins: { top: 0.8, bottom: 0 } },\n });\n\n if (opts.scaleMode === 'log') {\n this.mainChart.priceScale('right').applyOptions({ mode: 1 });\n }\n\n this.mainSeries = this.mainChart.addSeries(CandlestickSeries, {\n upColor: '#26a69a',\n downColor: '#ef5350',\n borderVisible: false,\n wickUpColor: '#26a69a',\n wickDownColor: '#ef5350',\n });\n this.maSeries = this.mainChart.addSeries(LineSeries, {\n color: '#f0b429',\n lineWidth: 1,\n title: 'MA',\n });\n this.emaSeries = this.mainChart.addSeries(LineSeries, {\n color: '#7ee787',\n lineWidth: 1,\n title: 'EMA',\n visible: false,\n });\n this.bollUpper = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e',\n lineWidth: 1,\n title: 'BOLL↑',\n visible: false,\n });\n this.bollMiddle = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e88',\n lineWidth: 1,\n lineStyle: 2,\n title: 'BOLL',\n visible: false,\n });\n this.bollLower = this.mainChart.addSeries(LineSeries, {\n color: '#8b949e',\n lineWidth: 1,\n title: 'BOLL↓',\n visible: false,\n });\n this.volumeSeries = this.volumeChart.addSeries(HistogramSeries, {\n color: '#26a69a55',\n priceFormat: { type: 'volume' },\n });\n this.volMaSeries = this.volumeChart.addSeries(LineSeries, {\n color: '#58a6ff',\n lineWidth: 1,\n title: 'VolMA5',\n });\n\n this.busRegistry.getBusForPane('main').register(this.mainChart);\n this.busRegistry.getBusForPane('volume').register(this.volumeChart);\n\n this.indicatorRoot = opts.indicatorRoot;\n this.indicatorConfig = opts.indicatorConfig ?? null;\n this.onIndicatorConfigChange = opts.onIndicatorConfigChange;\n this.autoBarSpacingOnInterval = opts.autoBarSpacingOnInterval ?? true;\n this.barSpacingByInterval = opts.barSpacingByInterval;\n this.pinePlots = opts.pinePlots ?? null;\n this.indicators = this.createIndicatorStack();\n\n this.initOverlay(this.mainEl);\n this.setSmoothPriceUpdate(opts.smoothPriceUpdate ?? false, opts.smoothPriceDurationMs);\n this.applyVolumeVisibility();\n if (opts.listenPaneResizeEvents !== false) {\n window.addEventListener('tradview:pane-resize', this.onPaneResize);\n }\n }\n\n private readonly onPaneResize = () => {\n this.resize();\n };\n\n setSmoothPriceUpdate(enabled: boolean, durationMs = 150): void {\n this.smoothPriceDurationMs = durationMs;\n if (enabled) {\n if (!this.barAnimator) {\n this.barAnimator = new BarSmoothAnimator(durationMs, (bar) => this.applyLastBarToSeries(bar));\n } else {\n this.barAnimator.setDuration(durationMs);\n }\n return;\n }\n this.barAnimator?.cancel();\n this.barAnimator = null;\n if (this.priceLine) {\n this.mainSeries.removePriceLine(this.priceLine);\n this.priceLine = null;\n }\n }\n\n /** Update the last candle (and price line); optional smooth interpolation. */\n updateLastBar(target: Bar, opts?: { smooth?: boolean; durationMs?: number }): void {\n const prev = this.barByTime.get(target.t);\n const smooth = opts?.smooth ?? !!this.barAnimator;\n const duration = opts?.durationMs ?? this.smoothPriceDurationMs;\n if (smooth && this.barAnimator) {\n this.barAnimator.setDuration(duration);\n this.barAnimator.animateTo(target, prev ?? target);\n return;\n }\n this.barAnimator?.cancel();\n this.applyLastBarToSeries(target);\n }\n\n private applyLastBarToSeries(bar: Bar): void {\n this.barByTime.set(bar.t, bar);\n this.mainSeries.update(barToCandle(bar));\n if (this.isVolumeVisible()) {\n this.volumeSeries.update(barToVolume(bar));\n }\n this.ensurePriceLine(bar.c);\n if (this.indicatorConfig) {\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.applyMainOverlays(bars);\n if (hasVisibleIndicatorPanes(this.indicatorConfig)) {\n this.indicators?.setBars(bars);\n }\n }\n }\n\n private ensurePriceLine(price: number): void {\n if (!this.priceLine) {\n this.priceLine = this.mainSeries.createPriceLine({\n price,\n color: '#58a6ff',\n lineWidth: 1,\n lineStyle: 2,\n axisLabelVisible: true,\n title: '',\n });\n } else {\n this.priceLine.applyOptions({ price });\n }\n }\n\n setIntervalContext(interval: Interval): void {\n this.currentInterval = interval;\n }\n\n setTheme(theme: 'dark' | 'light'): void {\n this.dark = theme === 'dark';\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.mainChart.applyOptions({ layout, grid });\n this.volumeChart.applyOptions({ layout, grid });\n this.indicators?.setTheme(theme);\n }\n\n setIndicatorConfig(config: IndicatorConfig | null): void {\n this.indicatorConfig = config;\n if (!config) {\n this.teardownIndicatorStack();\n this.maSeries.setData([]);\n this.emaSeries.setData([]);\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n this.volMaSeries.setData([]);\n this.volumeSeries.setData([]);\n this.emaSeries.applyOptions({ visible: false });\n this.bollUpper.applyOptions({ visible: false });\n this.bollMiddle.applyOptions({ visible: false });\n this.bollLower.applyOptions({ visible: false });\n this.applyVolumeVisibility();\n return;\n }\n if (!this.indicators) this.indicators = this.createIndicatorStack();\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.indicators?.setConfig(config);\n if (bars.length > 0) {\n this.applyMainOverlays(bars);\n if (hasVisibleIndicatorPanes(config)) {\n this.indicators?.setBars(bars);\n }\n }\n this.applyVolumeVisibility();\n }\n\n private isVolumeVisible(): boolean {\n return this.indicatorConfig?.showVolume ?? true;\n }\n\n private closeVolumePane(): void {\n if (!this.indicatorConfig) {\n this.indicatorConfig = { ...DEFAULT_INDICATOR_CONFIG, showVolume: false };\n } else {\n this.indicatorConfig = { ...this.indicatorConfig, showVolume: false };\n }\n this.applyVolumeVisibility();\n this.onIndicatorConfigChange?.(this.indicatorConfig);\n }\n\n private applyVolumeVisibility(): void {\n const show = this.isVolumeVisible();\n this.volWrap.style.display = show ? '' : 'none';\n this.rebuildMainVolumeResizer();\n if (!show) {\n this.volumeSeries.setData([]);\n this.volMaSeries.setData([]);\n }\n this.syncChartSize();\n }\n\n /** Assign per-pane sync group ids (`''` / omit = independent). Re-registers LWC charts on group change. */\n setPaneSyncGroups(patch: PaneSyncGroupPatch): void {\n const apply = (pane: PaneSyncKey, groupId: string | null | undefined) => {\n const prevKey = this.busRegistry.setPaneSyncGroup(pane, groupId);\n const nextKey = this.busRegistry.getBusKeyForPane(pane);\n if (pane === 'main') {\n this.busRegistry.moveChart(this.mainChart, prevKey, nextKey);\n } else if (pane === 'volume') {\n this.busRegistry.moveChart(this.volumeChart, prevKey, nextKey);\n } else if (this.indicators) {\n for (const chart of this.indicators.getCharts()) {\n this.busRegistry.moveChart(chart, prevKey, nextKey);\n }\n }\n };\n if (patch.main !== undefined) apply('main', patch.main);\n if (patch.volume !== undefined) apply('volume', patch.volume);\n if (patch.indicator !== undefined) apply('indicator', patch.indicator);\n }\n\n setActiveSyncPane(pane: ChartPaneId): void {\n const key: PaneSyncKey =\n pane === 'volume' ? 'volume' : pane === 'indicator' ? 'indicator' : 'main';\n this.busRegistry.setActivePane(key);\n }\n\n /** P2: when set, only these panes get LWC resize (panes in the same sync group still share TimeScaleBus). */\n setResizeFocusPanes(panes: ChartPaneId[] | null): void {\n this.resizeFocusPanes = panes?.length ? new Set(panes) : null;\n this.resize();\n }\n\n /** Current resize focus (null = all panes). @internal — not part of public package API. */\n getResizeFocusPanes(): ChartPaneId[] | null {\n return this.resizeFocusPanes ? [...this.resizeFocusPanes] : null;\n }\n\n private shouldResizePane(pane: ChartPaneId): boolean {\n return shouldResizeChartPane(this.resizeFocusPanes, pane);\n }\n\n private rebuildMainVolumeResizer(): void {\n if (this.layeredPanes) return;\n this.detachMainVolResizer();\n const parent = this.mainEl.parentElement;\n parent\n ?.querySelectorAll(':scope > [data-pane-resizer]')\n .forEach((el) => el.remove());\n\n if (!this.isVolumeVisible()) {\n this.mainEl.style.flex = '1';\n return;\n }\n this.mainEl.style.flex = '';\n this.volWrap.style.flex = '';\n this.detachMainVolResizer = attachPaneResizer(this.mainEl, this.volWrap, {\n storageKey: 'tradview:pane:main-volume',\n minTopPx: 120,\n minBottomPx: 48,\n });\n }\n\n setPinePlots(plots: PinePlotLine[] | null): void {\n this.pinePlots = plots;\n const bars = [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n this.syncPinePlotSeries(bars);\n }\n\n private teardownIndicatorStack(): void {\n this.indicators?.destroy();\n this.indicators = null;\n }\n\n private applyMainOverlays(bars: Bar[]): void {\n const cfg = this.indicatorConfig;\n if (!cfg) return;\n if (cfg.showMa) {\n this.maSeries.applyOptions({ visible: true, title: `MA${cfg.maPeriod}` });\n this.maSeries.setData(maOverlayLine(bars, cfg.maPeriod, cfg.source));\n } else {\n this.maSeries.applyOptions({ visible: false });\n this.maSeries.setData([]);\n }\n if (cfg.showVolMa) {\n this.volMaSeries.applyOptions({ visible: true });\n this.volMaSeries.setData(volMaOverlayLine(bars, cfg.volMaPeriod));\n } else {\n this.volMaSeries.applyOptions({ visible: false });\n this.volMaSeries.setData([]);\n }\n\n if (cfg.showEma) {\n this.emaSeries.applyOptions({ visible: true, title: `EMA${cfg.emaPeriod}` });\n this.emaSeries.setData(emaOverlayLine(bars, cfg.emaPeriod, cfg.source));\n } else {\n this.emaSeries.applyOptions({ visible: false });\n this.emaSeries.setData([]);\n }\n\n if (cfg.showBoll) {\n const bands = bollOverlayLines(bars, cfg.bollPeriod, cfg.bollMult, cfg.source);\n this.bollUpper.applyOptions({ visible: true });\n this.bollMiddle.applyOptions({ visible: true });\n this.bollLower.applyOptions({ visible: true });\n this.bollUpper.setData(bands.upper);\n this.bollMiddle.setData(bands.middle);\n this.bollLower.setData(bands.lower);\n } else {\n this.bollUpper.applyOptions({ visible: false });\n this.bollMiddle.applyOptions({ visible: false });\n this.bollLower.applyOptions({ visible: false });\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n }\n this.syncPinePlotSeries(bars);\n }\n\n private syncPinePlotSeries(bars: Bar[]): void {\n for (const s of this.pinePlotSeries) this.mainChart.removeSeries(s);\n this.pinePlotSeries = [];\n if (!this.pinePlots?.length || bars.length === 0) return;\n\n const palette = ['#58a6ff', '#d2a8ff', '#ff7b72', '#ffa657'];\n for (let i = 0; i < this.pinePlots.length; i++) {\n const plot = this.pinePlots[i]!;\n const series = this.mainChart.addSeries(LineSeries, {\n color: plot.color ?? palette[i % palette.length]!,\n lineWidth: 1,\n title: plot.title,\n });\n const out: { time: UTCTimestamp; value: number }[] = [];\n for (let j = 0; j < bars.length; j++) {\n const v = plot.values[j];\n if (v == null) continue;\n out.push({ time: toUtcSeconds(bars[j]!.t), value: v });\n }\n series.setData(out);\n this.pinePlotSeries.push(series);\n }\n }\n\n setShowGrid(show: boolean): void {\n this.showGrid = show;\n const grid = gridOptions(show, this.dark);\n this.mainChart.applyOptions({ grid });\n this.volumeChart.applyOptions({ grid });\n this.indicators?.setShowGrid(show);\n }\n\n setBars(bars: Bar[], gaps?: number[]): void {\n const renderBars = lodDecimateBars(bars, this.maxRenderPoints);\n this.barByTime = new Map(renderBars.map((b) => [b.t, b]));\n this.barTimesOrdered = renderBars.map((b) => b.t);\n\n const gapSet = new Set(gaps ?? []);\n const seenTimes = new Set<number>();\n type CandlePoint = CandlestickData | WhitespaceData<UTCTimestamp>;\n const candles: CandlePoint[] = [];\n const vols: HistogramData<UTCTimestamp>[] = [];\n\n for (let i = 0; i < renderBars.length; i++) {\n const b = renderBars[i]!;\n const time = toUtcSeconds(b.t);\n if (seenTimes.has(time)) continue;\n seenTimes.add(time);\n if (gapSet.has(b.t)) {\n candles.push({ time });\n }\n candles.push(barToCandle(b));\n vols.push(barToVolume(b));\n }\n\n this.mainSeries.setData(candles);\n if (this.isVolumeVisible()) {\n this.volumeSeries.setData(vols);\n } else {\n this.volumeSeries.setData([]);\n }\n if (this.indicatorConfig) {\n this.applyMainOverlays(renderBars);\n if (hasVisibleIndicatorPanes(this.indicatorConfig)) {\n this.indicators?.setBars(renderBars);\n }\n } else {\n this.maSeries.setData([]);\n this.emaSeries.setData([]);\n this.bollUpper.setData([]);\n this.bollMiddle.setData([]);\n this.bollLower.setData([]);\n this.volMaSeries.setData([]);\n this.syncPinePlotSeries(renderBars);\n }\n\n if (renderBars.length > 0) {\n this.syncChartSize();\n this.tryInitialViewportFit(renderBars);\n this.skipNextInitialFit = false;\n }\n }\n\n private mainPaneHasSize(): boolean {\n const el = this.mainChart.chartElement().parentElement;\n return (el?.clientWidth ?? 0) > 0 && (el?.clientHeight ?? 0) > 0;\n }\n\n private tryInitialViewportFit(renderBars: Bar[]): void {\n if (this.didInitialFit || this.skipNextInitialFit) return;\n if (!this.mainPaneHasSize()) {\n this.pendingViewportFit = true;\n this.pendingViewportBars = renderBars;\n return;\n }\n this.applyViewAfterDataReload(renderBars);\n this.didInitialFit = true;\n this.pendingViewportFit = false;\n this.pendingViewportBars = null;\n }\n\n private flushPendingViewportFit(): void {\n if (!this.pendingViewportFit || this.skipNextInitialFit || this.didInitialFit) return;\n const bars =\n this.pendingViewportBars ??\n [...this.barByTime.values()].sort((a, b) => a.t - b.t);\n if (bars.length === 0 || !this.mainPaneHasSize()) return;\n this.applyViewAfterDataReload(bars);\n this.didInitialFit = true;\n this.pendingViewportFit = false;\n this.pendingViewportBars = null;\n }\n\n subscribeCrosshair(listener: (payload: CrosshairPayload | null) => void): () => void {\n const handler = (param: MouseEventParams<Time>) => {\n if (param.time == null || !param.point) {\n listener(null);\n return;\n }\n const tMs = typeof param.time === 'number' ? param.time * 1000 : null;\n if (tMs == null) {\n listener(null);\n return;\n }\n const price = this.mainSeries.coordinateToPrice(param.point.y) ?? null;\n const bar = this.barByTime.get(tMs) ?? this.findNearestBar(tMs);\n listener({\n time: tMs,\n price,\n ohlcv: bar\n ? { o: bar.o, h: bar.h, l: bar.l, c: bar.c, v: bar.v }\n : null,\n });\n };\n this.mainChart.subscribeCrosshairMove(handler);\n return () => this.mainChart.unsubscribeCrosshairMove(handler);\n }\n\n private findNearestBar(tMs: number): Bar | null {\n let best: Bar | null = null;\n let bestDt = Infinity;\n for (const b of this.barByTime.values()) {\n const dt = Math.abs(b.t - tMs);\n if (dt < bestDt) {\n bestDt = dt;\n best = b;\n }\n }\n return bestDt < 120_000 ? best : null;\n }\n\n private createIndicatorStack(): IndicatorPaneStack | null {\n if (!this.indicatorRoot || !this.indicatorConfig) return null;\n return new IndicatorPaneStack(this.indicatorRoot, this.busRegistry.getBusForPane('indicator'), {\n theme: this.dark ? 'dark' : 'light',\n showGrid: this.showGrid,\n config: this.indicatorConfig,\n onConfigChange: (config) => {\n this.indicatorConfig = config;\n this.onIndicatorConfigChange?.(config);\n },\n });\n }\n\n /** After symbol/interval reload: bar spacing for interval + show integrator-loaded span. */\n applyIntervalBarSpacing(interval?: Interval): void {\n if (!this.autoBarSpacingOnInterval) return;\n const iv = interval ?? this.currentInterval;\n const spacing = resolveBarSpacingForInterval(iv, this.barSpacingByInterval);\n this.busRegistry.forEachBus((_, bus) => bus.setBarSpacing(spacing));\n }\n\n setBarSpacingPolicy(opts: {\n autoBarSpacingOnInterval?: boolean;\n barSpacingByInterval?: Partial<Record<Interval, number>>;\n }): void {\n if (opts.autoBarSpacingOnInterval !== undefined) {\n this.autoBarSpacingOnInterval = opts.autoBarSpacingOnInterval;\n }\n if (opts.barSpacingByInterval !== undefined) {\n this.barSpacingByInterval = opts.barSpacingByInterval;\n }\n }\n\n /** Sync time scale to loaded bars (integrator history); adjust bar spacing only, not bar count. */\n private applyViewAfterDataReload(renderBars: Bar[]): void {\n if (this.autoBarSpacingOnInterval) {\n this.applyIntervalBarSpacing();\n } else {\n this.mainChart.timeScale().fitContent();\n if (this.isVolumeVisible()) this.volumeChart.timeScale().fitContent();\n this.indicators?.fitContent();\n }\n\n if (renderBars.length > 0) {\n const fromMs = renderBars[0]!.t;\n const toMs = renderBars[renderBars.length - 1]!.t + intervalMs(this.currentInterval);\n this.bus.setVisibleTimeRange({ fromMs, toMs });\n }\n this.scrollToRealtime();\n }\n\n resetViewState(): void {\n this.didInitialFit = false;\n this.skipNextInitialFit = false;\n this.pendingViewportFit = false;\n this.pendingViewportBars = null;\n this.busRegistry.forEachBus((_, bus) => {\n bus.visibleFromMs = 0;\n bus.visibleToMs = 0;\n });\n }\n\n /** Skip the next automatic fitContent after setBars (used by reloadHistory). */\n preserveViewportOnNextSetBars(): void {\n this.skipNextInitialFit = true;\n this.didInitialFit = true;\n }\n\n getVisibleRange(): ChartVisibleRange | null {\n return this.bus.getVisibleRange();\n }\n\n getBarSpace(): number {\n return this.bus.getBarSpacing();\n }\n\n setBarSpace(px: number): void {\n this.bus.setBarSpacing(px);\n }\n\n setVisibleRange(range: ChartVisibleRange): void {\n this.bus.setVisibleTimeRange(range);\n this.didInitialFit = true;\n }\n\n scrollToTimestamp(tsMs: number, animationMs?: number): void {\n const time = toUtcSeconds(tsMs);\n const idx = this.mainChart.timeScale().timeToIndex(time, true);\n if (idx == null) {\n const nearest = this.findNearestBar(tsMs);\n if (nearest == null) return;\n const i = this.barTimesOrdered.indexOf(nearest.t);\n if (i < 0) return;\n this.busRegistry.getBusForPane('main').scrollToLogicalPosition(i, (animationMs ?? 0) > 0);\n return;\n }\n this.busRegistry.getBusForPane('main').scrollToLogicalPosition(idx as number, (animationMs ?? 0) > 0);\n }\n\n /** Clear series while symbol/interval data reloads (avoids overlapping candles). */\n clearBars(): void {\n this.barAnimator?.cancel();\n this.barByTime = new Map();\n this.barTimesOrdered = [];\n this.mainSeries.setData([]);\n this.maSeries.setData([]);\n this.volumeSeries.setData([]);\n this.volMaSeries.setData([]);\n this.indicators?.clearBars();\n }\n\n fitContent(): void {\n this.mainChart.timeScale().fitContent();\n if (this.isVolumeVisible()) this.volumeChart.timeScale().fitContent();\n this.indicators?.fitContent();\n this.didInitialFit = true;\n }\n\n scrollToRealtime(): void {\n this.mainChart.timeScale().scrollToRealTime();\n if (this.isVolumeVisible()) this.volumeChart.timeScale().scrollToRealTime();\n this.indicators?.scrollToRealtime();\n }\n\n setLogScale(enabled: boolean): void {\n this.mainChart.priceScale('right').applyOptions({ mode: enabled ? 1 : 0 });\n }\n\n resize(): void {\n this.syncChartSize();\n this.syncOverlaySize();\n if (this.shouldResizePane('indicator')) this.indicators?.resize();\n this.flushPendingViewportFit();\n }\n\n /**\n * Resize every LWC pane once for viewport fit; does **not** change {@link resizeFocusPanes}.\n * @internal Used by ChartController data refresh paths.\n */\n resizeAllPanes(): void {\n this.syncChartSize({ allPanes: true });\n this.syncOverlaySize();\n this.indicators?.resize();\n this.flushPendingViewportFit();\n }\n\n getOverlayCanvas(): HTMLCanvasElement | null {\n return this.overlayCanvas;\n }\n\n timeToX(tMs: number): number | null {\n const coord = this.mainChart.timeScale().timeToCoordinate(toUtcSeconds(tMs));\n if (coord == null) return null;\n return coord * devicePixelRatio;\n }\n\n priceToY(price: number): number | null {\n const coord = this.mainSeries.priceToCoordinate(price);\n if (coord == null) return null;\n return coord * devicePixelRatio;\n }\n\n xToTime(x: number): number | null {\n const t = this.mainChart.timeScale().coordinateToTime(x / devicePixelRatio);\n if (t == null) return null;\n return Number(t) * 1000;\n }\n\n yToPrice(y: number): number | null {\n const p = this.mainSeries.coordinateToPrice(y / devicePixelRatio);\n return p ?? null;\n }\n\n destroy(): void {\n if (this.listenPaneResizeEvents) {\n window.removeEventListener('tradview:pane-resize', this.onPaneResize);\n }\n this.detachMainVolResizer();\n this.barAnimator?.cancel();\n if (this.priceLine) {\n this.mainSeries.removePriceLine(this.priceLine);\n this.priceLine = null;\n }\n this.mainChart.remove();\n this.volumeChart.remove();\n this.indicators?.destroy();\n this.overlayCanvas?.remove();\n }\n\n private initOverlay(parent: HTMLElement) {\n const canvas = document.createElement('canvas');\n canvas.style.cssText =\n 'position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10;';\n parent.style.position = 'relative';\n parent.appendChild(canvas);\n this.overlayCanvas = canvas;\n this.syncOverlaySize();\n this.busRegistry.forEachBus((_, bus) => {\n bus.subscribeTransform(() => {\n this.syncOverlaySize();\n });\n });\n }\n\n /** Let drawing overlay receive clicks; cursor mode keeps pan/zoom on LWC. */\n setOverlayPointerEvents(mode: 'auto' | 'none'): void {\n if (this.overlayCanvas) this.overlayCanvas.style.pointerEvents = mode;\n }\n\n private syncOverlaySize() {\n if (!this.overlayCanvas?.parentElement) return;\n const parent = this.overlayCanvas.parentElement;\n if (parent.lastElementChild !== this.overlayCanvas) {\n parent.appendChild(this.overlayCanvas);\n }\n const rect = parent.getBoundingClientRect();\n this.overlayCanvas.width = rect.width * devicePixelRatio;\n this.overlayCanvas.height = rect.height * devicePixelRatio;\n }\n\n private syncChartSize(opts?: { allPanes?: boolean }): void {\n const all = opts?.allPanes === true;\n const mainEl = this.mainChart.chartElement().parentElement;\n const volEl = this.volumeChart.chartElement().parentElement;\n if (mainEl && (all || this.shouldResizePane('main'))) {\n const w = mainEl.clientWidth;\n const h = mainEl.clientHeight;\n if (w > 0 && h > 0) this.mainChart.resize(w, h);\n }\n if (this.isVolumeVisible() && volEl && (all || this.shouldResizePane('volume'))) {\n const w = volEl.clientWidth;\n const h = volEl.clientHeight;\n if (w > 0 && h > 0) this.volumeChart.resize(w, h);\n }\n }\n\n private layoutForTheme(dark: boolean) {\n return {\n background: { type: ColorType.Solid, color: dark ? '#0d1117' : '#ffffff' },\n textColor: dark ? '#e6edf3' : '#24292f',\n };\n }\n}","/** LWC grid line options — default off per product spec. */\nexport function gridOptions(showGrid: boolean, dark: boolean) {\n const color = dark ? '#21262d' : '#d0d7de';\n return {\n vertLines: { visible: showGrid, color },\n horzLines: { visible: showGrid, color },\n };\n}","import {\n ColorType,\n createChart,\n HistogramSeries,\n LineSeries,\n type HistogramData,\n type IChartApi,\n type ISeriesApi,\n type LineData,\n type UTCTimestamp,\n} from 'lightweight-charts';\nimport type { Bar } from '@coderyo/data';\nimport {\n type IndicatorConfig,\n DEFAULT_INDICATOR_CONFIG,\n hasVisibleIndicatorPanes,\n boll,\n kdj,\n macd,\n rsi,\n sma,\n ema,\n} from '@coderyo/indicators';\nimport { gridOptions } from './chart-grid.js';\nimport { attachPaneResizer } from './pane-resize.js';\nimport type { TimeScaleBus } from './time-scale-bus.js';\n\nexport type IndicatorPaneId = 'macd' | 'rsi' | 'kdj';\n\nexport interface IndicatorPaneStackOptions {\n theme?: 'dark' | 'light';\n showGrid?: boolean;\n config?: IndicatorConfig;\n onConfigChange?: (config: IndicatorConfig) => void;\n}\n\nfunction barsForSource(bars: Bar[], source: IndicatorConfig['source']): Bar[] {\n if (source === 'close') return bars;\n return bars.map((b) => ({ ...b, c: (b.h + b.l + b.c) / 3 }));\n}\n\nfunction toUtcSeconds(tMs: number): UTCTimestamp {\n return Math.floor(tMs / 1000) as UTCTimestamp;\n}\n\n/** PR-21: detect in-place tail updates vs full recompute. */\nexport function detectIndicatorBarMutation(\n prevTimes: number[],\n bars: Bar[],\n): 'full' | 'tail-append' | 'tail-update' {\n if (prevTimes.length === 0 || bars.length < prevTimes.length) return 'full';\n const prefixLen = Math.min(prevTimes.length, bars.length);\n for (let i = 0; i < prefixLen - 1; i++) {\n if (bars[i]!.t !== prevTimes[i]) return 'full';\n }\n if (bars.length === prevTimes.length) {\n return bars.length > 0 && bars[bars.length - 1]!.t === prevTimes[prevTimes.length - 1]\n ? 'tail-update'\n : 'full';\n }\n if (bars.length - prevTimes.length > 8) return 'full';\n for (let i = 0; i < prevTimes.length; i++) {\n if (bars[i]!.t !== prevTimes[i]) return 'full';\n }\n return 'tail-append';\n}\n\nfunction lineData(bars: Bar[], values: (number | null)[]): LineData<UTCTimestamp>[] {\n const out: LineData<UTCTimestamp>[] = [];\n for (let i = 0; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n out.push({ time: toUtcSeconds(bars[i]!.t), value: v });\n }\n return out;\n}\n\nfunction histData(bars: Bar[], values: (number | null)[]): HistogramData<UTCTimestamp>[] {\n const out: HistogramData<UTCTimestamp>[] = [];\n for (let i = 0; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n out.push({\n time: toUtcSeconds(bars[i]!.t),\n value: v,\n color: v >= 0 ? '#26a69a88' : '#ef535088',\n });\n }\n return out;\n}\n\nexport class IndicatorPaneStack {\n private readonly macdChart: IChartApi;\n private readonly rsiChart: IChartApi;\n private readonly kdjChart: IChartApi;\n private readonly macdLine: ISeriesApi<'Line'>;\n private readonly macdSignal: ISeriesApi<'Line'>;\n private readonly macdHist: ISeriesApi<'Histogram'>;\n private readonly rsiLine: ISeriesApi<'Line'>;\n private readonly kdjK: ISeriesApi<'Line'>;\n private readonly kdjD: ISeriesApi<'Line'>;\n private readonly kdjJ: ISeriesApi<'Line'>;\n private dark = true;\n private showGrid = false;\n private config: IndicatorConfig = DEFAULT_INDICATOR_CONFIG;\n private readonly macdWrap: HTMLElement;\n private readonly rsiWrap: HTMLElement;\n private readonly kdjWrap: HTMLElement;\n private readonly detachResizers: Array<() => void> = [];\n private lastBarTimes: number[] = [];\n private onConfigChange?: (config: IndicatorConfig) => void;\n\n constructor(\n private readonly root: HTMLElement,\n bus: TimeScaleBus,\n opts: IndicatorPaneStackOptions | 'dark' | 'light' = 'dark',\n ) {\n const o = typeof opts === 'string' ? { theme: opts, showGrid: false } : opts;\n this.dark = o.theme !== 'light';\n this.showGrid = o.showGrid ?? false;\n this.config = o.config ?? DEFAULT_INDICATOR_CONFIG;\n this.onConfigChange = o.onConfigChange;\n this.root.style.display = 'flex';\n this.root.style.flexDirection = 'column';\n this.root.style.flex = '2';\n this.root.style.minHeight = '0';\n this.root.style.overflow = 'hidden';\n\n const macdPane = this.createPaneWrap('MACD', 'macd');\n const rsiPane = this.createPaneWrap('RSI', 'rsi');\n const kdjPane = this.createPaneWrap('KDJ', 'kdj');\n this.macdWrap = macdPane.wrap;\n this.rsiWrap = rsiPane.wrap;\n this.kdjWrap = kdjPane.wrap;\n\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.macdChart = createChart(macdPane.el, { layout, grid, autoSize: true });\n this.rsiChart = createChart(rsiPane.el, { layout, grid, autoSize: true });\n this.kdjChart = createChart(kdjPane.el, { layout, grid, autoSize: true });\n\n for (const c of [this.macdChart, this.rsiChart, this.kdjChart]) bus.register(c);\n\n this.macdLine = this.macdChart.addSeries(LineSeries, { color: '#2962ff', lineWidth: 1 });\n this.macdSignal = this.macdChart.addSeries(LineSeries, { color: '#ff9800', lineWidth: 1 });\n this.macdHist = this.macdChart.addSeries(HistogramSeries, {\n priceFormat: { type: 'price', precision: 4, minMove: 0.0001 },\n });\n this.rsiLine = this.rsiChart.addSeries(LineSeries, { color: '#ab47bc', lineWidth: 1 });\n this.kdjK = this.kdjChart.addSeries(LineSeries, { color: '#42a5f5', lineWidth: 1 });\n this.kdjD = this.kdjChart.addSeries(LineSeries, { color: '#ffa726', lineWidth: 1 });\n this.kdjJ = this.kdjChart.addSeries(LineSeries, { color: '#ef5350', lineWidth: 1 });\n\n this.applyPaneVisibility();\n }\n\n setConfig(config: IndicatorConfig): void {\n this.config = config;\n this.lastBarTimes = [];\n this.applyPaneVisibility();\n if (!this.config.showMacd && !this.config.showRsi && !this.config.showKdj) {\n this.clearBars();\n }\n }\n\n private closePane(id: IndicatorPaneId): void {\n const patch: Partial<IndicatorConfig> =\n id === 'macd' ? { showMacd: false } : id === 'rsi' ? { showRsi: false } : { showKdj: false };\n this.config = { ...this.config, ...patch };\n this.applyPaneVisibility();\n this.onConfigChange?.(this.config);\n }\n\n private applyPaneVisibility(): void {\n const anyVisible = this.config.showMacd || this.config.showRsi || this.config.showKdj;\n this.root.style.display = anyVisible ? 'flex' : 'none';\n this.rebuildPaneLayout();\n }\n\n /** Rebuild flex children and drag handles only between visible panes. */\n private rebuildPaneLayout(): void {\n for (const detach of this.detachResizers) detach();\n this.detachResizers.length = 0;\n this.root.querySelectorAll('[data-pane-resizer]').forEach((el) => el.remove());\n\n const panes: Array<{ id: IndicatorPaneId; el: HTMLElement }> = [];\n if (this.config.showMacd) panes.push({ id: 'macd', el: this.macdWrap });\n if (this.config.showRsi) panes.push({ id: 'rsi', el: this.rsiWrap });\n if (this.config.showKdj) panes.push({ id: 'kdj', el: this.kdjWrap });\n\n this.root.replaceChildren(...panes.map((p) => p.el));\n\n for (let i = 0; i < panes.length - 1; i++) {\n const top = panes[i]!;\n const bottom = panes[i + 1]!;\n this.detachResizers.push(\n attachPaneResizer(top.el, bottom.el, {\n storageKey: `tradview:pane:${top.id}-${bottom.id}`,\n minTopPx: 72,\n minBottomPx: 72,\n }),\n );\n }\n this.resize();\n }\n\n clearBars(): void {\n this.macdLine.setData([]);\n this.macdSignal.setData([]);\n this.macdHist.setData([]);\n this.rsiLine.setData([]);\n this.kdjK.setData([]);\n this.kdjD.setData([]);\n this.kdjJ.setData([]);\n this.lastBarTimes = [];\n }\n\n private warmupLookback(): number {\n const c = this.config;\n return (\n Math.max(\n c.macdSlow + c.macdSignal,\n c.rsiPeriod,\n c.kdjPeriod + c.kdjKSmooth + c.kdjDSmooth,\n ) + 5\n );\n }\n\n private detectBarMutation(bars: Bar[]): 'full' | 'tail-append' | 'tail-update' {\n return detectIndicatorBarMutation(this.lastBarTimes, bars);\n }\n\n private pushSeriesUpdates(\n series: ISeriesApi<'Line'>,\n bars: Bar[],\n values: (number | null)[],\n fromIndex: number,\n ): void {\n for (let i = fromIndex; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n series.update({ time: toUtcSeconds(bars[i]!.t), value: v });\n }\n }\n\n private pushHistUpdates(\n series: ISeriesApi<'Histogram'>,\n bars: Bar[],\n values: (number | null)[],\n fromIndex: number,\n ): void {\n for (let i = fromIndex; i < bars.length; i++) {\n const v = values[i];\n if (v == null) continue;\n series.update({\n time: toUtcSeconds(bars[i]!.t),\n value: v,\n color: v >= 0 ? '#26a69a88' : '#ef535088',\n });\n }\n }\n\n setBars(bars: Bar[]): void {\n if (bars.length === 0) {\n this.clearBars();\n return;\n }\n\n const needMacd = this.config.showMacd;\n const needRsi = this.config.showRsi;\n const needKdj = this.config.showKdj;\n if (!hasVisibleIndicatorPanes(this.config)) {\n return;\n }\n\n const mutation = this.detectBarMutation(bars);\n this.lastBarTimes = bars.map((b) => b.t);\n const src = barsForSource(bars, this.config.source);\n const m = needMacd\n ? macd(src, this.config.macdFast, this.config.macdSlow, this.config.macdSignal)\n : null;\n const r = needRsi ? rsi(src, this.config.rsiPeriod) : null;\n const k = needKdj\n ? kdj(src, this.config.kdjPeriod, this.config.kdjKSmooth, this.config.kdjDSmooth)\n : null;\n\n if (mutation === 'full') {\n if (needMacd && m) {\n this.macdLine.setData(lineData(bars, m.macd));\n this.macdSignal.setData(lineData(bars, m.signal));\n this.macdHist.setData(histData(bars, m.histogram));\n this.macdChart.timeScale().fitContent();\n }\n if (needRsi && r) {\n this.rsiLine.setData(lineData(bars, r));\n this.rsiChart.timeScale().fitContent();\n }\n if (needKdj && k) {\n this.kdjK.setData(lineData(bars, k.k));\n this.kdjD.setData(lineData(bars, k.d));\n this.kdjJ.setData(lineData(bars, k.j));\n this.kdjChart.timeScale().fitContent();\n }\n } else {\n const from =\n mutation === 'tail-update' ? Math.max(0, bars.length - 1) : Math.max(0, bars.length - this.warmupLookback());\n if (needMacd && m) {\n this.pushSeriesUpdates(this.macdLine, bars, m.macd, from);\n this.pushSeriesUpdates(this.macdSignal, bars, m.signal, from);\n this.pushHistUpdates(this.macdHist, bars, m.histogram, from);\n }\n if (needRsi && r) {\n this.pushSeriesUpdates(this.rsiLine, bars, r, from);\n }\n if (needKdj && k) {\n this.pushSeriesUpdates(this.kdjK, bars, k.k, from);\n this.pushSeriesUpdates(this.kdjD, bars, k.d, from);\n this.pushSeriesUpdates(this.kdjJ, bars, k.j, from);\n }\n }\n\n this.resize();\n }\n\n setTheme(theme: 'dark' | 'light'): void {\n this.dark = theme === 'dark';\n const layout = this.layoutForTheme(this.dark);\n const grid = gridOptions(this.showGrid, this.dark);\n this.macdChart.applyOptions({ layout, grid });\n this.rsiChart.applyOptions({ layout, grid });\n this.kdjChart.applyOptions({ layout, grid });\n }\n\n setShowGrid(show: boolean): void {\n this.showGrid = show;\n const grid = gridOptions(show, this.dark);\n this.macdChart.applyOptions({ grid });\n this.rsiChart.applyOptions({ grid });\n this.kdjChart.applyOptions({ grid });\n }\n\n fitContent(): void {\n this.macdChart.timeScale().fitContent();\n this.rsiChart.timeScale().fitContent();\n this.kdjChart.timeScale().fitContent();\n }\n\n scrollToRealtime(): void {\n this.macdChart.timeScale().scrollToRealTime();\n this.rsiChart.timeScale().scrollToRealTime();\n this.kdjChart.timeScale().scrollToRealTime();\n }\n\n resize(): void {\n const panes: Array<{ show: boolean; chart: IChartApi }> = [\n { show: this.config.showMacd, chart: this.macdChart },\n { show: this.config.showRsi, chart: this.rsiChart },\n { show: this.config.showKdj, chart: this.kdjChart },\n ];\n for (const { show, chart } of panes) {\n if (!show || !chart) continue;\n const el = chart.chartElement()?.parentElement;\n if (!el) continue;\n const w = el.clientWidth;\n const h = el.clientHeight;\n if (w > 0 && h > 0) chart.resize(w, h);\n }\n }\n\n destroy(): void {\n for (const detach of this.detachResizers) detach();\n this.detachResizers.length = 0;\n this.macdChart.remove();\n this.rsiChart.remove();\n this.kdjChart.remove();\n this.root.replaceChildren();\n }\n\n private createPaneWrap(\n label: string,\n paneId: IndicatorPaneId,\n ): { wrap: HTMLElement; el: HTMLElement } {\n const wrap = document.createElement('div');\n wrap.className = `tv-indicator-pane tv-indicator-pane--${paneId}`;\n wrap.dataset.paneId = paneId;\n wrap.style.cssText =\n 'flex:1;min-height:72px;width:100%;position:relative;border-top:1px solid #30363d;';\n const tag = document.createElement('span');\n tag.textContent = label;\n tag.style.cssText =\n 'position:absolute;left:6px;top:4px;z-index:2;font-size:10px;color:#8b949e;pointer-events:none;';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.textContent = '×';\n closeBtn.title = `關閉 ${label}`;\n closeBtn.setAttribute('aria-label', `Close ${label}`);\n closeBtn.style.cssText =\n 'position:absolute;right:6px;top:4px;z-index:3;width:22px;height:22px;padding:0;border:1px solid #30363d;border-radius:4px;background:#21262d;color:#8b949e;cursor:pointer;font-size:14px;line-height:1;';\n closeBtn.onmouseenter = () => {\n closeBtn.style.color = '#e6edf3';\n closeBtn.style.borderColor = '#484f58';\n };\n closeBtn.onmouseleave = () => {\n closeBtn.style.color = '#8b949e';\n closeBtn.style.borderColor = '#30363d';\n };\n closeBtn.onclick = () => this.closePane(paneId);\n const el = document.createElement('div');\n el.style.cssText = 'width:100%;height:100%;';\n wrap.append(tag, closeBtn, el);\n return { wrap, el };\n }\n\n private layoutForTheme(dark: boolean) {\n return {\n background: { type: ColorType.Solid, color: dark ? '#0d1117' : '#ffffff' },\n textColor: dark ? '#e6edf3' : '#24292f',\n };\n }\n\n /** LWC instances for sync-group reassignment. */\n getCharts(): IChartApi[] {\n return [this.macdChart, this.rsiChart, this.kdjChart];\n }\n}\n\nexport function maOverlayLine(\n bars: Bar[],\n period = 20,\n source: IndicatorConfig['source'] = 'close',\n): LineData<UTCTimestamp>[] {\n const src = barsForSource(bars, source);\n return lineData(bars, sma(src, period));\n}\n\nexport function volMaOverlayLine(bars: Bar[], period = 5): LineData<UTCTimestamp>[] {\n const volBars = bars.map((b) => ({ ...b, c: b.v ?? 0 }));\n return lineData(bars, sma(volBars, period, 'close'));\n}\n\nexport function emaOverlayLine(\n bars: Bar[],\n period: number,\n source: IndicatorConfig['source'] = 'close',\n): LineData<UTCTimestamp>[] {\n const src = barsForSource(bars, source);\n return lineData(bars, ema(src, period));\n}\n\nexport function bollOverlayLines(\n bars: Bar[],\n period: number,\n mult: number,\n source: IndicatorConfig['source'] = 'close',\n): {\n upper: LineData<UTCTimestamp>[];\n middle: LineData<UTCTimestamp>[];\n lower: LineData<UTCTimestamp>[];\n} {\n const src = barsForSource(bars, source);\n const bands = boll(src, period, mult);\n return {\n upper: lineData(bars, bands.upper),\n middle: lineData(bars, bands.middle),\n lower: lineData(bars, bands.lower),\n };\n}","export function attachPaneResizer(\n topPane: HTMLElement,\n bottomPane: HTMLElement,\n opts: { minTopPx?: number; minBottomPx?: number; storageKey?: string } = {},\n): () => void {\n const minTop = opts.minTopPx ?? 120;\n const minBottom = opts.minBottomPx ?? 60;\n const parent = topPane.parentElement;\n if (!parent) return () => {};\n\n let dragging = false;\n\n const handle = document.createElement('div');\n handle.dataset.paneResizer = '1';\n handle.style.cssText =\n 'height:6px;cursor:row-resize;background:#30363d;flex-shrink:0;touch-action:none;z-index:5;';\n handle.onmouseenter = () => {\n handle.style.background = '#388bfd';\n };\n handle.onmouseleave = () => {\n if (!dragging) handle.style.background = '#30363d';\n };\n bottomPane.insertAdjacentElement('beforebegin', handle);\n\n const saved = opts.storageKey ? localStorage.getItem(opts.storageKey) : null;\n if (saved) {\n const ratio = Number(saved);\n if (Number.isFinite(ratio) && ratio >= 0.15 && ratio <= 0.85) {\n topPane.style.flex = `${ratio * 10}`;\n bottomPane.style.flex = `${(1 - ratio) * 10}`;\n }\n }\n\n const onMove = (clientY: number) => {\n const rect = parent.getBoundingClientRect();\n const y = clientY - rect.top;\n const ratio = Math.min(0.85, Math.max(0.15, y / rect.height));\n const topPx = ratio * rect.height;\n const bottomPx = rect.height - topPx - handle.offsetHeight;\n if (topPx < minTop || bottomPx < minBottom) return;\n topPane.style.flex = `${ratio * 10}`;\n bottomPane.style.flex = `${(1 - ratio) * 10}`;\n if (opts.storageKey) localStorage.setItem(opts.storageKey, String(ratio));\n };\n\n const stop = () => {\n const wasDragging = dragging;\n dragging = false;\n document.body.style.cursor = '';\n handle.style.background = '#30363d';\n if (wasDragging) window.dispatchEvent(new CustomEvent('tradview:pane-resize'));\n };\n\n handle.addEventListener('pointerdown', (e) => {\n dragging = true;\n handle.setPointerCapture(e.pointerId);\n document.body.style.cursor = 'row-resize';\n });\n handle.addEventListener('pointermove', (e) => {\n if (dragging) {\n onMove(e.clientY);\n window.dispatchEvent(new CustomEvent('tradview:pane-resize'));\n }\n });\n handle.addEventListener('pointerup', stop);\n handle.addEventListener('pointercancel', stop);\n\n return () => handle.remove();\n}","import type { IChartApi, LogicalRange, UTCTimestamp } from 'lightweight-charts';\n\nexport interface ChartVisibleRange {\n fromMs: number;\n toMs: number;\n}\n\nexport interface TransformState {\n visibleFromMs: number;\n visibleToMs: number;\n width: number;\n height: number;\n}\n\ntype TransformListener = (state: TransformState) => void;\n\n/** Sync visible logical range across multiple LWC panes (§10.4.1). */\nexport class TimeScaleBus {\n private charts: IChartApi[] = [];\n private listeners = new Set<TransformListener>();\n private syncing = false;\n visibleFromMs = 0;\n visibleToMs = 0;\n\n register(chart: IChartApi): void {\n if (this.charts.includes(chart)) return;\n this.charts.push(chart);\n chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {\n if (!this.charts.includes(chart)) return;\n if (this.syncing || !range) return;\n const tr = chart.timeScale().getVisibleRange();\n if (tr && typeof tr.from === 'number' && typeof tr.to === 'number') {\n this.visibleFromMs = tr.from * 1000;\n this.visibleToMs = tr.to * 1000;\n }\n this.syncFrom(chart, range);\n });\n }\n\n unregister(chart: IChartApi): void {\n const i = this.charts.indexOf(chart);\n if (i >= 0) this.charts.splice(i, 1);\n }\n\n subscribeTransform(listener: TransformListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n setBarsTimeRange(fromMs: number, toMs: number): void {\n this.visibleFromMs = fromMs;\n this.visibleToMs = toMs;\n this.emit();\n }\n\n getVisibleRange(): ChartVisibleRange | null {\n if (this.visibleToMs <= this.visibleFromMs) return null;\n return { fromMs: this.visibleFromMs, toMs: this.visibleToMs };\n }\n\n getBarSpacing(): number {\n const chart = this.charts[0];\n return chart ? chart.timeScale().options().barSpacing : 6;\n }\n\n setBarSpacing(spacing: number): void {\n if (!Number.isFinite(spacing) || spacing <= 0) return;\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().applyOptions({ barSpacing: spacing });\n }\n this.syncing = false;\n this.emit();\n }\n\n setVisibleTimeRange(range: ChartVisibleRange): void {\n const from = Math.floor(range.fromMs / 1000) as UTCTimestamp;\n const to = Math.floor(range.toMs / 1000) as UTCTimestamp;\n if (to <= from) return;\n this.visibleFromMs = range.fromMs;\n this.visibleToMs = range.toMs;\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().setVisibleRange({ from, to });\n }\n this.syncing = false;\n this.emit();\n }\n\n scrollToLogicalPosition(position: number, animated = false): void {\n this.syncing = true;\n for (const chart of this.charts) {\n chart.timeScale().scrollToPosition(position, animated);\n }\n this.syncing = false;\n this.emit();\n }\n\n private syncFrom(source: IChartApi, range: LogicalRange) {\n this.syncing = true;\n for (const chart of this.charts) {\n if (chart !== source) {\n chart.timeScale().setVisibleLogicalRange(range);\n }\n }\n this.syncing = false;\n this.emit();\n }\n\n private emit(): void {\n const state: TransformState = {\n visibleFromMs: this.visibleFromMs,\n visibleToMs: this.visibleToMs,\n width: 0,\n height: 0,\n };\n for (const l of this.listeners) l(state);\n }\n}","import type { IChartApi } from 'lightweight-charts';\nimport { TimeScaleBus } from './time-scale-bus.js';\n\n/** Trim; empty / whitespace → independent pane (no cross-pane sync). */\nexport function normalizeSyncGroupId(id?: string | null): string | null {\n if (id == null) return null;\n const trimmed = String(id).trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nexport type PaneSyncKey = 'main' | 'volume' | 'indicator';\n\nconst INDEP_PREFIX = '@independent:';\n\nexport function independentBusKey(pane: PaneSyncKey): string {\n return `${INDEP_PREFIX}${pane}`;\n}\n\nexport function resolveBusMapKey(\n groupId: string | null | undefined,\n pane: PaneSyncKey,\n): string {\n const norm = normalizeSyncGroupId(groupId);\n return norm ?? independentBusKey(pane);\n}\n\nexport interface PaneSyncGroupPatch {\n main?: string | null;\n volume?: string | null;\n indicator?: string | null;\n}\n\n/**\n * One {@link TimeScaleBus} per sync group id; empty group id → per-pane independent bus.\n */\nexport class TimeScaleBusRegistry {\n private readonly buses = new Map<string, TimeScaleBus>();\n private readonly paneKeys = new Map<PaneSyncKey, string>();\n private activeKey: string;\n\n constructor() {\n for (const pane of ['main', 'volume', 'indicator'] as const) {\n const key = independentBusKey(pane);\n this.paneKeys.set(pane, key);\n this.getOrCreateBus(key);\n }\n this.activeKey = this.paneKeys.get('main')!;\n }\n\n getOrCreateBus(key: string): TimeScaleBus {\n let bus = this.buses.get(key);\n if (!bus) {\n bus = new TimeScaleBus();\n this.buses.set(key, bus);\n }\n return bus;\n }\n\n getBusKeyForPane(pane: PaneSyncKey): string {\n return this.paneKeys.get(pane)!;\n }\n\n getBusForPane(pane: PaneSyncKey): TimeScaleBus {\n return this.getOrCreateBus(this.getBusKeyForPane(pane));\n }\n\n /** Active bus for IChart viewport APIs (follows last-focused chart pane). */\n get activeBus(): TimeScaleBus {\n return this.getOrCreateBus(this.activeKey);\n }\n\n getActiveBusKey(): string {\n return this.activeKey;\n }\n\n setActivePane(pane: PaneSyncKey): void {\n this.activeKey = this.paneKeys.get(pane)!;\n }\n\n setPaneSyncGroup(pane: PaneSyncKey, groupId: string | null | undefined): string {\n const nextKey = resolveBusMapKey(groupId, pane);\n const prevKey = this.paneKeys.get(pane)!;\n this.paneKeys.set(pane, nextKey);\n this.getOrCreateBus(nextKey);\n if (this.activeKey === prevKey) this.activeKey = nextKey;\n return prevKey;\n }\n\n forEachBus(fn: (key: string, bus: TimeScaleBus) => void): void {\n for (const [key, bus] of this.buses) fn(key, bus);\n }\n\n moveChart(chart: IChartApi, fromKey: string, toKey: string, copyRange = true): void {\n if (fromKey === toKey) return;\n const from = this.getOrCreateBus(fromKey);\n const to = this.getOrCreateBus(toKey);\n const range = copyRange ? from.getVisibleRange() : null;\n from.unregister(chart);\n to.register(chart);\n if (range) to.setVisibleTimeRange(range);\n }\n}","import { intervalMs, type Interval } from '@coderyo/data';\n\n/**\n * Default horizontal bar spacing (px) per interval so candle width feels consistent\n * when the integrator controls how many bars are loaded / visible.\n */\nexport function defaultBarSpacingForInterval(interval: Interval): number {\n const ms = intervalMs(interval);\n if (ms <= 1_000) return 3;\n if (ms <= 5_000) return 4;\n if (ms <= 15_000) return 5;\n if (ms <= 30_000) return 6;\n if (ms <= 60_000) return 7;\n if (ms <= 300_000) return 8;\n if (ms <= 900_000) return 9;\n if (ms <= 3_600_000) return 10;\n if (ms <= 14_400_000) return 11;\n return 12;\n}\n\nexport function resolveBarSpacingForInterval(\n interval: Interval,\n overrides?: Partial<Record<Interval, number>>,\n): number {\n const custom = overrides?.[interval];\n if (custom != null && Number.isFinite(custom) && custom > 0) {\n return Math.min(24, Math.max(2, custom));\n }\n return defaultBarSpacingForInterval(interval);\n}","import type { Bar } from '@coderyo/data';\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nfunction easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\n}\n\n/** Interpolate last candle OHLC toward target over `durationMs` (interrupts on new target). */\nexport class BarSmoothAnimator {\n private raf = 0;\n private start = 0;\n private from: Bar | null = null;\n private to: Bar | null = null;\n\n constructor(\n private durationMs: number,\n private readonly onFrame: (bar: Bar) => void,\n ) {}\n\n setDuration(ms: number): void {\n this.durationMs = ms;\n }\n\n animateTo(target: Bar, from?: Bar): void {\n if (this.raf) cancelAnimationFrame(this.raf);\n const base = from ?? this.to ?? target;\n this.from = { ...base, t: target.t };\n this.to = { ...target };\n this.start = performance.now();\n\n const step = (now: number) => {\n const raw = Math.min(1, (now - this.start) / this.durationMs);\n const p = easeOutCubic(raw);\n const f = this.from!;\n const t = this.to!;\n const frame: Bar = {\n t: t.t,\n o: lerp(f.o, t.o, p),\n h: lerp(f.h, t.h, p),\n l: lerp(f.l, t.l, p),\n c: lerp(f.c, t.c, p),\n v: t.v,\n };\n this.onFrame(frame);\n if (raw < 1) {\n this.raf = requestAnimationFrame(step);\n } else {\n this.raf = 0;\n this.onFrame(t);\n }\n };\n this.raf = requestAnimationFrame(step);\n }\n\n cancel(): void {\n if (this.raf) cancelAnimationFrame(this.raf);\n this.raf = 0;\n }\n}"],"mappings":"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","names":["ColorType","createChart","HistogramSeries","LineSeries","intervalMs","DEFAULT_INDICATOR_CONFIG","hasVisibleIndicatorPanes","toUtcSeconds","createChart","LineSeries","HistogramSeries","hasVisibleIndicatorPanes","DEFAULT_INDICATOR_CONFIG","intervalMs","ColorType"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coderyo/renderer-lite",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -9,18 +9,25 @@
9
9
  "import": "./dist/index.js"
10
10
  }
11
11
  },
12
+ "scripts": {
13
+ "build": "tsup",
14
+ "test": "vitest run --passWithNoTests",
15
+ "lint": "eslint src",
16
+ "typecheck": "tsc --noEmit"
17
+ },
12
18
  "dependencies": {
13
- "lightweight-charts": "^5.0.7",
14
- "@coderyo/series": "1.0.2",
15
- "@coderyo/data": "1.0.2",
16
- "@coderyo/indicators": "1.0.2"
19
+ "@coderyo/data": "workspace:*",
20
+ "@coderyo/indicators": "workspace:*",
21
+ "@coderyo/series": "workspace:*",
22
+ "lightweight-charts": "^5.0.7"
17
23
  },
18
24
  "devDependencies": {
25
+ "@coderyo/eslint-config": "workspace:*",
26
+ "@coderyo/tsconfig": "workspace:*",
27
+ "happy-dom": "^20.9.0",
19
28
  "tsup": "^8.5.0",
20
29
  "typescript": "^5.8.3",
21
- "vitest": "^3.2.4",
22
- "@coderyo/tsconfig": "0.0.0",
23
- "@coderyo/eslint-config": "0.0.0"
30
+ "vitest": "^3.2.4"
24
31
  },
25
32
  "files": [
26
33
  "dist"
@@ -32,11 +39,5 @@
32
39
  },
33
40
  "publishConfig": {
34
41
  "access": "public"
35
- },
36
- "scripts": {
37
- "build": "tsup",
38
- "test": "vitest run --passWithNoTests",
39
- "lint": "eslint src",
40
- "typecheck": "tsc --noEmit"
41
42
  }
42
- }
43
+ }